diff --git a/README.md b/README.md index 9f226ae..5b0d41b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,134 @@ -# acs-timetable -A simple My SQL database and springboot build for ACS@Fsci student to get their timetable. +# ACS TIME TABLE + +## Topic + +- [Installation](#installation) +- [Frontend](#frontend) +- [Backend](#backend) +- [How to use](#how-to-use) +- [OOP Concept](#oop-concept) + +# Installation + +``` +git clone https://github.com/tententgc/acs-timetable.git + +cd acs-timetable + +``` + +# Frontend + +- Tool + - React + - MobX + - Tailwind + - and more... + +## Frontend Setup + +`Installation` + +```bash +cd client +npm install +``` + +`Run` + +```bash +npm start +``` + +will running on port 3000 + +
+
+
+
+ +# Backend + +- Tool + - Spring Boot JPA + - Postgresql + - JWT + - Bcrypt + +## Backend Setup + +- สร้าง schema ใน database ชื่อ acs + เปลี่ยนค่าต่าง ๆ ใน file application.properties ในไฟล์ `application.properties` ใน folder `server/src/main/resources` ให้เปลี่ยนค่าต่าง ๆ ให้ตรงกับค่าของ database ที่ใช้ โดยค่า default จะเป็น Schema ชื่อ Test ใน database postgres + +```sql +create schema YOUR_SCHEMA_NAME; +``` + +- `สร้าง folder secret ใน path ต่อไปนี้` + +```bash +cd server/src/main/java/com/oop/server +mkdir secret +cd secret +touch SecretKeyENV.java +``` + +- `ใน file SecretKeyENV.java ประกอบด้วย secretKey และ adminKey` + +```java +package com.oop.server.secret; + +public class SecretKeyENV { + public static String secretKey = "your custom"; + public static String adminKey = "your custom"; +} +``` + +### Folder Structure + +```bash +src/ +|____test +| |____java +| | |____com +| | | |____oop +| | | | |____server +| | | | | |____ServerApplicationTests.java +|____main +| |____resources +| | |____static +| | |____templates +| | |____application.properties +| |____java +| | |____com +| | | |____oop +| | | | |____server +| | | | | |____middleware +| | | | | | |____TokenHandler.java +| | | | | |____ServerApplication.java +| | | | | |____repository +| | | | | |____controller +| | | | | |____model +| | | | | |____secret +``` + +- Folder `Middleware` จะเก็บ middleware ต่างๆเอาไว้จัดการกับ request เช่น Token Handle. + +- Folder `Repository` จะเก็บการ Connection กับ database เช่น คำสั่งที่ใช้ในการ query. + +- Folder `Controller` จะเก็บการจัดการกับ request ที่เข้ามาจาก client และส่ง response กลับไป. + + - สามารถดู API ต่าง ๆ ได้ผ่าน file API.txt + +- Folder `Model` จะเก็บ model entity ต่างๆที่ใช้ในการเก็บข้อมูล. + +- Folder `Secret` จะเก็บ secret key ต่างๆที่ใช้ในการเข้าถึงข้อมูล. + +
+
+
+
+ +# How to install + +- สามารถดูวิธีการติดตั้งงานได้ที่ [Click here](https://youtu.be/h8YF-NsLznU) diff --git a/client/public/favicon.ico b/client/public/favicon.ico index a11777c..10a0485 100644 Binary files a/client/public/favicon.ico and b/client/public/favicon.ico differ diff --git a/client/src/assets/logo.png b/client/src/assets/ACS-Black.png similarity index 100% rename from client/src/assets/logo.png rename to client/src/assets/ACS-Black.png diff --git a/client/src/assets/ACS-Purple.png b/client/src/assets/ACS-Purple.png new file mode 100644 index 0000000..1d4238c Binary files /dev/null and b/client/src/assets/ACS-Purple.png differ diff --git a/client/src/assets/ACS-White.png b/client/src/assets/ACS-White.png new file mode 100644 index 0000000..81df4ca Binary files /dev/null and b/client/src/assets/ACS-White.png differ diff --git a/client/src/assets/sign-in-image.png b/client/src/assets/sign-in-image.png index 8a14907..9653f85 100644 Binary files a/client/src/assets/sign-in-image.png and b/client/src/assets/sign-in-image.png differ diff --git a/client/src/assets/sign-in-image2.png b/client/src/assets/sign-in-image2.png new file mode 100644 index 0000000..9546cf7 Binary files /dev/null and b/client/src/assets/sign-in-image2.png differ diff --git a/client/src/components/Calendar.tsx b/client/src/components/Calendar.tsx index 5dd4c64..711842a 100644 --- a/client/src/components/Calendar.tsx +++ b/client/src/components/Calendar.tsx @@ -7,6 +7,7 @@ import CalendarModal from "./CalendarModal"; interface CalendarProps { store: CalendarStoreImpl; + theme: boolean; } const Calendar: React.FC = observer((props) => { @@ -45,6 +46,7 @@ const Calendar: React.FC = observer((props) => { currMonth={currMonth} handleChangeMonth={handleChangeMonth} store={props.store} + theme={props.theme} /> = observer((props) => { store={props.store} /> - {props.store.modalOpen && } + {props.store.modalOpen && ( + + )} ); }); diff --git a/client/src/components/CalendarAccordian.tsx b/client/src/components/CalendarAccordian.tsx index 84061f7..8874315 100644 --- a/client/src/components/CalendarAccordian.tsx +++ b/client/src/components/CalendarAccordian.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useRef, useState } from "react"; import autoAnimate from "@formkit/auto-animate"; -import { MdOutlineClose } from "react-icons/md"; +import { FiX } from "react-icons/fi"; import styled from "styled-components"; import Chip from "./Chip"; import { deleteEvent, EventType } from "../api/eventRouter"; @@ -15,6 +15,7 @@ import EventEditForm from "./EventEditForm"; type CalendarAccordianProps = EventType & { store: AuthenStoreImpl; eventStore: CalendarStoreImpl; + theme: boolean; }; const CalendarAccordian: React.FC = (props) => { @@ -66,7 +67,7 @@ const CalendarAccordian: React.FC = (props) => { return (
@@ -88,7 +89,7 @@ const CalendarAccordian: React.FC = (props) => { }`} > = (props) => { {props.store.user_status === 200 && !show ? (
setOpenEditForm(true)} >
setDeleteInterupt(true)} > @@ -141,15 +142,25 @@ const CalendarAccordian: React.FC = (props) => { {show && (
- +
)}
- {show &&

{props.description}

} + {show && ( +
+ {props.description.split("\n").map((item) => { + return ( +

+ {item} +

+ ); + })} +
+ )}
{openEditform ? ( @@ -162,15 +173,20 @@ const CalendarAccordian: React.FC = (props) => { time_range={props.time_range} header={props.header} event_id={props.event_id} + theme={props.theme} /> ) : ( "" )} +
); @@ -190,7 +206,7 @@ const HeaderCustom = styled.p` height: 1px; bottom: 0px; left: 0; - background-color: white; + background-color: black; transform-origin: bottom right; transition: transform 0.2s ease-out; } diff --git a/client/src/components/CalendarBody.tsx b/client/src/components/CalendarBody.tsx index 41ddac1..80add46 100644 --- a/client/src/components/CalendarBody.tsx +++ b/client/src/components/CalendarBody.tsx @@ -21,7 +21,7 @@ interface CalendarBodyProps { const CalendarBody: React.FC = observer((props) => { return ( -
+
{props.store.workAll === null ? ( ) : ( @@ -34,7 +34,7 @@ const CalendarBody: React.FC = observer((props) => { {dateList.map((item, index) => { return (
{item} diff --git a/client/src/components/CalendarBox.tsx b/client/src/components/CalendarBox.tsx index 9f9e740..65fc368 100644 --- a/client/src/components/CalendarBox.tsx +++ b/client/src/components/CalendarBox.tsx @@ -16,42 +16,49 @@ const CalendarBox: React.FC = observer((props) => { }; return ( -
+
-
-

{props.day}

-
-
- {props.store.checkWorkDay(props.day) - ? props.store.workDayFilter[props.day].map((item) => { - return ( -
-
-
+
+
+

+ {props.day} +

+
+
+ {props.store.checkWorkDay(props.day) + ? props.store.workDayFilter[props.day].map((item) => { + return ( +
+
+
+
+

+ {item.header} +

-

- {item.header} -

-
- ); - }) - : ""} + ); + }) + : ""} +
diff --git a/client/src/components/CalendarColorTheme.tsx b/client/src/components/CalendarColorTheme.tsx index 81f79bf..1ffe724 100644 --- a/client/src/components/CalendarColorTheme.tsx +++ b/client/src/components/CalendarColorTheme.tsx @@ -24,7 +24,7 @@ const CalendarColorTheme: React.FC = observer( }, [props.colorStore]); return ( -
+
{colordata.map((item, index) => { // wait fetch data from backend color table @@ -39,11 +39,7 @@ const CalendarColorTheme: React.FC = observer( })} {props.store.colorFilter.length ? (
- +
) : ( "" diff --git a/client/src/components/CalendarHeader.tsx b/client/src/components/CalendarHeader.tsx index 65f3d12..0b3fefb 100644 --- a/client/src/components/CalendarHeader.tsx +++ b/client/src/components/CalendarHeader.tsx @@ -7,6 +7,7 @@ interface CalendarHeaderProps { currMonth: number; handleChangeMonth: (n: number) => void; store: CalendarStoreImpl; + theme: boolean; } const CalendarHeader: React.FC = (props) => { @@ -16,45 +17,47 @@ const CalendarHeader: React.FC = (props) => { return (
-
-
- handleClick(-1)} - > - - -
-
-

- {monthList[props.currMonth]} {props.currYear} -

-
-
- handleClick(1)} - > - - +
+
+
+ handleClick(-1)} + > + + +
+
+

+ {monthList[props.currMonth]} {props.currYear} +

+
+
+ handleClick(1)} + > + + +
diff --git a/client/src/components/CalendarModal.tsx b/client/src/components/CalendarModal.tsx index 86cf662..7fee8ae 100644 --- a/client/src/components/CalendarModal.tsx +++ b/client/src/components/CalendarModal.tsx @@ -6,6 +6,7 @@ import { AuthenStore } from "../store/AuthenStore"; interface CalendarModalProps { store: CalendarStoreImpl; + theme: boolean; } const CalendarModal: React.FC = observer((props) => { @@ -28,6 +29,7 @@ const CalendarModal: React.FC = observer((props) => { key={Math.random()} store={AuthenStore} eventStore={props.store} + theme={props.theme} /> ); })} diff --git a/client/src/components/Chip.tsx b/client/src/components/Chip.tsx index 6f7a0d7..9a60c9b 100644 --- a/client/src/components/Chip.tsx +++ b/client/src/components/Chip.tsx @@ -11,7 +11,7 @@ const Chip: React.FC = (props) => { className={`px-2 py-[0.5px] flex rounded-xl w-fit`} style={{ backgroundColor: `#${props.color}` }} > -

{props.title}

+

{props.title}

); }; diff --git a/client/src/components/ColorTheme.tsx b/client/src/components/ColorTheme.tsx index e031709..c2f42c2 100644 --- a/client/src/components/ColorTheme.tsx +++ b/client/src/components/ColorTheme.tsx @@ -3,7 +3,7 @@ import React from "react"; import { CalendarStoreImpl } from "../store/CalendarStore"; interface ColorThemeProps { - color: string; + color?: string; title: string; store: CalendarStoreImpl; } @@ -15,18 +15,20 @@ const ColorTheme: React.FC = observer((props) => { return ( handleClick(props.color, props.title)} + onClick={() => handleClick(props.color as string, props.title)} >
-

{props.title}

+

{props.title}

); }); diff --git a/client/src/components/DeleteWarning.tsx b/client/src/components/DeleteWarning.tsx index 76c15c1..264c97e 100644 --- a/client/src/components/DeleteWarning.tsx +++ b/client/src/components/DeleteWarning.tsx @@ -17,16 +17,19 @@ const DeleteWarning: React.FC = (props) => { props.open ? "block" : "hidden" } z-10`} > -
+
-

+

Are you sure to delete this event ?

@@ -79,43 +81,45 @@ const Drawer: React.FC<{ role: string; username: string }> = (props) => { className="animate-[spin_10s_linear_infinite]" />
-

{props.username}

+

+ {props.username} +

{props.role === "ADMIN" ? (
handleSignOut("Create Event")} >
-

Add Admin Event

+

Add Admin Event

) : (
handleSignOut("Create Event")} >
-

Create Event

+

Create Event

)}
handleSignOut("Sign Out")} >
-

Sign Out

+

Sign Out

@@ -128,6 +132,7 @@ const Drawer: React.FC<{ role: string; username: string }> = (props) => { open={openList.form} store={CalendarStore} colorStore={ColorStore} + theme={props.theme} /> ) : ( "" diff --git a/client/src/components/EventEditForm.tsx b/client/src/components/EventEditForm.tsx index 70f6c28..0e6cea6 100644 --- a/client/src/components/EventEditForm.tsx +++ b/client/src/components/EventEditForm.tsx @@ -1,6 +1,6 @@ import React, { useState } from "react"; import InputCustom from "./InputCustom"; -import { FcCloseUpMode } from "react-icons/fc"; +import { FiX } from "react-icons/fi"; import { CalendarStoreImpl } from "../store/CalendarStore"; import { putEvent, PutEventRequest } from "../api/eventRouter"; import { ToastContainer, toast } from "react-toastify"; @@ -10,6 +10,7 @@ interface EventFormType { open: boolean; handleClose: () => void; store: CalendarStoreImpl; + theme: boolean; } type EventFormProps = PutEventRequest & EventFormType; @@ -26,6 +27,7 @@ const EventEditForm: React.FC = (props) => { description: props.description, time_range: props.time_range, event_date: props.event_date, + theme: props.theme, }); const [timeRange, setTimeRange] = useState<{ t1: string; t2: string }>({ t1: "", @@ -84,7 +86,7 @@ const EventEditForm: React.FC = (props) => { onClick={handleClick} >
@@ -92,62 +94,69 @@ const EventEditForm: React.FC = (props) => {
-
+
props.handleClose()} > - +