-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
41 changed files
with
14,035 additions
and
6,559 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button, cn } from "@nextui-org/react"; | ||
|
||
export default function Alert({ | ||
title = "", | ||
content = "", | ||
disclosure, | ||
callback, | ||
placement = "center", | ||
className = "", | ||
color = "primary", | ||
isDismissable = true | ||
}) { | ||
const dismissableProp = { | ||
isDismissable: false, | ||
isKeyboardDismissDisabled: true | ||
} | ||
return ( | ||
<Modal | ||
isOpen={disclosure.isOpen} | ||
onOpenChange={disclosure.onOpenChange} | ||
placement={placement} | ||
scrollBehavior="inside" | ||
className={cn('max-w-[90%]', className)} | ||
hideCloseButton={true} | ||
{...(isDismissable ? {} : dismissableProp)} | ||
> | ||
<ModalContent> | ||
{ | ||
onClose => ( | ||
<> | ||
<ModalHeader className="flex flex-col gap-1">{title}</ModalHeader> | ||
<ModalBody> | ||
<p>{content}</p> | ||
</ModalBody> | ||
<ModalFooter className='justify-center'> | ||
<Button color={color} className='grow' onPress={() => { | ||
onClose(); | ||
if (typeof callback === 'function') callback(); | ||
}}>確認</Button> | ||
</ModalFooter> | ||
</> | ||
) | ||
} | ||
</ModalContent> | ||
</Modal> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { | ||
Modal, | ||
ModalContent, | ||
ModalHeader, | ||
ModalBody, | ||
ModalFooter, | ||
Button, | ||
cn | ||
} from "@nextui-org/react"; | ||
|
||
export default function Confirm({ title, content, disclosure, confirm, placement = "center", className = "" }) { | ||
return ( | ||
<Modal | ||
isOpen={disclosure.isOpen} | ||
onOpenChange={disclosure.onOpenChange} | ||
placement={placement} | ||
scrollBehavior="inside" | ||
hideCloseButton={true} | ||
className={cn('max-w-[90%]', className)} | ||
> | ||
<ModalContent> | ||
{ | ||
onClose => ( | ||
<> | ||
<ModalHeader className="flex flex-col gap-1">{title}</ModalHeader> | ||
<ModalBody>{content}</ModalBody> | ||
<ModalFooter className='justify-center'> | ||
<Button color="default" variant="faded" className='grow' onPress={onClose}>取消</Button> | ||
<Button color="primary" className='grow' onPress={() => { | ||
confirm(); | ||
onClose(); | ||
}}>確認</Button> | ||
</ModalFooter> | ||
</> | ||
) | ||
} | ||
</ModalContent> | ||
</Modal> | ||
) | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,73 +1,108 @@ | ||
import Link from 'next/link'; | ||
import { Card, CardHeader, CardBody, CardFooter, Progress, CheckboxGroup } from "@nextui-org/react"; | ||
import examString from '@/data/exam.json'; | ||
import { WayCheckbox } from '@/components/WayCheckbox'; | ||
import { WayChip } from '@/components/WayChip'; | ||
|
||
import styles from '../styles/CourseCardComponent.module.css'; | ||
|
||
export default function CourseCard({ e, isDemo, theme, setRevelationConfirmShow, setRevelationID }) { | ||
export default function CourseCard({ e, isDemo, setRevelationConfirmShow, setRevelationID, setShareErrorConfirmShow }) { | ||
|
||
function shareOnClick(shareData) { | ||
if (navigator.share) { | ||
navigator.share(shareData); | ||
} else { | ||
setShareErrorConfirmShow(true); | ||
setShareErrorText('您的瀏覽器不支援分享功能,請使用其他瀏覽器。'); | ||
setShareErrorConfirmShow(); | ||
} | ||
} | ||
|
||
return ( | ||
<div className={styles.outer + ' ' + (theme == 'dark' ? styles[theme] : '')} key={'course_' + e.id}> | ||
<div className={styles["title-bar"]}> | ||
<div className={styles.className}>{e.className}</div> | ||
<div className={styles['mini-btn-group']}> | ||
<div title="分享" onClick={isDemo ? () => { } : | ||
() => shareOnClick({ | ||
title: `${e.teacher.join('和')}的${e.className} 的課程評價`, | ||
text: `在每日文大課程評價中,查看${e.teacher.join('和')}的${e.className}。`, | ||
url: 'https://daily-pccu.web.app/course/' + e.id, | ||
}) | ||
}> | ||
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 256 256"><path d="M237.66,106.35l-80-80A8,8,0,0,0,144,32V72.35c-25.94,2.22-54.59,14.92-78.16,34.91-28.38,24.08-46.05,55.11-49.76,87.37a12,12,0,0,0,20.68,9.58h0c11-11.71,50.14-48.74,107.24-52V192a8,8,0,0,0,13.66,5.65l80-80A8,8,0,0,0,237.66,106.35ZM160,172.69V144a8,8,0,0,0-8-8c-28.08,0-55.43,7.33-81.29,21.8a196.17,196.17,0,0,0-36.57,26.52c5.8-23.84,20.42-46.51,42.05-64.86C99.41,99.77,127.75,88,152,88a8,8,0,0,0,8-8V51.32L220.69,112Z"></path></svg> | ||
<Card key={'course_' + e.id}> | ||
<CardHeader className='flex justify-between'> | ||
<div className='font-bold text-lg'>{e.className}</div> | ||
<div className='flex gap-2 cursor-pointer opacity-50'> | ||
<div | ||
title="分享" | ||
onClick={isDemo ? null : | ||
() => shareOnClick({ | ||
title: `${e.teacher.join('和')}的${e.className} 的課程評價`, | ||
text: `在每日文大課程評價中,查看${e.teacher.join('和')}的${e.className}。`, | ||
url: 'https://daily-pccu.web.app/course/' + e.id, | ||
}) | ||
}> | ||
<svg xmlns="http://www.w3.org/2000/svg" width="1.2rem" height="1.2rem" fill='currentColor' viewBox="0 0 256 256"><path d="M237.66,106.35l-80-80A8,8,0,0,0,144,32V72.35c-25.94,2.22-54.59,14.92-78.16,34.91-28.38,24.08-46.05,55.11-49.76,87.37a12,12,0,0,0,20.68,9.58h0c11-11.71,50.14-48.74,107.24-52V192a8,8,0,0,0,13.66,5.65l80-80A8,8,0,0,0,237.66,106.35ZM160,172.69V144a8,8,0,0,0-8-8c-28.08,0-55.43,7.33-81.29,21.8a196.17,196.17,0,0,0-36.57,26.52c5.8-23.84,20.42-46.51,42.05-64.86C99.41,99.77,127.75,88,152,88a8,8,0,0,0,8-8V51.32L220.69,112Z"></path></svg> | ||
</div> | ||
<div title="審查" onClick={isDemo ? () => { } : | ||
() => { | ||
setRevelationConfirmShow(true); | ||
setRevelationID(e.id); | ||
} | ||
}> | ||
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm-8-80V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z"></path></svg> | ||
<div | ||
title="審查" | ||
onClick={isDemo ? null : | ||
() => { | ||
setRevelationConfirmShow(); | ||
setRevelationID(e.id); | ||
} | ||
}> | ||
<svg xmlns="http://www.w3.org/2000/svg" width="1.2rem" height="1.2rem" fill='currentColor' viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm-8-80V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z"></path></svg> | ||
</div> | ||
</div> | ||
</div> | ||
<div className={styles.department}>{e.department}</div> | ||
<div className={styles.teacher}> | ||
{ | ||
e.teacher.map(teacher => { | ||
return ( | ||
<Link href={isDemo ? '#' : `/course/${e.year}/teacher/${teacher}`} key={`course_${e.year}_${teacher}`}>{teacher}</Link> | ||
) | ||
}) | ||
} | ||
</div> | ||
<div className={styles['point-progress']}> | ||
<div className={styles['point-progress-bar']}> | ||
<div className={styles['point-progress-bar-value']} style={{ transform: `scaleX(${e.point / 100})`, backgroundColor: (e.point >= 80 ? 'var(--green)' : (e.point >= 60 ? 'var(--yellow)' : 'var(--red)')) }}></div> | ||
</CardHeader> | ||
<CardBody> | ||
<div>{e.department}</div> | ||
<div className='mt-3 flex gap-2'> | ||
{ | ||
e.teacher.map(teacher => <Link className='underline underline-offset-4' href={isDemo ? '' : `/course/${e.year}/teacher/${teacher}`} key={`course_${e.year}_${teacher}`}>{teacher}</Link>) | ||
} | ||
</div> | ||
<div className={styles['point-progress-text']} style={{ color: (e.point >= 80 ? 'var(--green)' : (e.point >= 60 ? 'var(--yellow)' : 'var(--red)')) }}>{e.point}</div> | ||
</div> | ||
<div className={styles.exam}> | ||
{ | ||
(e.exam != '' ? e.exam.split(',').map((exam, index) => <div key={'exam_' + index}>{exam}</div>) : '') | ||
e.point >= 80 ? | ||
<Progress | ||
label="評分" | ||
value={e.point} | ||
color="success" | ||
showValueLabel={true} | ||
size="sm" | ||
className='mt-3' | ||
classNames={{ value: "text-success" }} | ||
/> | ||
: | ||
e.point >= 60 ? | ||
<Progress | ||
label="評分" | ||
value={e.point} | ||
color="warning" | ||
showValueLabel={true} | ||
size="sm" | ||
className='mt-3' | ||
classNames={{ value: "text-warning" }} | ||
/> | ||
: | ||
<Progress | ||
label="評分" | ||
value={e.point} | ||
color="danger" | ||
showValueLabel={true} | ||
size="sm" | ||
className='mt-3' | ||
classNames={{ value: "text-danger" }} | ||
/> | ||
} | ||
</div> | ||
<div className={styles.way}>授課方式:<br /> | ||
{e.way} | ||
</div> | ||
<div className={styles.evaluation}>課程評語:<br /> | ||
{e.evaluation.replaceAll('\\n', '\n')} | ||
</div> | ||
<div className={styles.date}> | ||
<div className='flex flex-wrap justify-around md:justify-start gap-2 mt-3'> | ||
{ | ||
examString.map((exam, index) => ( | ||
e.exam.includes(exam) ? | ||
<WayChip key={'exam_' + index} value={exam} isDemo={true} isSelected>{exam}</WayChip> | ||
: | ||
<WayChip key={'exam_' + index} value={exam} isDemo={true}>{exam}</WayChip> | ||
)) | ||
} | ||
</div> | ||
<div className=' mt-3'>授課方式:<br /> | ||
{e.way} | ||
</div> | ||
<div className='w-full whitespace-pre-line mt-3'>課程評語:<br /> | ||
{e.evaluation.replaceAll('\\n', '\n')} | ||
</div> | ||
</CardBody> | ||
<CardFooter className='text-sm flex justify-between'> | ||
<div>{e.year}學年</div> | ||
<div>{new Date(e.date).toLocaleDateString()}</div> | ||
</div> | ||
</div> | ||
</CardFooter> | ||
</Card > | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,35 @@ | ||
import Link from 'next/link'; | ||
import styles from '../styles/FooterComponent.module.css'; | ||
import styles from '@/styles/FooterComponent.module.css'; | ||
|
||
export default function Footer() { | ||
export default function Footer({ options = {} }) { | ||
if (options.hidden == true) return null; | ||
return ( | ||
<footer className={styles.foot}> | ||
<div> | ||
<div className={styles['team-info']}> | ||
<img | ||
src='https://firebasestorage.googleapis.com/v0/b/daily-pccu.appspot.com/o/web%2Flogo-bg_w350.webp?alt=media&token=dd0eae47-4373-42d7-8602-afbffd1cfd3a' | ||
alt="每日文大 logo" | ||
srcSet='https://firebasestorage.googleapis.com/v0/b/daily-pccu.appspot.com/o/web%2Flogo-bg.webp?alt=media&token=80013b5d-0cb7-4a2d-9619-67fede77edb7 350w' | ||
/> | ||
<p>每日文大創立於2020年,致力於設計和開發更方便及人性化的移動應用程式,提供更便捷的服務給文大學生,讓每日文大成為文大學生的日常。</p> | ||
</div> | ||
<div className={styles['page-info']}> | ||
<div> | ||
<Link href='/' className={styles['parent-anchor']}>首頁</Link> | ||
<Link href='/#add_friend'>如何加入</Link> | ||
<Link href='/#history'>重大事件</Link> | ||
<footer className='w-full md:h-[80svh] py-[10svh] relative bg-content2'> | ||
<div className='container mx-auto'> | ||
<div className='px-4 flex flex-col md:flex-row w-full'> | ||
<div className='w-full md:w-[20vw]'> | ||
<img | ||
className='w-[200px] h-[200px] object-cover rounded-full border border-[#00000020] shadow-xl' | ||
src='https://firebasestorage.googleapis.com/v0/b/daily-pccu.appspot.com/o/web%2Flogo-bg_w350.webp?alt=media&token=dd0eae47-4373-42d7-8602-afbffd1cfd3a' | ||
alt="每日文大 logo" | ||
srcSet='https://firebasestorage.googleapis.com/v0/b/daily-pccu.appspot.com/o/web%2Flogo-bg.webp?alt=media&token=80013b5d-0cb7-4a2d-9619-67fede77edb7 350w' | ||
/> | ||
<p className='leading-8 mt-[5vh]'>每日文大創立於2020年,致力於設計和開發更方便及人性化的移動應用程式,提供更便捷的服務給文大學生,讓每日文大成為文大學生的日常。</p> | ||
</div> | ||
<div> | ||
<Link href='/course' className={styles['parent-anchor']}>課程評價</Link> | ||
<Link href='/addCourse' target='_blank'>新增課程評價</Link> | ||
<div className={styles.links + ' w-full mx-auto my-4 md:my-[8vh] md:my-0 flex grow justify-center flex-wrap md:px-10'}> | ||
<div className='flex flex-col pt-[10px] w-full md:w-[300px] my-4 md:my-0'> | ||
<Link className='no-underline relative pt-5 text-3xl' href='/'>首頁</Link> | ||
<Link className='no-underline relative pt-5' href='/#add_friend'>如何加入</Link> | ||
<Link className='no-underline relative pt-5' href='/#history'>重大事件</Link> | ||
</div> | ||
<div className='flex flex-col pt-[10px] w-full md:w-[300px] my-4 md:my-0'> | ||
<Link className='no-underline relative pt-5 text-3xl' href='/course'>課程評價</Link> | ||
<Link className='no-underline relative pt-5' href='/addCourse' target='_blank'>新增課程評價</Link> | ||
</div> | ||
</div> | ||
</div> | ||
<small className='px-4 absolute bottom-[5vh] left-0 opacity-60'>© 2022 All Rights Reserved - <a href="https://github.com/PMinn">P'MIN</a>.</small> | ||
</div> | ||
<small>© 2022 All Rights Reserved - <a href="https://github.com/PMinn">P'MIN</a>.</small> | ||
</footer> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
export function WeatherIcon(prop) { | ||
return ( | ||
<svg xmlns='http://www.w3.org/2000/svg' fill='currentColor' viewBox='0 0 256 256' {...prop}> | ||
<path d='M120,40V32a8,8,0,0,1,16,0v8a8,8,0,0,1-16,0Zm8,24a64,64,0,1,0,64,64A64.07,64.07,0,0,0,128,64ZM58.34,69.66A8,8,0,0,0,69.66,58.34l-8-8A8,8,0,0,0,50.34,61.66Zm0,116.68-8,8a8,8,0,0,0,11.32,11.32l8-8a8,8,0,0,0-11.32-11.32ZM192,72a8,8,0,0,0,5.66-2.34l8-8a8,8,0,0,0-11.32-11.32l-8,8A8,8,0,0,0,192,72Zm5.66,114.34a8,8,0,0,0-11.32,11.32l8,8a8,8,0,0,0,11.32-11.32ZM40,120H32a8,8,0,0,0,0,16h8a8,8,0,0,0,0-16Zm88,88a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-8A8,8,0,0,0,128,208Zm96-88h-8a8,8,0,0,0,0,16h8a8,8,0,0,0,0-16Z'></path> | ||
</svg> | ||
) | ||
} | ||
|
||
export function EatIcon(prop) { | ||
return ( | ||
<svg xmlns='http://www.w3.org/2000/svg' fill='currentColor' viewBox='0 0 256 256' {...prop}> | ||
<path d='M224,104h-8.37a88,88,0,0,0-175.26,0H32a8,8,0,0,0-8,8,104.35,104.35,0,0,0,56,92.28V208a16,16,0,0,0,16,16h64a16,16,0,0,0,16-16v-3.72A104.35,104.35,0,0,0,232,112,8,8,0,0,0,224,104ZM173.48,56.23q2.75,2.25,5.27,4.75a87.92,87.92,0,0,0-49.15,43H100.1A72.26,72.26,0,0,1,168,56C169.83,56,171.66,56.09,173.48,56.23ZM148.12,104a71.84,71.84,0,0,1,41.27-29.57A71.45,71.45,0,0,1,199.54,104ZM128,40a71.87,71.87,0,0,1,19,2.57A88.36,88.36,0,0,0,83.33,104H56.46A72.08,72.08,0,0,1,128,40Z'></path> | ||
</svg> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import FooterComponent from './FooterComponent'; | ||
import NavComponent from './NavComponent'; | ||
import { useSystem } from "@/contexts/System"; | ||
|
||
export default function Layout({ children, options = {} }) { | ||
const { theme, setTheme } = useSystem(); | ||
return ( | ||
<div> | ||
<NavComponent theme={theme} setTheme={setTheme} options={options.nav}></NavComponent> | ||
<main>{children}</main> | ||
<FooterComponent options={options.footer} /> | ||
</div> | ||
) | ||
} |
Oops, something went wrong.