Skip to content
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"next-pwa": "^5.6.0",
"react": "^18",
"react-dom": "^18",
"react-hot-toast": "^2.5.2",
"react-router-dom": "^6.24.0",
"shadcn-ui": "^0.9.4",
"swiper": "^11.2.4",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import Sidebar from 'src/components/desktop/Sidebar';
import Sidebar from '@/components/desktop/Sidebar';
import { useState, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { useMutation, useQuery } from '@tanstack/react-query';
Expand All @@ -13,9 +13,10 @@ import {
import { Admins } from '@/types/admins';
import { SearchInput } from '@/components/ui/search-input';
import { PageChangeAction } from '@/types/paginationType';
import toast from 'react-hot-toast';
import TableComponent from './_components/AdminTable';

export default function PayerInquiryPage() {
export default function AdminInquiryPage() {
const [isDeleteModeOriginal, setIsDeleteModeOriginal] = useState(false);
const [, setIsDeleteModeAdded] = useState(false);
const [selectedOriginal, setSelectedOriginal] = useState<number[]>([]);
Expand All @@ -41,19 +42,19 @@ export default function PayerInquiryPage() {
const deleteMutation = useMutation({
mutationFn: deleteAdmins,
onSuccess: () => {
alert('선택된 관리자 정보가 성공적으로 삭제되었습니다.');
toast.success('선택된 관리자 정보가 성공적으로 삭제되었습니다.');
refetch();
},
onError: () => alert('관리자 정보 삭제에 실패했습니다.'),
onError: () => toast.error('관리자 정보 삭제에 실패했습니다.'),
});

const mutation = useMutation({
mutationFn: addAdmins,
onSuccess: () => {
alert('추가된 관리자 정보가 성공적으로 저장되었습니다.');
toast.success('추가된 관리자 정보가 성공적으로 저장되었습니다.');
refetch();
},
onError: () => alert('추가된 관리자 정보 저장에 실패했습니다.'),
onError: () => toast.error('추가된 관리자 정보 저장에 실패했습니다.'),
});

useEffect(() => {
Expand Down Expand Up @@ -104,12 +105,12 @@ export default function PayerInquiryPage() {
const handleApply = () => {
if (!memberData || !Array.isArray(memberData.members)) {
console.error('memberData가 올바른 형식이 아닙니다.', memberData);
alert('데이터를 불러오는 중입니다. 잠시 후 다시 시도해주세요.');
toast.loading('데이터를 불러오는 중입니다. 잠시 후 다시 시도해주세요.');
return;
}

if (selectedAdded.length === 0) {
alert('추가할 관리자를 선택해주세요.');
toast.error('추가할 관리자를 선택해주세요.');
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import {
} from '@/components/ui/table';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Item, ItemTableProps } from '@/types/items';
import { Item, ItemTableProps, ItemTypeText } from '@/types/items';
import Image from 'next/image';
import { PageChangeAction } from '@/types/paginationType';

export default function ItemTable({
items = [],
showCheckboxes = true,
headers = ['로고', '물품명', '소모품', '총 수량', '대여 중'],
headers = ['로고', '물품명', '소모품/대여품', '총 수량', '대여 중'],
selected,
setSelected,
currentPage = 1,
Expand Down Expand Up @@ -91,7 +91,7 @@ export default function ItemTable({
{item.itemName}
</TableCell>
<TableCell className="w-30 text-center">
{item.itemType ? 'RENTAL' : 'CONSUMPTION'}
{ItemTypeText[item.itemType]}
</TableCell>
<TableCell className="w-30 text-center">{item.count}</TableCell>
<TableCell className="w-30 text-center">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
'use client';

import Sidebar from 'src/components/desktop/Sidebar';
import Sidebar from '@/components/desktop/Sidebar';
import { useState, useCallback, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { getItems, addItems, deleteItems } from '@/services/items';
import { SearchInput } from '@/components/ui/search-input';
import Image from 'next/image';
import { PageChangeAction } from '@/types/paginationType';
import toast from 'react-hot-toast';
import TableComponent from './_components/ItemTable';

export default function ItemListPage() {
Expand All @@ -28,21 +29,21 @@ export default function ItemListPage() {
const mutation = useMutation({
mutationFn: addItems,
onSuccess: () => {
alert('물품 등록이 완료되었습니다.');
toast.success('물품 등록이 완료되었습니다.');
queryClient.invalidateQueries({ queryKey: ['items'] });
},
onError: () => {
alert('물품 등록에 실패했습니다.');
toast.error('물품 등록에 실패했습니다.');
},
});

const deleteMutation = useMutation({
mutationFn: deleteItems,
onSuccess: () => {
alert('선택된 물품이 삭제되었습니다.');
toast.success('선택된 물품이 삭제되었습니다.');
},
onError: () => {
alert('물품 삭제에 실패했습니다.');
toast.error('물품 삭제에 실패했습니다.');
},
});

Expand All @@ -56,7 +57,7 @@ export default function ItemListPage() {
const { itemName, quantity, selectedImage, isConsumable } = formData;

if (!itemName || quantity === '' || quantity <= 0) {
alert('모든 정보를 입력하세요.');
toast.error('모든 정보를 입력하세요.');
return;
}

Expand Down Expand Up @@ -97,11 +98,9 @@ export default function ItemListPage() {
};

const handlePageChange = async (pageChangeAction: PageChangeAction) => {
console.log('PageChange:', pageChangeAction);
setPage((current) =>
pageChangeAction === 'NEXT' ? current + 1 : current - 1,
);
console.log(`page: ${page}`);
};
// 삭제 모드 토글
const toggleDeleteMode = () => {
Expand All @@ -112,7 +111,7 @@ export default function ItemListPage() {
// 물품 삭제 핸들러
const handleDeleteItem = () => {
if (selectedItem === null) {
alert('삭제할 물품을 선택해 주세요.');
toast.error('삭제할 물품을 선택해 주세요.');
return;
}

Expand Down
20 changes: 20 additions & 0 deletions src/app/desktop/(nav-bar)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use client';

import useAuthRedirect from '@/hooks/useAuthRedirect';
import React from 'react';
import NavBar from '@/components/desktop/NavBar/NavBar';

interface NavBarLayoutProps {
children: React.ReactNode;
}

export default function NavBarLayout({ children }: NavBarLayoutProps) {
useAuthRedirect();

return (
<div>
<NavBar />
{children}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import Sidebar from 'src/components/desktop/Sidebar';
import Sidebar from '@/components/desktop/Sidebar';
import { useState, useEffect } from 'react';
import AddStudentId from '@/components/desktop/AddStudentId';
import { Button } from '@/components/ui/button';
Expand All @@ -9,8 +9,9 @@ import { getPayer, addPayer, deletePayer } from '@/services/payers';
import { Payer } from '@/types/payers';
import { SearchInput } from '@/components/ui/search-input';
import { PageChangeAction } from '@/types/paginationType';
import toast from 'react-hot-toast';
import TableComponent from './_components/TableComponent';
import AddInput from '../../../components/desktop/AddInput';
import AddInput from '../../../../components/desktop/AddInput';

export default function PayerInquiryPage() {
const [searchQuery, setSearchQuery] = useState('');
Expand All @@ -37,24 +38,24 @@ export default function PayerInquiryPage() {
const mutation = useMutation({
mutationFn: addPayer,
onSuccess: () => {
alert('추가된 납부자 정보가 성공적으로 저장되었습니다.');
toast.success('추가된 납부자 정보가 성공적으로 저장되었습니다.');
setAddedData([]);
refetch();
},
onError: () => {
alert('추가된 납부자 정보 저장에 실패했습니다.');
toast.error('추가된 납부자 정보 저장에 실패했습니다.');
},
});

const deleteMutation = useMutation({
mutationFn: deletePayer,
onSuccess: () => {
alert('선택된 납부자 정보가 성공적으로 삭제되었습니다.');
toast.success('선택된 납부자 정보가 성공적으로 삭제되었습니다.');
setAddedData([]);
refetch();
},
onError: () => {
alert('납부자 정보 삭제에 실패했습니다.');
toast.error('납부자 정보 삭제에 실패했습니다.');
},
});

Expand Down Expand Up @@ -84,13 +85,13 @@ export default function PayerInquiryPage() {

const handleAddStudent = () => {
if (!newStudentId || !newStudentName) {
alert('이름과 학번을 입력해주세요.');
toast.error('이름과 학번을 입력해주세요.');
return;
}

const studentIdPattern = /^\d{8}$/;
if (!studentIdPattern.test(newStudentId)) {
alert('학번은 8자리 숫자로 입력해야 합니다.');
toast.error('학번은 8자리 숫자로 입력해야 합니다.');
return;
}

Expand Down Expand Up @@ -120,11 +121,9 @@ export default function PayerInquiryPage() {
};

const handlePageChange = async (pageChangeAction: PageChangeAction) => {
console.log('PageChange:', pageChangeAction);
setPage((current) =>
pageChangeAction === 'NEXT' ? current + 1 : current - 1,
);
console.log(`page: ${page}`);
};

const toggleDeleteMode = (mode: 'original' | 'added') => {
Expand Down
13 changes: 7 additions & 6 deletions src/app/desktop/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
'use client';

import useAuthRedirect from '@/hooks/useAuthRedirect';
import React from 'react';
import { Toaster } from 'react-hot-toast';

interface DesktopLayoutProps {
children: React.ReactNode;
}

export default function DesktopLayout({ children }: DesktopLayoutProps) {
useAuthRedirect();

return <div>{children}</div>;
return (
<div>
<Toaster />
{children}
</div>
);
}
69 changes: 48 additions & 21 deletions src/app/desktop/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import axios from 'axios';
import { postAdminLogin } from '@/services/admins';
import { handleLoginSuccess } from '@/utils/loginHandler';
import { useRouter } from 'next/navigation';
import toast from 'react-hot-toast';

export default function Login() {
const router = useRouter();
Expand All @@ -14,50 +15,76 @@ export default function Login() {

const validateLoginForm = (studentId: string, password: string) => {
if (!studentId) {
alert('학번을 입력해 주세요!');
toast.error('학번을 입력해 주세요!');
return false;
}

if (!password) {
alert('비밀번호를 입력해 주세요!');
toast.error('비밀번호를 입력해 주세요!');
return false;
}

const idRegex = /^\d{8}$/;
if (!idRegex.test(studentId)) {
alert('학번은 숫자 8자리여야 합니다.');
toast.error('학번은 숫자 8자리여야 합니다.');
return false;
}

return true;
};

const handleAdminLogin = async () => {
const handleAdminLogin = async (
event: React.MouseEvent<HTMLElement, MouseEvent>,
) => {
event.preventDefault();

const studentId = studentIdRef?.current?.value || '';
const password = passwordRef?.current?.value || '';

if (!validateLoginForm(studentId, password)) return;

try {
const data = await postAdminLogin({
studentId,
password,
});
await toast.promise(
postAdminLogin({ studentId, password }).then((data) => {
handleLoginSuccess(data.accessToken);
router.push('/desktop/rental-history');
}),
{
loading: '로그인 중...',
success: '로그인에 성공했습니다!',
error: (error) => {
if (axios.isAxiosError(error)) {
const errorResponse = error.response?.data;

handleLoginSuccess(data.accessToken);
router.push('/desktop/rental-history');
} catch (error) {
if (axios.isAxiosError(error)) {
const errorResponse = error.response?.data;
if (errorResponse) {
return errorResponse.message;
}
}

if (!errorResponse) {
alert('관리자 로그인 중 오류가 발생했습니다!');
return;
}
return '관리자 로그인 중 오류가 발생했습니다!';
},
},
);

alert(errorResponse.message);
}
}
// try {
// const data = await postAdminLogin({
// studentId,
// password,
// });
//
// handleLoginSuccess(data.accessToken);
// router.push('/desktop/rental-history');
// } catch (error) {
// if (axios.isAxiosError(error)) {
// const errorResponse = error.response?.data;
//
// if (!errorResponse) {
// toast.error('관리자 로그인 중 오류가 발생했습니다!');
// return;
// }
//
// toast.error(errorResponse.message);
// }
// }
};

return (
Expand Down
Empty file.
Loading