Skip to content

Commit 3b3ebf8

Browse files
authored
Merge pull request #165 from TEAM-COMFIT/refactor/#164/experience-detail-cleanup
[Refactor] experience-detail 구조 정리 및 내부 API 범위 축소
2 parents 9ed38bf + bf52d76 commit 3b3ebf8

13 files changed

Lines changed: 288 additions & 535 deletions

File tree

Lines changed: 6 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,15 @@
1-
export { DatePicker } from "./ui/date-picker/date-picker";
21
export { ExperienceForm } from "./ui/experience-form/experience-form";
32
export { ExperienceViewer } from "./ui/experience-viewer/experience-viewer";
43
export { ExperienceAlertRenderer } from "./ui/experience-alert-renderer/experience-alert-renderer";
54

6-
export {
7-
postExperience,
8-
usePostExperience,
9-
type PostExperienceResponse,
10-
} from "./api/use-post-experience.query";
5+
export { useGetExperienceDetail } from "./api/use-get-experience-detail.query";
116

12-
export {
13-
getExperienceDetail,
14-
useGetExperienceDetail,
15-
type GetExperienceDetailResponse,
16-
} from "./api/use-get-experience-detail.query";
17-
18-
export {
19-
patchExperience,
20-
usePatchExperience,
21-
} from "./api/use-patch-experience.query";
22-
23-
export {
24-
deleteExperience,
25-
useDeleteExperience as useDeleteExperienceMutation,
26-
} from "./api/use-delete-experience.query";
27-
28-
export {
29-
patchExperienceDefault,
30-
usePatchExperienceDefault,
31-
type PatchDefaultResponse,
32-
} from "./api/use-patch-experience-default.query";
33-
34-
export {
35-
useExperienceDetailStore,
36-
initialDraft,
37-
} from "./store/experience.store";
38-
39-
export {
40-
useExperienceMode,
41-
useExperienceCurrent,
42-
useExperienceDraft,
43-
useDefaultExperienceId,
44-
useExperienceActions,
45-
useIsDraftDefault,
46-
useDefaultButtonLabel,
47-
useShowEditDeleteButtons,
48-
useShowSubmitButton,
49-
useCurrentExperienceId,
50-
} from "./store/use-experience-hooks";
51-
52-
export {
53-
useExperienceSubmit,
54-
useExperienceHeaderActions,
55-
useDeleteExperience,
56-
} from "./model/use-actions";
57-
58-
export { useExperienceDateField } from "./model/use-experience-date-field";
59-
60-
export { formatDateDash, parseYMD } from "@/shared/lib/format-date";
61-
62-
export {
63-
showExperienceError,
64-
showExperienceSuccess,
65-
showExperienceInfo,
66-
showExperienceWarning,
67-
showValidationError,
68-
showSaveError,
69-
showDeleteError,
70-
showDefaultSettingError,
71-
showSaveSuccess,
72-
showDeleteSuccess,
73-
useExperienceAlerts,
74-
useExperienceAlertActions,
75-
} from "./model/use-alert";
7+
export { useExperienceMode } from "./store/use-experience-hooks";
768

779
export { useLeaveConfirm } from "./model/use-leave-confirm";
10+
export { initExperienceDetail } from "./model/use-init-experience-detail";
11+
export { applyExperienceDetailFromApi } from "./model/use-hydrate-experience";
7812

79-
export {
80-
useInitExperienceDetail,
81-
useResetExperienceDetail,
82-
initExperienceDetail,
83-
resetExperienceDetail,
84-
} from "./model/use-init-experience-detail";
85-
86-
export {
87-
useHydrateExperienceFromApi,
88-
hydrateExperienceFromApi,
89-
} from "./model/use-hydrate-experience";
90-
91-
export { toExperienceEntity } from "./lib/to-experience-entity";
92-
93-
export { validateExperienceDraft } from "./lib/validation";
94-
95-
export type {
96-
ExperienceMode,
97-
ExperienceType,
98-
ExperienceUpsertBody,
99-
ExperienceEntity,
100-
DefaultExperience,
101-
} from "./types/experience-detail.types";
13+
export type { ExperienceMode } from "./types/experience-detail.types";
10214

103-
export { EXPERIENCE_MESSAGES, DEFAULT_BUTTON_LABELS } from "./config/messages";
15+
export { EXPERIENCE_MESSAGES } from "./config/messages";

src/features/experience-detail/model/use-actions.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -225,12 +225,3 @@ export const useExperienceHeaderActions = () => {
225225
onToggleDefault,
226226
};
227227
};
228-
229-
export const useDeleteExperience = () => {
230-
const current = useExperienceCurrent();
231-
232-
return {
233-
targetExperience: current,
234-
canDelete: Boolean(current),
235-
};
236-
};

src/features/experience-detail/model/use-alert.ts

Lines changed: 40 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -16,90 +16,74 @@ interface ExperienceAlertState {
1616
actions: {
1717
show: (variant: AlertVariant, title: string, description: string) => void;
1818
close: (id: string) => void;
19-
closeAll: () => void;
2019
};
2120
}
2221

2322
let alertIdCounter = 0;
2423

25-
export const useExperienceAlertStore = create<ExperienceAlertState>(
26-
(set, get) => ({
27-
alerts: [],
28-
actions: {
29-
show: (variant, title, description) => {
30-
const { alerts } = get();
31-
const isDuplicate = alerts.some(
32-
(a) =>
33-
a.variant === variant &&
34-
a.title === title &&
35-
a.description === description
36-
);
37-
if (isDuplicate) return;
38-
39-
const id = `exp-alert-${++alertIdCounter}`;
40-
set((state) => ({
41-
alerts: [...state.alerts, { id, variant, title, description }],
42-
}));
43-
},
44-
close: (id) => {
45-
set((state) => ({
46-
alerts: state.alerts.filter((a) => a.id !== id),
47-
}));
48-
},
49-
closeAll: () => {
50-
set({ alerts: [] });
51-
},
24+
const useExperienceAlertStore = create<ExperienceAlertState>((set, get) => ({
25+
alerts: [],
26+
actions: {
27+
show: (variant, title, description) => {
28+
const { alerts } = get();
29+
const lastAlert = alerts[alerts.length - 1];
30+
31+
const isDuplicate =
32+
lastAlert != null &&
33+
lastAlert.variant === variant &&
34+
lastAlert.title === title &&
35+
lastAlert.description === description;
36+
37+
if (isDuplicate) return;
38+
39+
const id = `exp-alert-${++alertIdCounter}`;
40+
set((state) => ({
41+
alerts: [...state.alerts, { id, variant, title, description }],
42+
}));
5243
},
53-
})
54-
);
55-
56-
export const showExperienceError = (message: string) => {
57-
const { show } = useExperienceAlertStore.getState().actions;
58-
show("error", "오류", message);
59-
};
60-
61-
export const showExperienceSuccess = (message: string, title = "완료") => {
62-
const { show } = useExperienceAlertStore.getState().actions;
63-
show("success", title, message);
64-
};
65-
66-
export const showExperienceInfo = (message: string) => {
67-
const { show } = useExperienceAlertStore.getState().actions;
68-
show("info", "안내", message);
69-
};
7044

71-
export const showExperienceWarning = (message: string) => {
72-
const { show } = useExperienceAlertStore.getState().actions;
73-
show("warning", "주의", message);
45+
close: (id) => {
46+
set((state) => ({
47+
alerts: state.alerts.filter((a) => a.id !== id),
48+
}));
49+
},
50+
},
51+
}));
52+
53+
const showAlert = (
54+
variant: AlertVariant,
55+
title: string,
56+
description: string
57+
) => {
58+
useExperienceAlertStore.getState().actions.show(variant, title, description);
7459
};
7560

7661
export const showValidationError = (title: string, description: string) => {
77-
const { show } = useExperienceAlertStore.getState().actions;
78-
show("error", title, description);
62+
showAlert("error", title, description);
7963
};
8064

8165
export const showSaveError = () => {
82-
showExperienceError(EXPERIENCE_MESSAGES.API.SAVE_FAILED);
66+
showAlert("error", "오류", EXPERIENCE_MESSAGES.API.SAVE_FAILED);
8367
};
8468

8569
export const showDeleteError = () => {
86-
showExperienceError(EXPERIENCE_MESSAGES.API.DELETE_FAILED);
70+
showAlert("error", "오류", EXPERIENCE_MESSAGES.API.DELETE_FAILED);
8771
};
8872

8973
export const showDefaultSettingError = () => {
90-
showExperienceError(EXPERIENCE_MESSAGES.API.DEFAULT_SETTING_FAILED);
74+
showAlert("error", "오류", EXPERIENCE_MESSAGES.API.DEFAULT_SETTING_FAILED);
9175
};
9276

9377
export const showSaveSuccess = (title?: string) => {
94-
showExperienceSuccess(EXPERIENCE_MESSAGES.SUCCESS.SAVED, title);
78+
showAlert("success", title ?? "완료", EXPERIENCE_MESSAGES.SUCCESS.SAVED);
9579
};
9680

9781
export const showDeleteSuccess = () => {
98-
showExperienceSuccess(EXPERIENCE_MESSAGES.SUCCESS.DELETED);
82+
showAlert("success", "완료", EXPERIENCE_MESSAGES.SUCCESS.DELETED);
9983
};
10084

10185
export const useExperienceAlerts = () =>
10286
useExperienceAlertStore((s) => s.alerts);
10387

10488
export const useExperienceAlertActions = () =>
105-
useExperienceAlertStore((s) => s.actions);
89+
useExperienceAlertStore((s) => s.actions);

src/features/experience-detail/model/use-hydrate-experience.ts

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,9 @@
1-
import { useCallback } from "react";
2-
31
import { toExperienceEntity } from "@/features/experience-detail/lib/to-experience-entity";
42
import { useExperienceDetailStore } from "@/features/experience-detail/store/experience.store";
53

64
import type { GetExperienceDetailResponse } from "@/features/experience-detail/api/use-get-experience-detail.query";
75

8-
export const useHydrateExperienceFromApi = () => {
9-
const { setCurrent, setDefaultExperienceId, hydrateDraftFromCurrent } =
10-
useExperienceDetailStore((s) => s.actions);
11-
12-
const hydrate = useCallback(
13-
(data: GetExperienceDetailResponse) => {
14-
const entity = toExperienceEntity(data);
15-
16-
setCurrent(entity);
17-
setDefaultExperienceId(entity.isDefault ? entity.experienceId : null);
18-
hydrateDraftFromCurrent();
19-
},
20-
[setCurrent, setDefaultExperienceId, hydrateDraftFromCurrent]
21-
);
22-
23-
return hydrate;
24-
};
25-
26-
export const hydrateExperienceFromApi = (data: GetExperienceDetailResponse) => {
6+
export const applyExperienceDetailFromApi = (data: GetExperienceDetailResponse) => {
277
const { actions } = useExperienceDetailStore.getState();
288
const entity = toExperienceEntity(data);
299

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,7 @@
1-
import { useCallback } from "react";
2-
31
import { useExperienceDetailStore } from "../store/experience.store";
42

53
import type { ExperienceMode } from "../types/experience-detail.types";
64

7-
export const useInitExperienceDetail = () => {
8-
const current = useExperienceDetailStore((s) => s.current);
9-
const { setMode, setCurrent, resetDraft, setDefaultExperienceId } =
10-
useExperienceDetailStore((s) => s.actions);
11-
12-
const init = useCallback(
13-
(mode: ExperienceMode, experienceId?: string) => {
14-
if (
15-
current &&
16-
experienceId &&
17-
String(current.experienceId) === experienceId
18-
) {
19-
setMode(mode);
20-
return;
21-
}
22-
23-
setMode(mode);
24-
25-
if (mode === "create") {
26-
setCurrent(null);
27-
resetDraft();
28-
setDefaultExperienceId(null);
29-
return;
30-
}
31-
32-
if (!experienceId) {
33-
setCurrent(null);
34-
resetDraft();
35-
return;
36-
}
37-
},
38-
[current, setMode, setCurrent, resetDraft, setDefaultExperienceId]
39-
);
40-
41-
return init;
42-
};
43-
44-
export const useResetExperienceDetail = () => {
45-
const { setMode, setCurrent, resetDraft, setDefaultExperienceId } =
46-
useExperienceDetailStore((s) => s.actions);
47-
48-
const reset = useCallback(() => {
49-
setMode("view");
50-
setCurrent(null);
51-
resetDraft();
52-
setDefaultExperienceId(null);
53-
}, [setMode, setCurrent, resetDraft, setDefaultExperienceId]);
54-
55-
return reset;
56-
};
57-
585
export const initExperienceDetail = (
596
mode: ExperienceMode,
607
experienceId?: string
@@ -85,11 +32,3 @@ export const initExperienceDetail = (
8532
return;
8633
}
8734
};
88-
89-
export const resetExperienceDetail = () => {
90-
const { actions } = useExperienceDetailStore.getState();
91-
actions.setMode("view");
92-
actions.setCurrent(null);
93-
actions.resetDraft();
94-
actions.setDefaultExperienceId(null);
95-
};
Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { DEFAULT_BUTTON_LABELS } from "../config/messages";
2-
31
import { useExperienceDetailStore } from "./experience.store";
42

53
export const useExperienceMode = () => useExperienceDetailStore((s) => s.mode);
@@ -10,30 +8,8 @@ export const useExperienceCurrent = () =>
108
export const useExperienceDraft = () =>
119
useExperienceDetailStore((s) => s.draft);
1210

13-
export const useDefaultExperienceId = () =>
14-
useExperienceDetailStore((s) => s.defaultExperience.experienceId);
15-
1611
export const useExperienceActions = () =>
1712
useExperienceDetailStore((s) => s.actions);
1813

1914
export const useIsDraftDefault = () =>
2015
useExperienceDetailStore((s) => s.draft.isDefault);
21-
22-
export const useDefaultButtonLabel = () => {
23-
const isDefault = useExperienceDetailStore((s) => s.draft.isDefault);
24-
return isDefault ? DEFAULT_BUTTON_LABELS.UNSET : DEFAULT_BUTTON_LABELS.SET;
25-
};
26-
27-
export const useShowEditDeleteButtons = () => {
28-
const mode = useExperienceDetailStore((s) => s.mode);
29-
const current = useExperienceDetailStore((s) => s.current);
30-
return mode === "view" && Boolean(current);
31-
};
32-
33-
export const useShowSubmitButton = () => {
34-
const mode = useExperienceDetailStore((s) => s.mode);
35-
return mode === "create" || mode === "edit";
36-
};
37-
38-
export const useCurrentExperienceId = () =>
39-
useExperienceDetailStore((s) => s.current?.experienceId ?? null);

0 commit comments

Comments
 (0)