Skip to content

Commit

Permalink
Merge pull request #69 from hanaro-on-and-on/feat/#24
Browse files Browse the repository at this point in the history
Feat/#24 캘린더 세부일정 구현
  • Loading branch information
ShinKwang2 authored Jul 2, 2024
2 parents 69bb60f + c985fe3 commit 1042aea
Show file tree
Hide file tree
Showing 22 changed files with 895 additions and 28 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
"dependencies": {
"axios": "^1.7.2",
"clsx": "^2.1.1",
"date-fns": "^3.6.0",
"react": "^18.3.1",
"react-calendar": "^5.0.0",
"react-dom": "^18.3.1",
"react-icons": "^5.2.1",
"react-kakao-maps-sdk": "^1.1.27",
"react-router-dom": "^6.24.0",
"swiper": "^11.1.4",
"react-kakao-maps-sdk": "^1.1.27"
"react-signature-canvas": "^1.0.6"
},
"devDependencies": {
Expand Down
14 changes: 14 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Route, Routes } from 'react-router-dom';
import './App.css';
import Test from './pages/test';
import UiTest from './pages/UiTest';
import OwnerMainPage from './pages/OwnerMainPage';
import CalendarCustom from './components/ui/CalendarCustom';
import DateDetail from './components/calendar-owner/DateDetail';
import AttendanceEdit from './components/calendar-owner/AttendanceEdit';
import PaymentMain from './pages/employee/PartTimeTab/PaymentMain';
import WorkTime from './pages/employee/PartTimeTab/WorkTime';
import Payment from './pages/employee/PartTimeTab/Payment';
Expand All @@ -21,6 +26,15 @@ function App() {
<Routes>
<Route path='/' element={<LandingPage />} />
<Route path='/test' element={<Test />} />
<Route path='/ui' element={<UiTest />} />
<Route path='/owner/*' element={<OwnerMainPage />}>
<Route path='calendar' element={<CalendarCustom />} />
<Route path='calendar/:date' element={<DateDetail />} />
<Route
path='calendar/attendance/:id/edit'
element={<AttendanceEdit />}
/>
</Route>
<Route path='/owner-calendar' element={<OwnerCalendarPage />} />
<Route path='/part-time/*' element={<PaymentMain />}>
<Route path='worktime' element={<WorkTime />} />
Expand Down
71 changes: 71 additions & 0 deletions src/components/calendar-owner/AttendanceEdit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { useState } from 'react';
import { useAttendance } from '../../contexts/Attendance-Context';
import InputBox from '../ui/InputBox';
import { VStack } from '../ui/Stack';
import TimeBox from './TimeBox';
import WorkPlaceName from '../ui/WorkPlaceName';
import SelectOptions from './SelectOptions';
import Select from './Select';

const mockData = [
{
workPlaceId: 1, // Long
workPlaceNm: '롯데리아 자양점',
workPlaceColor: '01', // String
workPlaceEmployeeId: 1, // Long
employeeNm: '이신광', // String
},
{
workPlaceId: 1, // Long
workPlaceNm: '롯데리아 자양점',
workPlaceColor: '01', // String
workPlaceEmployeeId: 2, // Long
employeeNm: '이서하', // String
},
{
workPlaceId: 1, // Long
workPlaceNm: '롯데리아 자양점',
workPlaceColor: '01',
workPlaceEmployeeId: 3, // Long
employeeNm: '정연주', // String
},
{
workPlaceId: 2, // Long
workPlaceNm: '버거킹',
workPlaceColor: '02', // String
workPlaceEmployeeId: 4, // Long
employeeNm: '고영우', // String
},
{
workPlaceId: 2, // Long
workPlaceNm: '버거킹',
workPlaceColor: '02', // String
workPlaceEmployeeId: 5, // Long
employeeNm: '최은진', // String
},
];

const AttendanceEdit = () => {
const [workEmployeeList, setWorkEmployeeList] = useState(mockData);

const { attendance, changeAttendance } = useAttendance();
const [employeeId, setEmployeeId] = useState(attendance?.workPlaceEmployeeId);
const [startTime, setStartTime] = useState(attendance?.startTime);
const [endTime, setEndTime] = useState(attendance?.endTime);
const [payPerHour, setPayPerHour] = useState(attendance?.payPerHour);

console.log(attendance);

return (
<VStack className='px-6 py-10 gap-6'>
<InputBox label='근무자명'>
<Select options={workEmployeeList} />
</InputBox>
<InputBox label='근무 시간'>
<TimeBox />
</InputBox>
<InputBox label='시급' value={String(payPerHour)} />
</VStack>
);
};
export default AttendanceEdit;
94 changes: 94 additions & 0 deletions src/components/calendar-owner/DateDetail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { useNavigate, useParams } from 'react-router-dom';
import { useCalendarData } from '../../contexts/Calender-Data-Context';
import { HStack, VStack } from '../ui/Stack';
import WorkPlaceName from '../ui/WorkPlaceName';
import { getTimeString } from '../../utils/get-TimeString';
import { FaAngleRight } from 'react-icons/fa6';
import { AiOutlineAccountBook, AiOutlinePlusCircle } from 'react-icons/ai';
import { useAttendance } from '../../contexts/Attendance-Context';
import { DateWorkDetail } from '../../types/calendar';
export type Attendance = {
attendanceId?: number;
workPlaceEmployeeId: number;
payPerHour: number; // 시급
startTime: Date; // 시작 시간
endTime: Date; // 끝 시간
restStartTime: Date;
restEndTime: Date;
};
const onClickChangeAttendance = (data: DateWorkDetail) => {
return {
attendenceId: data.attendanceId,
workPlaceEmployeeId: data.workPlaceEmployeeId,
payPerHour: data.payPerHour,
startTime: data.startTime,
endTime: data.endTime,
restStartTime: new Date(),
restEndTime: new Date(),
};
};

const DateDetail = () => {
const { date } = useParams();
const navigate = useNavigate();
const { calendarData, getFilteredData } = useCalendarData();
const { changeAttendance } = useAttendance();

const onClickEditAttendance = (attendanceId: number) => {
navigate(`/owner/calendar/attendance/${attendanceId}/edit`);
};

const targetDate = new Date(date!);

const temp = getFilteredData(targetDate);
console.log(temp);

return (
<div className='px-6'>
<h2>Selected Date: {date}</h2>

<VStack className='gap-3'>
<HStack className='justify-between items-center'>
<div>총 근무 시간: 8시간</div>
<button className='bg-hanaLightGreen gap-2 py-1 px-2 flex items-center rounded-lg text-white'>
<AiOutlinePlusCircle />
<div>근무 추가</div>
</button>
</HStack>

{temp.map((item) => (
<button
key={item.attendanceId}
onClick={() => {
changeAttendance({
attendanceId: item.attendanceId,
workPlaceEmployeeId: item.workPlaceEmployeeId,
payPerHour: item.payPerHour,
startTime: item.startTime,
endTime: item.endTime,
restStartTime: new Date(),
restEndTime: new Date(),
}),
onClickEditAttendance(item.attendanceId);
}}
className='px-1 py-3 w-full rounded-lg border border-hanaLightGreen bg-white'
>
<HStack className='justify-around items-center'>
<WorkPlaceName
name={`${item.workPlaceName}`}
colorType={`${item.workPlaceColor}`}
/>
<VStack className=''>
<div className='text-lg'>{`${item.employeeName}`}</div>
<div className='text-sm'>{`${getTimeString(item.startTime)} - ${getTimeString(temp[0].endTime)}`}</div>
</VStack>
<FaAngleRight />
</HStack>
</button>
))}
</VStack>
</div>
);
};

export default DateDetail;
49 changes: 49 additions & 0 deletions src/components/calendar-owner/Select.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { FaAngleDown } from 'react-icons/fa6';
import WorkPlaceName from '../ui/WorkPlaceName';
import SelectBox from './SelectBox';
import { useState } from 'react';

type SelectProps = {
options: [];
};

const Select = ({ options }: SelectProps) => {
const [selected, setSelected] = useState({
workPlaceId: 1, // Long
workPlaceNm: '롯데리아 자양점',
workPlaceColor: '01', // String
workPlaceEmployeeId: 1, // Long
employeeNm: '이신광', // String
});
const [showList, setShowList] = useState(false);

const onClickSelect = (data) => {
setSelected(data);
};

return (
<div className='w-full'>
<button
className='w-full bg-white border-b border-b-hanaLightGreen flex flex-row gap-2 justify-between items-center'
onClick={() => setShowList(!showList)}
>
<div className='w-1/2 px-1 py-2'>
<WorkPlaceName
name={selected.workPlaceNm}
colorType={selected.workPlaceColor}
/>
</div>
<div className='w-1/2'>{selected.employeeNm}</div>
<FaAngleDown />
</button>
<SelectBox
isOpen={showList}
options={options}
onClose={() => setShowList(false)}
onClick={onClickSelect}
/>
</div>
);
};

export default Select;
88 changes: 88 additions & 0 deletions src/components/calendar-owner/SelectBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { useState } from 'react';
import { HStack, VStack } from '../ui/Stack';
import WorkPlaceName from '../ui/WorkPlaceName';
import { FaAngleDown } from 'react-icons/fa6';

const mockData = [
{
workPlaceId: 1, // Long
workPlaceNm: '롯데리아 자양점',
workPlaceColor: '01', // String
workPlaceEmployeeId: 1, // Long
employeeNm: '이신광', // String
},
{
workPlaceId: 1, // Long
workPlaceNm: '롯데리아 자양점',
workPlaceColor: '01', // String
workPlaceEmployeeId: 2, // Long
employeeNm: '이서하', // String
},
{
workPlaceId: 1, // Long
workPlaceNm: '롯데리아 자양점',
workPlaceColor: '01',
workPlaceEmployeeId: 3, // Long
employeeNm: '정연주', // String
},
{
workPlaceId: 2, // Long
workPlaceNm: '버거킹',
workPlaceColor: '02', // String
workPlaceEmployeeId: 4, // Long
employeeNm: '고영우', // String
},
{
workPlaceId: 2, // Long
workPlaceNm: '버거킹',
workPlaceColor: '02', // String
workPlaceEmployeeId: 5, // Long
employeeNm: '최은진', // String
},
];

type SelectBoxProps = {
isOpen: boolean;
options: {
workPlaceId: number;
workPlaceNm: string;
workPlaceColor: string;
workPlaceEmployeeId: number;
employeeNm: string;
}[];
onClose: () => void;
onClick: (data) => void;
};

const SelectBox = ({ isOpen, options, onClose, onClick }: SelectBoxProps) => {
if (!isOpen) return null;

return (
<div className='w-full border overflow-y-scroll rounded-b-xl'>
<VStack>
{options.map((data) => (
<button
key={data.workPlaceEmployeeId}
onClick={() => {
onClick(data);
onClose();
}}
className='bg-white'
>
<HStack className='items-center justify-between'>
<div className='w-1/2 p-2'>
<WorkPlaceName
name={data.workPlaceNm}
colorType={data.workPlaceColor}
/>
</div>
<div className='w-1/2'>{data.employeeNm}</div>
</HStack>
</button>
))}
</VStack>
</div>
);
};

export default SelectBox;
33 changes: 33 additions & 0 deletions src/components/calendar-owner/TimeBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { CgBorderStyleSolid } from 'react-icons/cg';
import { HStack, VStack } from '../ui/Stack';
import { FaAngleDown } from 'react-icons/fa6';

const TimeBox = () => {
return (
<VStack className='mx-auto'>
<HStack className='justify-center items-center'>
<div className='font-semibold text-sm me-3'>근무 시간</div>
<HStack className='border-b-2 border-b-black font-bold items-center'>
10:30
<FaAngleDown />
</HStack>
<CgBorderStyleSolid />
<HStack className='border-b-2 border-b-black font-bold items-center'>
20:00 <FaAngleDown />
</HStack>
</HStack>
<HStack className='justify-center items-center'>
<div className='font-semibold text-sm me-3'>휴게 시간</div>
<HStack className='border-b-2 border-b-black font-bold items-center'>
18:00 <FaAngleDown />
</HStack>
<CgBorderStyleSolid />
<HStack className='border-b-2 border-b-black font-bold items-center'>
18:30 <FaAngleDown />
</HStack>
</HStack>
</VStack>
);
};

export default TimeBox;
Loading

0 comments on commit 1042aea

Please sign in to comment.