Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: department #33

Merged
merged 3 commits into from
Jan 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 28 additions & 24 deletions src/components/Faculties/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
export interface CardProps {
nameThai: string;
nameEnglish: string;
instagram?: string;
facebook?: string;
isActive: boolean;
link: string;
}
const Card: React.FC<CardProps> = ({
nameThai,
nameEnglish,
import { motion } from "framer-motion";

import type { Faculty } from "@/types/faculty";

const Card: React.FC<Faculty> = ({
nameTH,
nameEN,
instagram,
facebook,
isActive,
link,
participateOPH,
id,
}) => {
return (
<div className="mx-4 my-2 flex h-60 min-h-full max-w-[29rem] flex-col justify-between rounded-2xl border-2 border-white bg-transparent bg-gradient-to-t from-pink-400/50 to-white/5 text-base font-medium text-white shadow-inner shadow-white">
<motion.a
href={"/faculties/" + id}
className="mx-4 my-2 flex h-full max-w-[29rem] flex-col justify-between rounded-2xl border-2 border-white bg-transparent bg-gradient-to-t from-pink-400/50 to-white/5 font-medium text-white shadow-inner shadow-white"
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
transition={{
type: "spring",
stiffness: 120,
damping: 10,
duration: 0.3,
}}
>
<div className="flex w-full flex-col p-6">
<p className="text-2xl font-bold">{nameThai}</p>
<p className="pb-2 pt-1">{nameEnglish}</p>
<p className="text-2xl font-bold">{nameTH}</p>
<p className="pb-2 pt-1">{nameEN}</p>
<div className="mb-2 inline-block w-fit rounded-2xl bg-white px-3 py-1 text-sm text-pink-550">
{!isActive && "ไม่ได้"}จัดงาน OPH ในวันที่ 20-21 ม.ค.
{!participateOPH && "ไม่ได้"}จัดงาน OPH ในวันที่ 20-21 ม.ค.
</div>
<div className="flex items-center py-1">
<p className="icon-[mdi--instagram] mr-1 h-6 w-6"></p>
Expand All @@ -31,14 +38,11 @@ const Card: React.FC<CardProps> = ({
<p>{facebook ?? "-"}</p>
</div>
</div>
<a
href={link}
className="flex h-11 w-full items-center justify-between rounded-b-2xl bg-indigo-900 bg-gradient-to-r from-indigo-900 to-pink-550 px-6"
>
<div className="flex h-11 w-full items-center justify-between rounded-b-2xl bg-gradient-to-tr from-indigo-900 to-pink-550 px-6">
<p>รายละเอียด / Details</p>
<i className="icon-[mdi--navigate-next] h-10 w-10"></i>
</a>
</div>
<i className="icon-[mdi--navigate-next] text-4xl"></i>
</div>
</motion.a>
);
};
export default Card;
23 changes: 0 additions & 23 deletions src/components/Faculties/FacultiesCard.tsx

This file was deleted.

47 changes: 47 additions & 0 deletions src/components/Faculties/FacultiesList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { motion } from "framer-motion";
import { useState } from "react";

import { FACULTIES } from "@/data/faculties";
import Card from "./Card.tsx";
import Selector from "./Selector.tsx";

const options = FACULTIES.map((faculty) => {
return {
id: parseInt(faculty.id),
name: faculty.nameTH + " / " + faculty.nameEN,
};
});

const FacultiesList = () => {
const [facultySelected, setFacultySelected] = useState(0);

return (
<>
<Selector
facultySelected={facultySelected}
setFacultySelected={setFacultySelected}
options={options}
/>
<motion.div
className="mt-12 grid w-full max-w-md grid-cols-1 gap-4 md:max-w-5xl md:grid-cols-2"
layout
transition={{
layout: {
type: "spring",
stiffness: 150,
damping: 20,
duration: 0.1,
},
}}
>
{FACULTIES.filter(
(faculty) =>
facultySelected === 0 || parseInt(faculty.id) === facultySelected
).map((faculty) => {
return <Card key={faculty.id} {...faculty} />;
})}
</motion.div>
</>
);
};
export default FacultiesList;
73 changes: 54 additions & 19 deletions src/components/Faculties/Selector.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
import { useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import type { FC } from "react";

const options = {
1: "Engineer",
2: "Science",
3: "Arts",
};
interface Props {
facultySelected: number;
setFacultySelected: (faculty: number) => void;
options: { id: number; name: string }[];
}

const Selector: FC<Props> = ({
facultySelected,
setFacultySelected,
options,
}) => {
const handleSelect = (e: React.ChangeEvent<HTMLSelectElement>) => {
e.preventDefault();
setFacultySelected(parseInt(e.target.value));
};

const Selector = () => {
const [from, setFrom] = useState(0);
const handleClear = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
setFacultySelected(0);
};

return (
<section className="flex w-full max-w-md justify-center">
<div className="mx-6 w-full">
<div className="mx-6 flex w-full">
<div className="relative flex h-12 items-center gap-4">
<label className="text-xl font-bold leading-none text-white">
เลือก
Expand All @@ -20,20 +33,42 @@ const Selector = () => {
</label>
<select
className="relative h-full w-full flex-1 appearance-none rounded-2xl bg-white px-4 font-medium text-pink-400"
onChange={(e) => setFrom(Number(e.currentTarget.value))}
value={from}
onChange={handleSelect}
value={facultySelected}
>
<option value="0" disabled hidden>
คณะ / Faculty
</option>
{Object.entries(options).map(([key, value]) => (
<option key={key} value={key}>
{value}
</option>
))}
<option value="0">คณะ / Faculty</option>
{options.map((option) => {
return (
<option key={option.id} value={option.id}>
{option.name}
</option>
);
})}
</select>
<i className="icon-[mdi--chevron-down] pointer-events-none absolute right-0 top-1/2 -translate-y-1/2 text-3xl text-pink-500"></i>
</div>
<AnimatePresence>
{facultySelected !== 0 && (
<motion.button
className="group right-0 flex items-center justify-center p-2 text-center"
onClick={handleClear}
initial={{ x: -50 }}
animate={{ x: 0 }}
exit={{ x: -50 }}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
transition={{
type: "spring",
stiffness: 100,
damping: 20,
duration: 0.3,
ease: "easeInOut",
}}
>
<i className="icon-[mdi--trash] text-3xl text-white group-hover:icon-[mdi--delete-empty]"></i>
</motion.button>
)}
</AnimatePresence>
</div>
</section>
);
Expand Down
78 changes: 78 additions & 0 deletions src/components/Faculty/Department.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { motion } from "framer-motion";
import type { FC } from "react";

import type { Department as DepartmentType } from "@/types/faculty";

interface Props {
departments: DepartmentType[];
}

const variants = {
initial: {
opacity: 0,
y: 50,
},
animate: {
opacity: 1,
y: 0,
transition: {
delayChildren: 0.2,
staggerChildren: 0.1,
},
},
};

const sectionVariants = {
initial: {
opacity: 0,
y: 50,
},
animate: {
opacity: 1,
y: 0,
},
};

const Department: FC<Props> = ({ departments }) => {
return (
<motion.ul
className="mx-auto mt-16 flex w-full max-w-xl flex-col gap-4"
variants={variants}
initial="initial"
animate="animate"
exit="initial"
transition={{
type: "spring",
stiffness: 100,
damping: 20,
}}
>
{departments.map((department) => (
<motion.li
className="flex flex-col gap-2.5"
variants={sectionVariants}
key={department.id}
>
<div className="flex w-full flex-col items-center justify-center rounded-2xl border-2 border-white bg-white px-4 py-2 text-center text-pink-500">
<p className="text-xl font-bold">{department.nameTH}</p>
<p className="font-bold">{department.nameEN}</p>
</div>
<ul className="mx-auto flex w-4/5 flex-col gap-2.5">
{department.sections.map((section) => (
<motion.li
className="mx-auto flex w-full flex-col items-center justify-center rounded-2xl border-2 border-white bg-gradient-to-t from-pink-550/50 to-pink-550/15 px-3 py-2 text-center shadow-inner shadow-white"
variants={sectionVariants}
key={section.id}
>
<p className="font-medium">{section.nameTH}</p>
<p className="font-medium">{section.nameEN}</p>
</motion.li>
))}
</ul>
</motion.li>
))}
</motion.ul>
);
};

export default Department;
6 changes: 3 additions & 3 deletions src/data/FAQs.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Props as TextBoxProps } from "@/components/FAQs/TextBox.astro";
import type { FAQ } from "@/types/FAQ";

export const FAQS_THAI: TextBoxProps[] = [
export const FAQS_THAI: FAQ[] = [
{
question: "จุฬาฯ จะจัด Open House วันไหน?",
answer:
Expand Down Expand Up @@ -60,7 +60,7 @@ export const FAQS_THAI: TextBoxProps[] = [
"เมื่อลงทะเบียนแล้วจะได้รับ QR Code แล้วสามารถนำ QR Code ตัวนี้ไปยื่นได้ทุกคณะ รวมถึงการเข้าร่วมงานของส่วนกลางที่บริเวณศาลาพระเกี้ยวด้วย",
},
];
export const FAQS_ENG: TextBoxProps[] = [
export const FAQS_ENG: FAQ[] = [
{
question: "When is Chulalongkorn University's Open House scheduled?",
answer:
Expand Down
52 changes: 0 additions & 52 deletions src/data/events.ts

This file was deleted.

Loading