Skip to content

Commit 776144d

Browse files
committed
feat: 옵션 수정 불가능 사유를 좀 더 명시적으로 노출
1 parent 03ff8c5 commit 776144d

2 files changed

Lines changed: 28 additions & 12 deletions

File tree

packages/shop/src/components/common/option_group_input.tsx

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { CircularProgress, FormControl, InputLabel, MenuItem, Select, TextField, Tooltip } from "@mui/material";
1+
import { CircularProgress, FormControl, FormHelperText, InputLabel, MenuItem, Select, TextField } from "@mui/material";
22
import { Suspense } from "@suspensive/react";
33
import { FC } from "react";
44
import { Control, Controller, FieldValues } from "react-hook-form";
55
import { isEmpty, isNonNull, isNumber, isString } from "remeda";
66

77
import { useShopContext } from "@frontend/shop/hooks";
88
import type { Option, OrderProductItem } from "@frontend/shop/schemas";
9-
import { getCustomResponsePattern, isOrderProductOptionModifiable } from "@frontend/shop/utils";
9+
import { getCustomResponsePattern, getOrderProductOptionNotModifiableReason, isOrderProductOptionModifiable } from "@frontend/shop/utils";
1010

1111
import { PriceDisplay } from "./price_display";
1212

@@ -54,7 +54,7 @@ const SelectableOptionGroupInput: FC<{
5454
);
5555
});
5656

57-
const selectElement = (
57+
return (
5858
<FormControl fullWidth>
5959
<InputLabel id={`${optionGroup.id}label`}>{optionGroup.name}</InputLabel>
6060
<Controller
@@ -65,10 +65,9 @@ const SelectableOptionGroupInput: FC<{
6565
defaultValue={defaultValue || ""}
6666
render={({ field }) => <Select label={`${optionGroup.id}label`} {...field} children={optionElements} />}
6767
/>
68+
{isFilledString(disabledReason) && <FormHelperText>{disabledReason}</FormHelperText>}
6869
</FormControl>
6970
);
70-
71-
return isFilledString(disabledReason) ? <Tooltip title={disabledReason}>{selectElement}</Tooltip> : selectElement;
7271
};
7372

7473
const CustomResponseOptionGroupInput: FC<{
@@ -78,7 +77,7 @@ const CustomResponseOptionGroupInput: FC<{
7877
disabledReason?: string;
7978
control: Control<FieldValues, unknown, FieldValues>;
8079
}> = ({ optionGroup, defaultValue, disabled, disabledReason, control }) => {
81-
const textFieldElement = (
80+
return (
8281
<Controller
8382
control={control}
8483
name={optionGroup.id}
@@ -87,12 +86,11 @@ const CustomResponseOptionGroupInput: FC<{
8786
defaultValue={defaultValue || ""}
8887
render={({ field, formState: { errors } }) => {
8988
const errorMessage: string | undefined = errors?.[optionGroup.id]?.message?.toString();
90-
return <TextField label={optionGroup.name} {...field} error={!!errors[optionGroup.id]} helperText={errorMessage} />;
89+
const helperText = errorMessage ?? (isFilledString(disabledReason) ? disabledReason : undefined);
90+
return <TextField label={optionGroup.name} {...field} error={!!errors[optionGroup.id]} helperText={helperText} />;
9191
}}
9292
/>
9393
);
94-
95-
return isFilledString(disabledReason) ? <Tooltip title={disabledReason}>{textFieldElement}</Tooltip> : textFieldElement;
9694
};
9795

9896
export const OptionGroupInput: FC<{
@@ -133,8 +131,8 @@ export const OrderProductRelationOptionInput: FC<{
133131
control: Control<FieldValues, unknown, FieldValues>;
134132
}> = Suspense.with({ fallback: <CircularProgress /> }, ({ optionRel, disabled, disabledReason, control }) => {
135133
const { language } = useShopContext();
134+
const guessedDisabledReason = getOrderProductOptionNotModifiableReason(language, optionRel) ?? undefined;
136135
let defaultValue: string | null = null;
137-
let guessedDisabledReason: string | undefined = undefined;
138136
let dummyOptions: {
139137
id: string;
140138
name: string;
@@ -145,8 +143,6 @@ export const OrderProductRelationOptionInput: FC<{
145143
// type hinting을 위해 if문을 사용함
146144
if (optionRel.product_option_group.is_custom_response === false && isNonNull(optionRel.product_option)) {
147145
defaultValue = optionRel.product_option.id;
148-
guessedDisabledReason =
149-
language === "ko" ? "추가 비용이 발생하는 옵션은 수정할 수 없어요." : "You cannot modify options that incur additional costs.";
150146
dummyOptions = [
151147
{
152148
id: optionRel.product_option.id,

packages/shop/src/utils/index.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,26 @@ export const isOrderProductOptionModifiable = (optionRel: OrderProductItem["opti
1515
return new Date() <= new Date(optionRel.product_option_group.response_modifiable_ends_at);
1616
};
1717

18+
export const getOrderProductOptionNotModifiableReason = (
19+
language: "ko" | "en",
20+
optionRel: OrderProductItem["options"][number]
21+
): string | null => {
22+
if (!optionRel.product_option_group.is_custom_response) {
23+
return language === "ko"
24+
? "추가 비용이 발생하는 옵션은 수정할 수 없어요."
25+
: "You cannot modify options that incur additional costs.";
26+
}
27+
if (isNullish(optionRel.product_option_group.response_modifiable_ends_at)) {
28+
return language === "ko" ? "이 옵션은 수정할 수 없어요." : "This option cannot be modified.";
29+
}
30+
if (new Date() > new Date(optionRel.product_option_group.response_modifiable_ends_at)) {
31+
return language === "ko"
32+
? "옵션 수정 가능 기간이 종료되었어요."
33+
: "The modification period for this option has ended.";
34+
}
35+
return null;
36+
};
37+
1838
// 옵션 그룹에 인스턴스를 더 추가할 수 없는 사유 (한도/재고). orderable 기간 만료는 별도 헬퍼.
1939
// null = 추가 가능.
2040
export const getCannotAddMoreOptionGroupReason = (

0 commit comments

Comments
 (0)