Skip to content

Commit

Permalink
update: version4_1
Browse files Browse the repository at this point in the history
  • Loading branch information
PMinn committed Mar 23, 2024
1 parent e452acc commit b86f50f
Show file tree
Hide file tree
Showing 41 changed files with 14,035 additions and 6,559 deletions.
47 changes: 47 additions & 0 deletions components/Alert.js
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>
)
}
40 changes: 40 additions & 0 deletions components/Confirm.js
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>
)
}
21 changes: 0 additions & 21 deletions components/ConfirmComponent.js

This file was deleted.

139 changes: 87 additions & 52 deletions components/CourseCardComponent.js
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 >
)
}
46 changes: 25 additions & 21 deletions components/FooterComponent.js
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>
)
}
15 changes: 15 additions & 0 deletions components/Icons.js
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>
)
}
14 changes: 14 additions & 0 deletions components/Layout.js
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>
)
}
Loading

0 comments on commit b86f50f

Please sign in to comment.