@uniai-fe/uds-templates 0.4.33 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/styles.css +93 -19
- package/package.json +1 -1
- package/src/auth/signup/hooks/index.ts +3 -0
- package/src/auth/signup/hooks/useSignupAgreementForm.ts +48 -0
- package/src/auth/signup/hooks/useSignupFarmCodeForm.ts +87 -0
- package/src/auth/signup/hooks/useSignupTypeSelectForm.ts +56 -0
- package/src/auth/signup/img/select-user-type-default.svg +15 -0
- package/src/auth/signup/img/select-user-type-selected.svg +3 -0
- package/src/auth/signup/index.ts +10 -0
- package/src/auth/signup/markup/AccountForm.tsx +1 -0
- package/src/auth/signup/markup/AgreementForm.tsx +229 -0
- package/src/auth/signup/markup/FarmCodeForm.tsx +122 -0
- package/src/auth/signup/markup/Template.tsx +58 -2
- package/src/auth/signup/markup/TypeSelectForm.tsx +102 -0
- package/src/auth/signup/markup/UserInfoForm.tsx +9 -0
- package/src/auth/signup/markup/VerificationForm.tsx +36 -26
- package/src/auth/signup/markup/index.ts +3 -0
- package/src/auth/signup/styles/signup.scss +95 -20
- package/src/auth/signup/types/hooks.ts +132 -0
- package/src/auth/signup/types/props.ts +210 -4
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { useEffect } from "react";
|
|
5
|
+
import { useFormContext } from "react-hook-form";
|
|
6
|
+
import { Button, Form, Input } from "@uniai-fe/uds-primitives";
|
|
7
|
+
import type { AuthSignupFarmCodeProps, AuthSignupFormValues } from "../types";
|
|
8
|
+
import { useSignupFarmCodeForm } from "../hooks";
|
|
9
|
+
import { getSignupFieldDefaultValue } from "../utils/getSignupFieldDefaultValue";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 회원가입 Step3; 농장 식별번호 입력 폼
|
|
13
|
+
* @component
|
|
14
|
+
* @param {AuthSignupFarmCodeProps} props step props
|
|
15
|
+
* @param {AuthSignupFarmCodeFields} props.fields 필드 설정
|
|
16
|
+
* @param {React.FormHTMLAttributes<HTMLFormElement>} [props.formAttr] form attr
|
|
17
|
+
* @param {import("react").ReactNode} [props.submitLabel] CTA 라벨
|
|
18
|
+
* @param {AuthSignupFarmCodeProps["onSubmit"]} props.onSubmit 제출 핸들러
|
|
19
|
+
*/
|
|
20
|
+
export function AuthSignupFarmCodeForm({
|
|
21
|
+
fields,
|
|
22
|
+
formAttr,
|
|
23
|
+
submitLabel,
|
|
24
|
+
onSubmit,
|
|
25
|
+
}: AuthSignupFarmCodeProps) {
|
|
26
|
+
const form = useFormContext<AuthSignupFormValues>();
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const config = fields.farmCode;
|
|
30
|
+
const fieldName = config.attr?.name ?? "farmCode";
|
|
31
|
+
const currentValue = form.getValues(
|
|
32
|
+
fieldName as keyof AuthSignupFormValues,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
if (
|
|
36
|
+
(typeof currentValue !== "string" || currentValue.length === 0) &&
|
|
37
|
+
config.attr?.defaultValue === undefined
|
|
38
|
+
) {
|
|
39
|
+
form.setValue(
|
|
40
|
+
fieldName as keyof AuthSignupFormValues,
|
|
41
|
+
getSignupFieldDefaultValue(config),
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}, [fields, form]);
|
|
45
|
+
|
|
46
|
+
const {
|
|
47
|
+
register,
|
|
48
|
+
helpers,
|
|
49
|
+
disabled,
|
|
50
|
+
onSubmit: handleSubmit,
|
|
51
|
+
} = useSignupFarmCodeForm({
|
|
52
|
+
fields,
|
|
53
|
+
form,
|
|
54
|
+
onSubmit,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<form
|
|
59
|
+
className={clsx("auth-signup-form", "auth-signup-form-farm-code")}
|
|
60
|
+
{...formAttr}
|
|
61
|
+
onSubmit={handleSubmit}
|
|
62
|
+
>
|
|
63
|
+
<div className="auth-signup-fields">
|
|
64
|
+
<Form.Field.Template
|
|
65
|
+
width={fields.farmCode.template?.width ?? "full"}
|
|
66
|
+
state={helpers.farmCode?.state === "error" ? "error" : undefined}
|
|
67
|
+
className={clsx(
|
|
68
|
+
"auth-signup-field",
|
|
69
|
+
"auth-signup-field-farm-code",
|
|
70
|
+
fields.farmCode.template?.className,
|
|
71
|
+
fields.farmCode.className,
|
|
72
|
+
)}
|
|
73
|
+
headerProps={{
|
|
74
|
+
...fields.farmCode.template?.headerProps,
|
|
75
|
+
label:
|
|
76
|
+
fields.farmCode.template?.headerProps?.label ??
|
|
77
|
+
fields.farmCode.label ??
|
|
78
|
+
"농장 식별번호",
|
|
79
|
+
}}
|
|
80
|
+
footer={
|
|
81
|
+
fields.farmCode.template?.footer ??
|
|
82
|
+
helpers.farmCode?.text ??
|
|
83
|
+
fields.farmCode.helper
|
|
84
|
+
}
|
|
85
|
+
footerProps={{
|
|
86
|
+
...fields.farmCode.template?.footerProps,
|
|
87
|
+
...(helpers.farmCode?.state
|
|
88
|
+
? { "data-state": helpers.farmCode.state }
|
|
89
|
+
: {}),
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
<Input.Base
|
|
93
|
+
{...(fields.farmCode.props ?? {})}
|
|
94
|
+
placeholder={fields.farmCode.props?.placeholder ?? "6자리 숫자"}
|
|
95
|
+
register={register.farmCode}
|
|
96
|
+
state={helpers.farmCode?.state ?? fields.farmCode.props?.state}
|
|
97
|
+
block={
|
|
98
|
+
fields.farmCode.block ?? fields.farmCode.props?.block ?? true
|
|
99
|
+
}
|
|
100
|
+
inputMode={fields.farmCode.props?.inputMode ?? "numeric"}
|
|
101
|
+
maxLength={fields.farmCode.props?.maxLength ?? 6}
|
|
102
|
+
pattern={fields.farmCode.props?.pattern ?? "[0-9]*"}
|
|
103
|
+
priority={fields.farmCode.props?.priority ?? "secondary"}
|
|
104
|
+
size={fields.farmCode.props?.size ?? "large"}
|
|
105
|
+
/>
|
|
106
|
+
</Form.Field.Template>
|
|
107
|
+
</div>
|
|
108
|
+
<Button.Default
|
|
109
|
+
type="submit"
|
|
110
|
+
fill="solid"
|
|
111
|
+
size="xlarge"
|
|
112
|
+
priority="primary"
|
|
113
|
+
block
|
|
114
|
+
disabled={disabled}
|
|
115
|
+
>
|
|
116
|
+
{submitLabel ?? "다음"}
|
|
117
|
+
</Button.Default>
|
|
118
|
+
</form>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export default AuthSignupFarmCodeForm;
|
|
@@ -3,21 +3,49 @@ import type { ReactNode } from "react";
|
|
|
3
3
|
import { AuthContainer } from "../../common/container";
|
|
4
4
|
import type {
|
|
5
5
|
AuthSignupStepIndicatorItem,
|
|
6
|
+
AuthSignupTypeValue,
|
|
6
7
|
AuthSignupTemplateProps,
|
|
7
8
|
} from "../types";
|
|
9
|
+
import { AuthSignupTypeSelectForm } from "./TypeSelectForm";
|
|
8
10
|
import { AuthSignupUserInfoForm } from "./UserInfoForm";
|
|
11
|
+
import { AuthSignupFarmCodeForm } from "./FarmCodeForm";
|
|
12
|
+
import { AuthSignupAgreementForm } from "./AgreementForm";
|
|
9
13
|
import { AuthSignupVerificationForm } from "./VerificationForm";
|
|
10
14
|
import { AuthSignupAccountForm } from "./AccountForm";
|
|
11
15
|
import { AuthSignupComplete } from "./Complete";
|
|
12
16
|
import { AuthStageHeader } from "../../common/container/header";
|
|
13
17
|
|
|
14
|
-
const
|
|
18
|
+
const LEGACY_DEFAULT_STEPS: AuthSignupStepIndicatorItem[] = [
|
|
15
19
|
{ id: "userInfo", label: "기본 정보" },
|
|
16
20
|
{ id: "verifyAgreement", label: "약관 · 인증" },
|
|
17
21
|
{ id: "generateAccount", label: "계정 생성" },
|
|
18
22
|
{ id: "complete", label: "완료" },
|
|
19
23
|
];
|
|
20
24
|
|
|
25
|
+
const NEXT_DEFAULT_STEPS: AuthSignupStepIndicatorItem[] = [
|
|
26
|
+
{ id: "typeSelect", label: "가입 유형" },
|
|
27
|
+
{ id: "identity", label: "본인 확인" },
|
|
28
|
+
{ id: "farmCode", label: "농장 코드" },
|
|
29
|
+
{ id: "agreement", label: "약관 동의" },
|
|
30
|
+
{ id: "account", label: "계정 생성" },
|
|
31
|
+
{ id: "complete", label: "완료" },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const resolveDefaultSteps = (
|
|
35
|
+
isNextFlow: boolean,
|
|
36
|
+
signupType?: AuthSignupTypeValue,
|
|
37
|
+
) => {
|
|
38
|
+
if (!isNextFlow) {
|
|
39
|
+
return LEGACY_DEFAULT_STEPS;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (signupType === "regionManager") {
|
|
43
|
+
return NEXT_DEFAULT_STEPS.filter(item => item.id !== "farmCode");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return NEXT_DEFAULT_STEPS;
|
|
47
|
+
};
|
|
48
|
+
|
|
21
49
|
/**
|
|
22
50
|
* 회원가입 템플릿; Step1~4 화면을 AuthContainer 위에서 전환한다.
|
|
23
51
|
* @component
|
|
@@ -30,15 +58,26 @@ const DEFAULT_STEPS: AuthSignupStepIndicatorItem[] = [
|
|
|
30
58
|
export function AuthSignupTemplate({
|
|
31
59
|
className,
|
|
32
60
|
header,
|
|
61
|
+
signupType,
|
|
33
62
|
step,
|
|
34
63
|
stepIndicator,
|
|
35
64
|
footer,
|
|
65
|
+
typeSelect,
|
|
66
|
+
identity,
|
|
67
|
+
farmCode,
|
|
68
|
+
agreement,
|
|
36
69
|
userInfo,
|
|
37
70
|
verification,
|
|
38
71
|
account,
|
|
39
72
|
complete,
|
|
40
73
|
}: AuthSignupTemplateProps) {
|
|
41
|
-
const
|
|
74
|
+
const isNextFlow =
|
|
75
|
+
Boolean(typeSelect || identity || farmCode || agreement) ||
|
|
76
|
+
["typeSelect", "identity", "farmCode", "agreement", "account"].includes(
|
|
77
|
+
step,
|
|
78
|
+
);
|
|
79
|
+
const steps =
|
|
80
|
+
stepIndicator?.items ?? resolveDefaultSteps(isNextFlow, signupType);
|
|
42
81
|
const currentStep = stepIndicator?.current ?? step;
|
|
43
82
|
const defaultStepIndex = Math.max(
|
|
44
83
|
0,
|
|
@@ -72,12 +111,29 @@ export function AuthSignupTemplate({
|
|
|
72
111
|
|
|
73
112
|
let content: ReactNode = null;
|
|
74
113
|
switch (currentStep) {
|
|
114
|
+
case "typeSelect":
|
|
115
|
+
content = typeSelect ? (
|
|
116
|
+
<AuthSignupTypeSelectForm {...typeSelect} />
|
|
117
|
+
) : null;
|
|
118
|
+
break;
|
|
119
|
+
case "identity":
|
|
120
|
+
content = <AuthSignupUserInfoForm {...(identity ?? userInfo)} />;
|
|
121
|
+
break;
|
|
122
|
+
case "farmCode":
|
|
123
|
+
content = farmCode ? <AuthSignupFarmCodeForm {...farmCode} /> : null;
|
|
124
|
+
break;
|
|
125
|
+
case "agreement":
|
|
126
|
+
content = agreement ? <AuthSignupAgreementForm {...agreement} /> : null;
|
|
127
|
+
break;
|
|
75
128
|
case "userInfo":
|
|
76
129
|
content = <AuthSignupUserInfoForm {...userInfo} />;
|
|
77
130
|
break;
|
|
78
131
|
case "verifyAgreement":
|
|
79
132
|
content = <AuthSignupVerificationForm {...verification} />;
|
|
80
133
|
break;
|
|
134
|
+
case "account":
|
|
135
|
+
content = <AuthSignupAccountForm {...account} />;
|
|
136
|
+
break;
|
|
81
137
|
case "generateAccount":
|
|
82
138
|
content = <AuthSignupAccountForm {...account} />;
|
|
83
139
|
break;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { useFormContext } from "react-hook-form";
|
|
5
|
+
import { Button } from "@uniai-fe/uds-primitives";
|
|
6
|
+
import type { AuthSignupFormValues, AuthSignupTypeSelectProps } from "../types";
|
|
7
|
+
import { useSignupTypeSelectForm } from "../hooks";
|
|
8
|
+
import CheckIcon from "../img/select-user-type-default.svg";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 회원가입 Step1; 가입 유형 선택 폼
|
|
12
|
+
* @component
|
|
13
|
+
* @param {AuthSignupTypeSelectProps} props step props
|
|
14
|
+
* @param {AuthSignupTypeSelectOption[]} props.options 선택 옵션 목록
|
|
15
|
+
* @param {React.FormHTMLAttributes<HTMLFormElement>} [props.formAttr] form attr
|
|
16
|
+
* @param {import("react").ReactNode} [props.submitLabel] CTA 라벨
|
|
17
|
+
* @param {AuthSignupTypeSelectProps["onSubmit"]} props.onSubmit 제출 핸들러
|
|
18
|
+
*/
|
|
19
|
+
export function AuthSignupTypeSelectForm({
|
|
20
|
+
options,
|
|
21
|
+
formAttr,
|
|
22
|
+
submitLabel,
|
|
23
|
+
onSubmit,
|
|
24
|
+
}: AuthSignupTypeSelectProps) {
|
|
25
|
+
const form = useFormContext<AuthSignupFormValues>();
|
|
26
|
+
const {
|
|
27
|
+
selectedType,
|
|
28
|
+
onValueChange,
|
|
29
|
+
disabled,
|
|
30
|
+
onSubmit: handleSubmit,
|
|
31
|
+
} = useSignupTypeSelectForm({
|
|
32
|
+
form,
|
|
33
|
+
onSubmit,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<form
|
|
38
|
+
className={clsx("auth-signup-form", "auth-signup-form-type-select")}
|
|
39
|
+
{...formAttr}
|
|
40
|
+
onSubmit={handleSubmit}
|
|
41
|
+
>
|
|
42
|
+
<div className="auth-signup-type-options" role="radiogroup">
|
|
43
|
+
{options.map(option => {
|
|
44
|
+
const isSelected = selectedType === option.id;
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<div className="auth-signup-type-option-group" key={option.id}>
|
|
48
|
+
<p className="auth-signup-type-question">{option.question}</p>
|
|
49
|
+
<Button.Default
|
|
50
|
+
className="auth-signup-type-option"
|
|
51
|
+
role="radio"
|
|
52
|
+
aria-checked={isSelected}
|
|
53
|
+
data-selected={isSelected ? "true" : "false"}
|
|
54
|
+
data-user-action={isSelected ? "hover" : undefined}
|
|
55
|
+
disabled={option.disabled}
|
|
56
|
+
fill="outlined"
|
|
57
|
+
size="xlarge"
|
|
58
|
+
priority={isSelected ? "primary" : "tertiary"}
|
|
59
|
+
block
|
|
60
|
+
left={
|
|
61
|
+
// 단일 svg asset을 currentColor 기반으로 재사용해 선택 상태를 버튼 foreground와 동기화한다.
|
|
62
|
+
<CheckIcon
|
|
63
|
+
width={24}
|
|
64
|
+
height={24}
|
|
65
|
+
viewBox="0 0 24 24"
|
|
66
|
+
aria-hidden="true"
|
|
67
|
+
/>
|
|
68
|
+
}
|
|
69
|
+
onClick={() => {
|
|
70
|
+
if (!option.disabled) {
|
|
71
|
+
onValueChange(option.id);
|
|
72
|
+
}
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
<span className="auth-signup-type-option-label">
|
|
76
|
+
{option.label}
|
|
77
|
+
</span>
|
|
78
|
+
</Button.Default>
|
|
79
|
+
{option.description ? (
|
|
80
|
+
<p className="auth-signup-type-description">
|
|
81
|
+
{option.description}
|
|
82
|
+
</p>
|
|
83
|
+
) : null}
|
|
84
|
+
</div>
|
|
85
|
+
);
|
|
86
|
+
})}
|
|
87
|
+
</div>
|
|
88
|
+
<Button.Default
|
|
89
|
+
type="submit"
|
|
90
|
+
fill="solid"
|
|
91
|
+
size="xlarge"
|
|
92
|
+
priority="primary"
|
|
93
|
+
block
|
|
94
|
+
disabled={disabled}
|
|
95
|
+
>
|
|
96
|
+
{submitLabel ?? "다음"}
|
|
97
|
+
</Button.Default>
|
|
98
|
+
</form>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export default AuthSignupTypeSelectForm;
|
|
@@ -71,6 +71,11 @@ export function AuthSignupUserInfoForm({
|
|
|
71
71
|
{renderedFields.includes("name") ? (
|
|
72
72
|
<Form.Field.Template
|
|
73
73
|
width={fields.name.template?.width ?? "full"}
|
|
74
|
+
state={
|
|
75
|
+
(helpers.name?.state ?? fields.name.props?.state) === "error"
|
|
76
|
+
? "error"
|
|
77
|
+
: undefined
|
|
78
|
+
}
|
|
74
79
|
className={clsx(
|
|
75
80
|
"auth-signup-field",
|
|
76
81
|
"auth-signup-field-name",
|
|
@@ -109,6 +114,10 @@ export function AuthSignupUserInfoForm({
|
|
|
109
114
|
<AuthCodePhoneTemplate
|
|
110
115
|
templateProps={{
|
|
111
116
|
width: fields.phone.template?.width ?? "full",
|
|
117
|
+
state:
|
|
118
|
+
(helpers.phone?.state ?? fields.phone.props?.state) === "error"
|
|
119
|
+
? "error"
|
|
120
|
+
: undefined,
|
|
112
121
|
className: clsx(
|
|
113
122
|
"auth-signup-field",
|
|
114
123
|
"auth-signup-field-phone",
|
|
@@ -53,6 +53,13 @@ const resolveCodeValue = (inputProps?: AuthCodeInputProps): string => {
|
|
|
53
53
|
return "";
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
+
const AGREEMENT_DETAIL_FALLBACK = (
|
|
57
|
+
<>
|
|
58
|
+
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
|
|
59
|
+
<p>Nulla facilisi. Integer porta, nisl at volutpat posuere, erat arcu.</p>
|
|
60
|
+
</>
|
|
61
|
+
);
|
|
62
|
+
|
|
56
63
|
/**
|
|
57
64
|
* 회원가입 Step2; 약관 동의 + 이메일 인증
|
|
58
65
|
* @component
|
|
@@ -145,6 +152,7 @@ export function AuthSignupVerificationForm({
|
|
|
145
152
|
const emailFooterProps = fields.email.template?.footerProps ?? {};
|
|
146
153
|
const emailTemplateProps: AuthFormFieldTemplateProps = {
|
|
147
154
|
width: fields.email.template?.width ?? "full",
|
|
155
|
+
state: helpers.email?.state === "error" ? "error" : undefined,
|
|
148
156
|
className: clsx(
|
|
149
157
|
"auth-signup-field",
|
|
150
158
|
"auth-signup-field-email",
|
|
@@ -301,14 +309,20 @@ export function AuthSignupVerificationForm({
|
|
|
301
309
|
</div>
|
|
302
310
|
{agreements.length ? (
|
|
303
311
|
<section className="auth-signup-agreements" aria-label="약관 동의">
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
+
{/* all-agree는 checkbox primitive를 유지하고 step3 카드 스타일만 signup에서 덮어쓴다. */}
|
|
313
|
+
<CheckboxField
|
|
314
|
+
size="large"
|
|
315
|
+
checked={allRequiredChecked}
|
|
316
|
+
onCheckedChange={() => onToggleAll({ requiredOnly: true })}
|
|
317
|
+
fieldClassName="auth-signup-agreement-all-field"
|
|
318
|
+
labelWrapperClassName="auth-signup-agreement-all"
|
|
319
|
+
className="auth-signup-agreement-all-checkbox"
|
|
320
|
+
label={
|
|
321
|
+
<span className="auth-signup-agreement-all-label">
|
|
322
|
+
필수 약관에 모두 동의하기
|
|
323
|
+
</span>
|
|
324
|
+
}
|
|
325
|
+
/>
|
|
312
326
|
<div className="auth-signup-agreements-list">
|
|
313
327
|
{agreements.map(option => {
|
|
314
328
|
const checked = Boolean(agreementState[option.id]);
|
|
@@ -320,7 +334,7 @@ export function AuthSignupVerificationForm({
|
|
|
320
334
|
data-required={option.required ? "true" : undefined}
|
|
321
335
|
data-checked={checked ? "true" : undefined}
|
|
322
336
|
>
|
|
323
|
-
{/* 약관
|
|
337
|
+
{/* 하위 약관 row는 primitive checkbox가 아니라 커스텀 check icon을 유지한다. */}
|
|
324
338
|
<button
|
|
325
339
|
type="button"
|
|
326
340
|
className="auth-signup-agreement-toggle"
|
|
@@ -336,18 +350,16 @@ export function AuthSignupVerificationForm({
|
|
|
336
350
|
</span>
|
|
337
351
|
{renderAgreementLabel(option)}
|
|
338
352
|
</button>
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
>
|
|
346
|
-
<
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
</button>
|
|
350
|
-
) : null}
|
|
353
|
+
<button
|
|
354
|
+
type="button"
|
|
355
|
+
className="auth-signup-agreement-detail"
|
|
356
|
+
aria-label={`${option.label} 약관 상세 보기`}
|
|
357
|
+
onClick={() => handleOpenAgreementDetail(option.id)}
|
|
358
|
+
>
|
|
359
|
+
<span aria-hidden="true">
|
|
360
|
+
<ChevronOpenDetailIcon />
|
|
361
|
+
</span>
|
|
362
|
+
</button>
|
|
351
363
|
</div>
|
|
352
364
|
);
|
|
353
365
|
})}
|
|
@@ -378,11 +390,9 @@ export function AuthSignupVerificationForm({
|
|
|
378
390
|
<DrawerHeader>
|
|
379
391
|
<DrawerTitle>{openedAgreement?.label ?? "약관 상세"}</DrawerTitle>
|
|
380
392
|
</DrawerHeader>
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
</DrawerBody>
|
|
385
|
-
) : null}
|
|
393
|
+
<DrawerBody className="auth-signup-agreement-drawer-body">
|
|
394
|
+
{openedAgreement?.description ?? AGREEMENT_DETAIL_FALLBACK}
|
|
395
|
+
</DrawerBody>
|
|
386
396
|
<DrawerFooter>
|
|
387
397
|
<Button.Default
|
|
388
398
|
type="button"
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
export { AuthSignupTypeSelectForm } from "./TypeSelectForm";
|
|
1
2
|
export { AuthSignupUserInfoForm } from "./UserInfoForm";
|
|
3
|
+
export { AuthSignupFarmCodeForm } from "./FarmCodeForm";
|
|
4
|
+
export { AuthSignupAgreementForm } from "./AgreementForm";
|
|
2
5
|
export { AuthSignupVerificationForm } from "./VerificationForm";
|
|
3
6
|
export { AuthSignupAccountForm } from "./AccountForm";
|
|
4
7
|
export { AuthSignupComplete } from "./Complete";
|
|
@@ -11,6 +11,64 @@
|
|
|
11
11
|
gap: var(--spacing-padding-5);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
.auth-signup-type-options {
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
gap: var(--spacing-padding-6);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.auth-signup-type-option-group {
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
gap: var(--spacing-padding-3);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.auth-signup-type-question {
|
|
27
|
+
margin: 0;
|
|
28
|
+
color: var(--color-label-standard);
|
|
29
|
+
font-size: var(--font-heading-xxsmall-size);
|
|
30
|
+
line-height: 1.4;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.auth-signup-type-option {
|
|
34
|
+
display: flex;
|
|
35
|
+
justify-content: flex-start;
|
|
36
|
+
text-align: left;
|
|
37
|
+
|
|
38
|
+
--button-default-padding-inline-large: 16px;
|
|
39
|
+
--button-default-tertiary-outline-foreground: var(--color-label-alternative);
|
|
40
|
+
|
|
41
|
+
.button-left {
|
|
42
|
+
display: flex;
|
|
43
|
+
width: 24px;
|
|
44
|
+
height: 24px;
|
|
45
|
+
align-items: center;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
flex-shrink: 0;
|
|
48
|
+
}
|
|
49
|
+
.button-left svg {
|
|
50
|
+
display: block;
|
|
51
|
+
width: 24px;
|
|
52
|
+
height: 24px;
|
|
53
|
+
}
|
|
54
|
+
.button-label {
|
|
55
|
+
flex: 1;
|
|
56
|
+
text-align: left;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.auth-signup-type-option-label {
|
|
61
|
+
font-size: var(--font-body-large-size);
|
|
62
|
+
line-height: 1.5;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.auth-signup-type-description {
|
|
66
|
+
margin: 0;
|
|
67
|
+
color: var(--color-label-assistive);
|
|
68
|
+
font-size: var(--font-body-xxsmall-size);
|
|
69
|
+
line-height: 1.5;
|
|
70
|
+
}
|
|
71
|
+
|
|
14
72
|
.auth-signup-verification {
|
|
15
73
|
display: flex;
|
|
16
74
|
flex-direction: column;
|
|
@@ -21,34 +79,47 @@
|
|
|
21
79
|
.auth-signup-agreements {
|
|
22
80
|
display: flex;
|
|
23
81
|
flex-direction: column;
|
|
24
|
-
gap:
|
|
82
|
+
gap: 12px;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.auth-signup-agreement-all-field {
|
|
86
|
+
gap: 0;
|
|
25
87
|
}
|
|
26
88
|
|
|
27
89
|
.auth-signup-agreement-all {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
align-items: center;
|
|
90
|
+
width: 100%;
|
|
91
|
+
min-height: 56px;
|
|
31
92
|
background: var(--color-bg-alternative-cool-gray, #f2f2f3);
|
|
32
|
-
border-radius:
|
|
33
|
-
|
|
34
|
-
|
|
93
|
+
border-radius: 12px;
|
|
94
|
+
padding: 8px 12px;
|
|
95
|
+
gap: 6px;
|
|
96
|
+
align-items: center;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.auth-signup-agreement-all-checkbox {
|
|
100
|
+
flex-shrink: 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.auth-signup-agreement-all-label {
|
|
104
|
+
color: var(--color-label-standard);
|
|
105
|
+
font-size: var(--font-body-large-size);
|
|
106
|
+
font-weight: 500;
|
|
107
|
+
line-height: 1.5;
|
|
35
108
|
}
|
|
36
109
|
|
|
37
110
|
.auth-signup-agreements-list {
|
|
38
111
|
width: 100%;
|
|
39
|
-
background: var(--color-common-100);
|
|
40
|
-
border-radius: var(--theme-radius-medium-3, 8px);
|
|
41
|
-
padding: var(--spacing-padding-3);
|
|
42
112
|
display: flex;
|
|
43
113
|
flex-direction: column;
|
|
44
|
-
gap:
|
|
114
|
+
gap: 12px;
|
|
115
|
+
padding: 4px 12px;
|
|
45
116
|
}
|
|
46
117
|
|
|
47
118
|
.auth-signup-agreement-row {
|
|
48
119
|
display: flex;
|
|
49
120
|
align-items: center;
|
|
50
121
|
justify-content: space-between;
|
|
51
|
-
gap:
|
|
122
|
+
gap: 8px;
|
|
52
123
|
}
|
|
53
124
|
|
|
54
125
|
// 약관 토글 행은 SVG 아이콘/텍스트를 하나의 버튼으로 묶어 디자인 명세와 일치시킨다.
|
|
@@ -59,12 +130,13 @@
|
|
|
59
130
|
margin: 0;
|
|
60
131
|
display: flex;
|
|
61
132
|
align-items: center;
|
|
62
|
-
gap:
|
|
133
|
+
gap: 8px;
|
|
63
134
|
cursor: pointer;
|
|
64
135
|
flex: 1;
|
|
65
136
|
text-align: left;
|
|
66
137
|
flex-wrap: nowrap;
|
|
67
138
|
font-size: 14px;
|
|
139
|
+
min-width: 0;
|
|
68
140
|
}
|
|
69
141
|
|
|
70
142
|
.auth-signup-agreement-icon {
|
|
@@ -86,19 +158,19 @@
|
|
|
86
158
|
|
|
87
159
|
.auth-signup-agreement-toggle[data-checked="true"] .auth-signup-agreement-icon {
|
|
88
160
|
color: var(--color-primary-default);
|
|
89
|
-
border-color: var(--color-primary-default);
|
|
90
161
|
}
|
|
91
162
|
|
|
92
163
|
.auth-signup-agreement-label {
|
|
93
|
-
display:
|
|
94
|
-
gap:
|
|
164
|
+
display: flex;
|
|
165
|
+
gap: 0;
|
|
95
166
|
align-items: baseline;
|
|
96
167
|
flex-wrap: nowrap;
|
|
168
|
+
min-width: 0;
|
|
97
169
|
}
|
|
98
170
|
|
|
99
171
|
.auth-signup-agreement-badge {
|
|
100
172
|
font-size: 14px;
|
|
101
|
-
|
|
173
|
+
font-weight: 400;
|
|
102
174
|
color: var(--color-primary-default);
|
|
103
175
|
|
|
104
176
|
&[data-required="false"] {
|
|
@@ -110,7 +182,9 @@
|
|
|
110
182
|
font-size: 14px;
|
|
111
183
|
color: var(--color-label-standard);
|
|
112
184
|
font-weight: 400;
|
|
113
|
-
line-height: 1.
|
|
185
|
+
line-height: 1.5;
|
|
186
|
+
overflow: hidden;
|
|
187
|
+
text-overflow: ellipsis;
|
|
114
188
|
}
|
|
115
189
|
|
|
116
190
|
.auth-signup-agreement-description {
|
|
@@ -131,11 +205,12 @@
|
|
|
131
205
|
justify-content: center;
|
|
132
206
|
width: 20px;
|
|
133
207
|
height: 20px;
|
|
208
|
+
flex-shrink: 0;
|
|
134
209
|
|
|
135
210
|
svg {
|
|
136
211
|
display: block;
|
|
137
|
-
width:
|
|
138
|
-
height:
|
|
212
|
+
width: 16px;
|
|
213
|
+
height: 16px;
|
|
139
214
|
}
|
|
140
215
|
}
|
|
141
216
|
|