Skip to content

Commit c4111fa

Browse files
committed
학사 및 교과 하위 편집 기능 수정
1 parent 2ba183f commit c4111fa

File tree

9 files changed

+172
-17
lines changed

9 files changed

+172
-17
lines changed

app/routes.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,15 @@ const getLocaleRoutes = (locale: Locale) => {
140140
),
141141
route(
142142
'/general-studies-requirements',
143-
'routes/academics/undergraduate/general-studies-requirements.tsx',
143+
'routes/academics/undergraduate/general-studies-requirements/index.tsx',
144+
),
145+
route(
146+
'/general-studies-requirements/create',
147+
'routes/academics/undergraduate/general-studies-requirements/create.tsx',
148+
),
149+
route(
150+
'/general-studies-requirements/edit/:year',
151+
'routes/academics/undergraduate/general-studies-requirements/edit.$year.tsx',
144152
),
145153
route(
146154
'/degree-requirements',

app/routes/academics/$studentType/course-changes/create.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export default function CourseChangesCreatePage({
3030
const onSubmit = async (data: TimelineFormData) => {
3131
const formData = new FormData2();
3232
formData.appendJson('request', {
33+
name: '',
3334
year: data.year,
3435
description: data.description,
3536
});

app/routes/academics/$studentType/scholarship/$id/edit.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default function ScholarshipEditPage({
4040

4141
const onSubmit = async (content: ScholarshipFormData) => {
4242
try {
43-
await fetchOk(`${BASE_URL}/v2/academics/scholarship/${id}`, {
43+
await fetchOk(`${BASE_URL}/v2/academics/scholarship`, {
4444
method: 'PUT',
4545
headers: { 'Content-Type': 'application/json' },
4646
body: JSON.stringify({

app/routes/academics/$studentType/scholarship/create.tsx

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,7 @@ export default function ScholarshipCreatePage({
3131
await fetchOk(`${BASE_URL}/v2/academics/${studentType}/scholarship`, {
3232
method: 'POST',
3333
headers: { 'Content-Type': 'application/json' },
34-
body: JSON.stringify({
35-
ko: {
36-
name: content.koName,
37-
description: content.koDescription,
38-
},
39-
en: {
40-
name: content.enName,
41-
description: content.enDescription,
42-
},
43-
}),
34+
body: JSON.stringify(content),
4435
});
4536
toast.success(t('장학금을 추가했습니다.'));
4637
navigate(`/academics/${studentType}/scholarship`);

app/routes/academics/components/timeline/TimelineViewer.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { useReducer, useState } from 'react';
22
import { Link, useLocation, useRevalidator } from 'react-router';
33
import { toast } from 'sonner';
4+
import LoginVisible from '~/components/feature/auth/LoginVisible';
45
import AlertDialog from '~/components/ui/AlertDialog';
56
import Attachments from '~/components/ui/Attachments';
67
import Button from '~/components/ui/Button';
78
import HTMLViewer from '~/components/ui/HTMLViewer';
8-
import LoginVisible from '~/components/feature/auth/LoginVisible';
9+
import { BASE_URL } from '~/constants/api';
910
import { useLanguage } from '~/hooks/useLanguage';
1011
import type { TimelineContent } from '~/types/api/v2/academics';
1112
import { fetchOk } from '~/utils/fetch';
@@ -104,7 +105,7 @@ function ActionButtons({ year, pathname }: { year: number; pathname: string }) {
104105

105106
const handleDelete = async () => {
106107
try {
107-
await fetchOk(`/v2${pathname}/${year}`, { method: 'DELETE' });
108+
await fetchOk(`/api/v2${pathname}/${year}`, { method: 'DELETE' });
108109
setShowDeleteDialog(false);
109110
toast.success('삭제에 성공했습니다.');
110111
revalidator.revalidate();

app/routes/academics/undergraduate/curriculum/edit.$year.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,17 @@ export async function loader({ params }: LoaderFunctionArgs) {
2020
throw new Error('Year parameter is required');
2121
}
2222

23-
return fetchJson<TimelineContent>(
24-
`${BASE_URL}/v2/academics/undergraduate/curriculum/${year}`,
23+
const data = await fetchJson<TimelineContent[]>(
24+
`${BASE_URL}/v2/academics/undergraduate/curriculum`,
2525
);
26+
const yearNum = Number(year);
27+
const selected = data.find((item) => item.year === yearNum);
28+
29+
if (!selected) {
30+
throw new Response('해당 연도 내용이 존재하지 않습니다.', { status: 404 });
31+
}
32+
33+
return selected;
2634
}
2735

2836
export default function CurriculumEditPage({
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { useNavigate } from 'react-router';
2+
import { toast } from 'sonner';
3+
import PageLayout from '~/components/layout/PageLayout';
4+
import { BASE_URL } from '~/constants/api';
5+
import { useLanguage } from '~/hooks/useLanguage';
6+
import { useAcademicsSubNav } from '~/hooks/useSubNav';
7+
import TimelineEditor, {
8+
type TimelineFormData,
9+
} from '~/routes/academics/components/timeline/TimelineEditor';
10+
import { fetchOk } from '~/utils/fetch';
11+
import { FormData2 } from '~/utils/form';
12+
13+
export default function GeneralStudiesCreatePage() {
14+
const { t } = useLanguage({ '필수 교양 과목 추가': 'Add General Studies' });
15+
const subNav = useAcademicsSubNav();
16+
const navigate = useNavigate();
17+
18+
const title = t('필수 교양 과목 추가');
19+
const onSubmit = async (data: TimelineFormData) => {
20+
const formData = new FormData2();
21+
formData.appendJson('request', {
22+
year: data.year,
23+
description: data.description,
24+
name: '', // TODO: 백엔드에서 name 필드 제거 필요
25+
});
26+
formData.appendIfLocal('attachments', data.file);
27+
28+
try {
29+
await fetchOk(
30+
`${BASE_URL}/v2/academics/undergraduate/general-studies-requirements`,
31+
{
32+
method: 'POST',
33+
body: formData,
34+
},
35+
);
36+
toast.success('추가에 성공했습니다.');
37+
navigate('/academics/undergraduate/general-studies-requirements');
38+
} catch {
39+
toast.error('추가에 실패했습니다.');
40+
}
41+
};
42+
43+
return (
44+
<PageLayout title={title} titleSize="xl" subNav={subNav}>
45+
<TimelineEditor
46+
onSubmit={onSubmit}
47+
cancelPath="/academics/undergraduate/general-studies-requirements"
48+
/>
49+
</PageLayout>
50+
);
51+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import type { Route } from '.react-router/types/app/routes/academics/undergraduate/general-studies-requirements/+types/edit.$year';
2+
import type { LoaderFunctionArgs } from 'react-router';
3+
import { useNavigate } from 'react-router';
4+
import { toast } from 'sonner';
5+
import PageLayout from '~/components/layout/PageLayout';
6+
import { BASE_URL } from '~/constants/api';
7+
import { useLanguage } from '~/hooks/useLanguage';
8+
import { useAcademicsSubNav } from '~/hooks/useSubNav';
9+
import TimelineEditor, {
10+
type TimelineFormData,
11+
} from '~/routes/academics/components/timeline/TimelineEditor';
12+
import type { TimelineContent } from '~/types/api/v2/academics';
13+
import { fetchJson, fetchOk } from '~/utils/fetch';
14+
import { FormData2, getDeleteIds } from '~/utils/form';
15+
16+
export async function loader({ params }: LoaderFunctionArgs) {
17+
const { year } = params;
18+
19+
if (!year) {
20+
throw new Error('Year parameter is required');
21+
}
22+
23+
const data = await fetchJson<TimelineContent[]>(
24+
`${BASE_URL}/v2/academics/undergraduate/general-studies-requirements`,
25+
);
26+
const yearNum = Number(year);
27+
const selected = data.find((item) => item.year === yearNum);
28+
29+
if (!selected) {
30+
throw new Response('해당 연도 내용이 존재하지 않습니다.', { status: 404 });
31+
}
32+
33+
return selected;
34+
}
35+
36+
export default function GeneralStudiesEditPage({
37+
loaderData: initContent,
38+
}: Route.ComponentProps) {
39+
const { t } = useLanguage({
40+
'필수 교양 과목 편집': 'Edit General Studies',
41+
});
42+
const subNav = useAcademicsSubNav();
43+
const navigate = useNavigate();
44+
45+
const title = t('필수 교양 과목 편집');
46+
const defaultValues: TimelineFormData = {
47+
year: initContent.year,
48+
description: initContent.description,
49+
file: initContent.attachments.map(
50+
(file: TimelineContent['attachments'][number]) => ({
51+
type: 'UPLOADED_FILE' as const,
52+
file,
53+
}),
54+
),
55+
};
56+
57+
const onSubmit = async (data: TimelineFormData) => {
58+
const deleteIds = getDeleteIds({
59+
prev: defaultValues.file,
60+
cur: data.file,
61+
});
62+
63+
const formData = new FormData2();
64+
formData.appendJson('request', {
65+
description: data.description,
66+
deleteIds,
67+
});
68+
formData.appendIfLocal('newAttachments', data.file);
69+
70+
try {
71+
await fetchOk(
72+
`${BASE_URL}/v2/academics/undergraduate/general-studies-requirements/${initContent.year}`,
73+
{
74+
method: 'PUT',
75+
body: formData,
76+
},
77+
);
78+
79+
toast.success('수정에 성공했습니다.');
80+
navigate('/academics/undergraduate/general-studies-requirements');
81+
} catch {
82+
toast.error('수정에 실패했습니다.');
83+
}
84+
};
85+
86+
return (
87+
<PageLayout title={title} titleSize="xl" subNav={subNav}>
88+
<TimelineEditor
89+
onSubmit={onSubmit}
90+
cancelPath="/academics/undergraduate/general-studies-requirements"
91+
defaultValues={defaultValues}
92+
/>
93+
</PageLayout>
94+
);
95+
}

app/routes/academics/undergraduate/general-studies-requirements.tsx renamed to app/routes/academics/undergraduate/general-studies-requirements/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Route } from '.react-router/types/app/routes/academics/undergraduate/+types/general-studies-requirements';
1+
import type { Route } from '.react-router/types/app/routes/academics/undergraduate/general-studies-requirements/+types/index';
22
import PageLayout from '~/components/layout/PageLayout';
33
import { BASE_URL } from '~/constants/api';
44
import { useLanguage } from '~/hooks/useLanguage';

0 commit comments

Comments
 (0)