Skip to content

Commit

Permalink
Merge pull request #23 from IT-Cotato/feature/#19-room_list
Browse files Browse the repository at this point in the history
[Feat] 과외방 목록
  • Loading branch information
yongaricode authored Jan 9, 2025
2 parents 63a45c5 + 6bb0ee0 commit b04a946
Show file tree
Hide file tree
Showing 8 changed files with 340 additions and 2 deletions.
7 changes: 6 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import './App.css';
import { router } from './routes/Router';
import { RouterProvider } from 'react-router-dom';
import { RoomProvider } from './context/RoomContext';

function App() {
return <RouterProvider router={router} />;
return (
<RoomProvider>
<RouterProvider router={router} />
</RoomProvider>
);
}

export default App;
31 changes: 31 additions & 0 deletions src/components/PermissionToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Permission } from '../context/RoomContext';

type TypeProps = {
type: Permission;
handleCheck: (id: number) => void;
};

const PermissionToggle = ({ type, handleCheck }: TypeProps) => {
return (
<div className="flex">
{type.title}
<input
id={`permission-${type.id}`}
type="checkbox"
checked={type.isChecked}
className="hidden"
onChange={() => handleCheck(type.id)}
/>
<label
htmlFor={`permission-${type.id}`}
className={`relative block w-10 h-6 bg-gray-100 rounded-lg cursor-pointer transition ${type.isChecked ? 'bg-green-400' : 'bg-gray-200'}
before:content-['']
before:absolute before:top-0.5 before:left-0.5
before:w-5 before:h-5 before:bg-white before:rounded-full before:transition
${type.isChecked ? 'before:translate-x-4' : ''}`}
/>
</div>
);
};

export default PermissionToggle;
35 changes: 35 additions & 0 deletions src/components/RoomInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { MdDeleteOutline } from 'react-icons/md';
import { CiEdit } from 'react-icons/ci';
import { Room, useRoomContext } from '../context/RoomContext';

type RoomProps = {
room: Room;
};

const RoomInfo = ({ room }: RoomProps) => {
const { onDelete } = useRoomContext();

const handleDelete = (id: number) => {
onDelete(id);
};

return (
<div className="flex items-center py-2.5 gap-4 px-4">
<div className="flex items-center p-1.5">
<img className="w-9 h-9" />
</div>
<div className="flex flex-1 flex-col text-gray-900 cursor-pointer">
<h1 className="text-body1 font-bold leading-9">{room.roomName}</h1>
<h3 className="text-body4 font-regular leading-6">학생이름</h3>
</div>
<div className="cursor-pointer">
<CiEdit size={20} />
</div>
<div className="cursor-pointer" onClick={() => handleDelete(room.id)}>
<MdDeleteOutline size={20} />
</div>
</div>
);
};

export default RoomInfo;
20 changes: 20 additions & 0 deletions src/components/SelectDate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Day } from '../context/RoomContext';

type DayProps = {
day: Day;
handleClick: (id: number) => void;
};

const SelectDate = ({ day, handleClick }: DayProps) => {
return (
<div>
<button
className={`px-4 text-white ${day.isClicked ? 'bg-black' : 'bg-gray-300'}`}
onClick={() => handleClick(day.id)}
>
{day.date}
</button>
</div>
);
};
export default SelectDate;
96 changes: 96 additions & 0 deletions src/context/RoomContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { createContext, ReactNode, useContext, useState, useRef } from 'react';

export type Day = {
id: number;
date: string;
isClicked: boolean;
};

export type Permission = {
id: number;
type: string;
title: string;
isChecked: boolean;
};

export type Room = {
id: number;
roomName: string;
subject: string;
days: string[];
pMaterials: boolean;
pHomework: boolean;
pStats: boolean;
pCounseling: true;
pPayment: true;
sMaterials: true;
sHomework: true;
sStats: true;
sCounseling: boolean;
sPayment: boolean;
};

type RoomContextType = {
rooms: Room[];
onCreate: (
roomName: string,
subject: string,
days: string[],
pMaterials: boolean,
pHomework: boolean,
pStats: boolean,
sCounseling: boolean,
sPayment: boolean,
) => void;
onDelete: (id: number) => void;
};

const RoomContext = createContext<RoomContextType | undefined>(undefined);

export const useRoomContext = () => {
const context = useContext(RoomContext);
if (!context) {
throw new Error('context 오류 발생');
}
return context;
};

export const RoomProvider = ({ children }: { children: ReactNode }) => {
const [rooms, setRooms] = useState<Room[]>([]);
const idRef = useRef(0);

const onCreate = (
roomName: string,
subject: string,
days: string[],
pMaterials: boolean,
pHomework: boolean,
pStats: boolean,
sCounseling: boolean,
sPayment: boolean,
) => {
const newRoom: Room = {
id: idRef.current++,
roomName: roomName,
subject: subject,
days: days,
pMaterials: pMaterials,
pHomework: pHomework,
pStats: pStats,
pCounseling: true,
pPayment: true,
sMaterials: true,
sHomework: true,
sStats: true,
sCounseling: sCounseling,
sPayment: sPayment,
};
setRooms([...rooms, newRoom]);
};

const onDelete = (id: number) => {
setRooms(rooms.filter((room) => room.id !== id));
};

return <RoomContext.Provider value={{ rooms, onCreate, onDelete }}>{children}</RoomContext.Provider>;
};
128 changes: 128 additions & 0 deletions src/pages/CreateRoom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import PermissionToggle from '../components/PermissionToggle';
import SelectDate from '../components/SelectDate';
import { useEffect, useState } from 'react';
import { useRoomContext } from '../context/RoomContext';
import { Day, Permission } from '../context/RoomContext';
import { useNavigate } from 'react-router-dom';

const CreateRoom = () => {
const navigate = useNavigate();
const { onCreate, rooms } = useRoomContext();
const [roomName, setRoomName] = useState('');
const [subject, setSubject] = useState('');
const [dayList, setDayList] = useState<Day[]>([
{ id: 0, date: '월', isClicked: false },
{ id: 1, date: '화', isClicked: false },
{ id: 2, date: '수', isClicked: false },
{ id: 3, date: '목', isClicked: false },
{ id: 4, date: '금', isClicked: false },
{ id: 5, date: '토', isClicked: false },
{ id: 6, date: '일', isClicked: false },
]);
const [days, setDays] = useState<string[]>([]);

const [parentP, setparentP] = useState<Permission[]>([
{ id: 0, type: 'materials', title: '강의 자료함', isChecked: false },
{ id: 1, type: 'homework', title: '주차별 숙제', isChecked: false },
{ id: 2, type: 'stats', title: '성적 통계', isChecked: false },
{ id: 3, type: 'counseling', title: '상담 일지', isChecked: true },
{ id: 4, type: 'payment', title: '입금', isChecked: true },
]);
const [studentP, setstudentP] = useState<Permission[]>([
{ id: 5, type: 'materials', title: '강의 자료함', isChecked: true },
{ id: 6, type: 'homework', title: '주차별 숙제', isChecked: true },
{ id: 7, type: 'stats', title: '성적 통계', isChecked: true },
{ id: 8, type: 'counseling', title: '상담 일지', isChecked: false },
{ id: 9, type: 'payment', title: '입금', isChecked: false },
]);

const handleClick = (id: number) => {
setDayList(dayList.map((day) => (id === day.id ? { ...day, isClicked: !day.isClicked } : day)));
};

useEffect(() => {
const selectedDays = dayList.filter((day) => day.isClicked).map((day) => day.date);
setDays(selectedDays);
}, [dayList]);

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.placeholder === '방이름') setRoomName(e.target.value);
if (e.target.placeholder === '과목명') setSubject(e.target.value);
};

const handleCheck = (id: number) => {
if (id >= 3 && id <= 7) return;
else if (id < 5)
setparentP(parentP.map((type) => (id === type.id ? { ...type, isChecked: !type.isChecked } : type)));
else if (id >= 5)
setstudentP(studentP.map((type) => (id === type.id ? { ...type, isChecked: !type.isChecked } : type)));
};
console.log(rooms);

const handleCreate = (
roomName: string,
subject: string,
days: string[],
pMaterials: boolean,
pHomework: boolean,
pStats: boolean,
sCounseling: boolean,
sPayment: boolean,
) => {
onCreate(
roomName,
subject,
days,
parentP[0].isChecked,
parentP[1].isChecked,
parentP[2].isChecked,
studentP[3].isChecked,
studentP[4].isChecked,
);
navigate('/user/roomlist');
};
return (
<div className="flex flex-col gap-16">
<input placeholder="방이름" onChange={handleChange} value={roomName} />
<input placeholder="과목명" onChange={handleChange} value={subject} />
<div className="flex gap-4 justify-center">
{dayList.map((day) => (
<SelectDate key={day.id} day={day} handleClick={handleClick} />
))}
</div>
<div className="flex justify-between">
<div className="flex flex-col">
<h1>학부모 권한설정</h1>
{parentP.map((type) => (
<PermissionToggle key={type.id} type={type} handleCheck={handleCheck} />
))}
</div>
<div className="flex flex-col">
<h1>학생 권한설정</h1>
{studentP.map((type) => (
<PermissionToggle key={type.id} type={type} handleCheck={handleCheck} />
))}
</div>
</div>

<button
onClick={() =>
handleCreate(
roomName,
subject,
days,
parentP[0].isChecked,
parentP[1].isChecked,
parentP[2].isChecked,
studentP[3].isChecked,
studentP[4].isChecked,
)
}
className="text-white"
>
완료
</button>
</div>
);
};
export default CreateRoom;
23 changes: 22 additions & 1 deletion src/pages/RoomList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
import { useNavigate } from 'react-router-dom';
import RoomInfo from '../components/RoomInfo';
import { useRoomContext } from '../context/RoomContext';

const RoomList = () => {
return <div>RoomList</div>;
const navigate = useNavigate();
const { rooms } = useRoomContext();
console.log(rooms);

return (
<div className="flex flex-col">
<div>
{rooms.map((room) => (
<RoomInfo key={room.id} room={room} />
))}
</div>
<div className="flex justify-end py-8">
<button onClick={() => navigate('createroom')} className="text-white px-4">
+ 과외방 개설
</button>
</div>
</div>
);
};

export default RoomList;
2 changes: 2 additions & 0 deletions src/routes/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Homework from '../pages/Homework';
import CounselingDiary from '../pages/CounselingDiary';
import Payment from '../pages/Payment';
import Statistics from '../pages/Statistics';
import CreateRoom from '../pages/CreateRoom';
import KakaoOauth from '../components/KakaoOauth';

export const router = createBrowserRouter([
Expand Down Expand Up @@ -42,6 +43,7 @@ export const router = createBrowserRouter([
path: 'roomlist',
children: [
{ index: true, element: <RoomList /> },
{ path: 'createroom', element: <CreateRoom /> },
{
path: ':roomId',
children: [
Expand Down

0 comments on commit b04a946

Please sign in to comment.