Skip to content

Commit

Permalink
✨ feat : Add Schedule component APIs & layout
Browse files Browse the repository at this point in the history
- Create Class Schedule API
- Delete Class Schedule API
- Get Class Schedule API
- Adding layout and the react-calendar library

Related Issue : YJU-OKURA#101 YJU-OKURA#99
  • Loading branch information
Lainari committed Apr 21, 2024
1 parent dc2338c commit e9c993c
Show file tree
Hide file tree
Showing 28 changed files with 1,070 additions and 75 deletions.
8 changes: 6 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
"prettier/prettier": ["error", {"endOfLine": "auto"}],
"node/no-unsupported-features/es-syntax": [
"error",
{"ignores": ["modules"]}
{
"version": "18.17.0",
"ignores": ["modules"]
}
],
"node/no-unpublished-import": "off",
"node/no-missing-import": "off"
"node/no-missing-import": "off",
"node/no-unsupported-features/node-builtins": "off"
},
"env": {
"browser": true,
Expand Down
6 changes: 5 additions & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ module.exports = {
return config;
},
images: {
domains: ['lh3.googleusercontent.com', 'd3sbrbqucv1146.cloudfront.net'],
domains: [
'lh3.googleusercontent.com',
'd3sbrbqucv1146.cloudfront.net',
'd1s5j3nmszux84.cloudfront.net',
],
},
reactStrictMode: false,
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"axios": "^1.6.5",
"next": "14.0.4",
"react": "^18",
"react-calendar": "^4.8.0",
"react-dom": "^18",
"react-infinite-scroller": "^1.2.6",
"react-markdown": "^9.0.1",
Expand Down
13 changes: 13 additions & 0 deletions src/api/classSchedule/deleteClassSchedule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import req from '../apiUtils';

const deleteClassSchedule = async (sid: number, cid: number, uid: number) => {
const response = await req(
`/cs/${sid}?cid=${cid}&uid=${uid}`,
'delete',
'gin'
);

return response.data;
};

export default deleteClassSchedule;
9 changes: 9 additions & 0 deletions src/api/classSchedule/getClassSchedule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import req from '../apiUtils';

const getClassSchedule = async (scheduleCode: number) => {
const response = await req(`/cs/${scheduleCode}`, 'get', 'gin');

return response.data;
};

export default getClassSchedule;
9 changes: 9 additions & 0 deletions src/api/classSchedule/getClassScheduleList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import req from '../apiUtils';

const getClassScheduleList = async (classCode: number) => {
const response = await req(`/cs?cid=${classCode}`, 'get', 'gin');

return response;
};

export default getClassScheduleList;
15 changes: 15 additions & 0 deletions src/api/classSchedule/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import getClassSchedule from './getClassSchedule';
import getClassScheduleList from './getClassScheduleList';
import postCreateClassSchedule from './postCreateClassSchedule';
import deleteClassSchedule from './deleteClassSchedule';
import putClassSchedule from './putClassSchedule';

const classScheduleAPI = {
getClassSchedule,
getClassScheduleList,
postCreateClassSchedule,
deleteClassSchedule,
putClassSchedule,
};

export default classScheduleAPI;
18 changes: 18 additions & 0 deletions src/api/classSchedule/postCreateClassSchedule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import req from '../apiUtils';
import {PostCreateScheduleData} from '@/src/interfaces/api/_class';

const postCreateClassSchedule = async (postData: PostCreateScheduleData) => {
const data = {
cid: postData.cid,
ended_at: postData.ended_at,
is_live: postData.is_live,
started_at: postData.started_at,
title: postData.title,
};

const response = await req(`/cs?uid=${postData.uid}`, 'post', 'gin', data);

return response;
};

export default postCreateClassSchedule;
21 changes: 21 additions & 0 deletions src/api/classSchedule/putClassSchedule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import req from '../apiUtils';
import {PutClassScheduleData} from '@/src/interfaces/api/_class';

const putClassSchedule = async (requestData: PutClassScheduleData) => {
const requestForm = {
ended_at: requestData.ended_at,
is_live: requestData.is_live,
started_at: requestData.started_at,
title: requestData.title,
};
const response = await req(
`/cs/${requestData.sid}?cid=${requestData.cid}&uid=${requestData.uid}`,
'put',
'gin',
requestForm
);

return response;
};

export default putClassSchedule;
81 changes: 69 additions & 12 deletions src/app/[className]/components/card/ScheduleCard.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,82 @@
import Image from 'next/image';
'use client';

import React, {useState} from 'react';
import {ClassEditSchedule} from '../modal';
import {Dropdown} from '@/src/app/components/_class/dropdown';
import {ScheduleCardProps} from '@/src/interfaces/_class';
import icons from '@/public/svgs/_class';

const ScheduleCard = ({scheduleName, time, managerRole}: ScheduleCardProps) => {
const ScheduleCard = ({
scheduleName,
startTime,
endTime,
managerRole,
isLive,
zIndex,
scheduleId,
deleteSchedule,
}: ScheduleCardProps & {zIndex: number} & {
deleteSchedule: (scheduleId: number) => void;
}) => {
const dropdownItems = [
{
modalId: 'scheduleEdit',
icon: icons.edit,
alt: 'Edit Icon',
text: 'Edit',
},
{
modalId: 'scheduleDelete',
icon: icons.delete,
alt: 'Delete Icon',
text: 'Delete',
},
];
const [isModalOpen, setIsModalOpen] = useState(false);
const [selectedModalId, setSelectedModalId] = useState<string | null>(null);

const setActiveModalId = (modalId: string) => {
setSelectedModalId(modalId);
setIsModalOpen(true);
if (modalId === 'scheduleDelete') {
deleteSchedule(scheduleId);
}
};

return (
<>
<div className="my-2 me-6">
<div className="min-w-64 border-b-4 border-b-blue-400">
<div className="flex justify-between">
<p className="font-semibold text-medium">{scheduleName}</p>
<div
className={`min-w-64 h-10 border-b-4 ${
isLive ? 'border-b-red-400' : 'border-b-blue-400'
}`}
>
<div className="flex justify-between items-center">
<p className="font-semibold text-lg">
{isLive ? `[Live] ${scheduleName}` : `${scheduleName}`}
</p>
{managerRole && (
<Image
src={icons.moreVert}
alt={'moreVert'}
width={30}
height={30}
/>
<>
<div style={{width: 30, height: 30}}>
<Dropdown
dropdownImageSrc={icons.moreVert}
items={dropdownItems}
setActiveModalId={setActiveModalId}
zIndex={zIndex}
/>
</div>
</>
)}
</div>
<p className="text-sm my-1">{time}</p>
</div>
<div className="my-2">
<p className="font-bold text-lg mb-2">Date</p>
<p className="ms-2 text-md mb-1">{startTime}</p>
<p className="ms-2 text-md">{endTime}</p>
</div>
{isModalOpen && selectedModalId === 'scheduleEdit' && (
<ClassEditSchedule setShowScheduleModal={setIsModalOpen} />
)}
</div>
</>
);
Expand Down
134 changes: 119 additions & 15 deletions src/app/[className]/components/main/Main.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,105 @@
'use client';

import {useState} from 'react';
import Image from 'next/image';
import {Notice, Post, Schedule} from '.';
import {
ClassCreatePost,
ClassCreateSchedule,
} from '@/src/app/[className]/components/modal';
import {RoleProps} from '@/src/interfaces/_class';
import icons from '@/public/svgs/_class';

const Main = ({managerRole}: RoleProps) => {
const Main = ({managerRole, classId}: RoleProps) => {
const [showDropdown, setShowDropdown] = useState<Record<string, boolean>>({
Notice: false,
Schedule: false,
Posts: false,
});
const [showScheduleModal, setShowScheduleModal] = useState(false);
const [showPostModal, setShowPostModal] = useState(false);

const handleDropdown = (sectionTitle: string) => {
setShowDropdown(prevState => {
const newState = Object.assign({}, prevState);
newState[sectionTitle] = !prevState[sectionTitle];
return newState;
});
};

const handleOpenScheduleModal = () => {
setShowDropdown(prevState => ({...prevState, Schedule: true}));
setShowScheduleModal(true);
};

const handleCloseScheduleModal = () => {
setShowDropdown(prevState => ({...prevState, Schedule: false}));
setShowScheduleModal(false);
};

const handleOpenPostModal = () => {
setShowDropdown(prevState => ({
...prevState,
Posts: true,
Notice: !prevState['Notice'],
}));
setShowPostModal(true);
};

const handleClosePostModal = () => {
setShowDropdown(prevState => ({
...prevState,
Posts: false,
Notice: !prevState['Notice'],
}));
setShowPostModal(false);
};

const mainSections = [
{title: 'Notice', component: <Notice managerRole={managerRole} />},
{title: 'Schedule', component: <Schedule managerRole={managerRole} />},
{title: 'Posts', component: <Post managerRole={managerRole} />},
{
title: 'Notice',
component: (
<Notice
managerRole={managerRole}
classId={classId}
isOpen={showDropdown['Notice']}
/>
),
},
{
title: 'Schedule',
component: (
<>
<Schedule
managerRole={managerRole}
classId={classId}
isOpen={showDropdown['Schedule']}
/>
{showScheduleModal && (
<ClassCreateSchedule
setShowScheduleModal={handleCloseScheduleModal}
/>
)}
</>
),
openModal: handleOpenScheduleModal,
},
{
title: 'Posts',
component: (
<>
<Post
managerRole={managerRole}
classId={classId}
isOpen={showDropdown['Posts']}
/>
{showPostModal && (
<ClassCreatePost setShowPostModal={handleClosePostModal} />
)}
</>
),
openModal: handleOpenPostModal,
},
];
return (
<>
Expand All @@ -20,24 +112,36 @@ const Main = ({managerRole}: RoleProps) => {
alt={'dropdown'}
width={0}
height={0}
className="me-2 w-auto h-auto max-w-6 max-h-6"
className={`me-2 w-auto h-auto max-w-6 max-h-6 hover:cursor-pointer ${
showDropdown[section.title] ? '' : '-rotate-90'
}`}
onClick={() => handleDropdown(section.title)}
/>
<div className="flex w-full justify-between">
<h3 className="text-xl font-bold">{section.title}</h3>
<div className="flex w-full mb-3 justify-between items-center">
<h3
className="text-xl font-bold hover:cursor-pointer"
onClick={() => handleDropdown(section.title)}
>
{section.title}
</h3>
{managerRole &&
(section.title === 'Schedule' ||
section.title === 'Posts') && (
<Image
src={icons.addButton}
alt={'addButton'}
width={0}
height={0}
className="w-auto h-auto max-w-6 max-h-6"
/>
<div onClick={section.openModal}>
<Image
src={icons.addButton}
alt={'addButton'}
width={0}
height={0}
className="w-auto h-auto max-w-6 max-h-6"
/>
</div>
)}
</div>
</div>
<div className="mb-10">{section.component}</div>
<div className="mb-10">
{showDropdown[section.title] && <div>{section.component}</div>}
</div>
</div>
))}
</div>
Expand Down
Loading

0 comments on commit e9c993c

Please sign in to comment.