@uniai-fe/uds-templates 0.5.25 → 0.5.27
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 +10 -0
- package/package.json +1 -1
- package/src/auth/login/markup/Container.tsx +1 -0
- package/src/auth/login/markup/LinkButtons.tsx +50 -17
- package/src/auth/login/styles/login.scss +12 -0
- package/src/auth/login/types/props.ts +5 -0
- package/src/cctv/apis/client.ts +3 -1
- package/src/cctv/hooks/useCompanyData.tsx +4 -2
- package/src/cctv/types/hook.ts +5 -0
package/dist/styles.css
CHANGED
|
@@ -967,17 +967,27 @@
|
|
|
967
967
|
|
|
968
968
|
.auth-login-find-account-button {
|
|
969
969
|
flex: 1;
|
|
970
|
+
background: none;
|
|
971
|
+
border: 0;
|
|
972
|
+
cursor: pointer;
|
|
970
973
|
font-size: 13px;
|
|
971
974
|
line-height: 1em;
|
|
972
975
|
font-weight: 400;
|
|
973
976
|
padding-inline: var(--spacing-padding-1);
|
|
977
|
+
text-decoration: none;
|
|
974
978
|
}
|
|
975
979
|
.auth-login-find-account-button:hover {
|
|
976
980
|
color: var(--color-primary-standard);
|
|
977
981
|
}
|
|
982
|
+
.auth-login-find-account-button:disabled {
|
|
983
|
+
cursor: default;
|
|
984
|
+
}
|
|
978
985
|
.auth-login-find-account-button span {
|
|
979
986
|
color: var(--color-label-standard);
|
|
980
987
|
}
|
|
988
|
+
.auth-login-find-account-button:disabled span {
|
|
989
|
+
color: var(--color-label-neutral);
|
|
990
|
+
}
|
|
981
991
|
|
|
982
992
|
.auth-find-id-button {
|
|
983
993
|
text-align: right;
|
package/package.json
CHANGED
|
@@ -38,6 +38,7 @@ export default function AuthLoginContainer({
|
|
|
38
38
|
{/* 링크 옵션이 부분적으로만 넘어와도 내부에서 존재하는 항목만 렌더링한다. */}
|
|
39
39
|
<AuthLoginLinkButtons
|
|
40
40
|
linkOptions={linkOptions}
|
|
41
|
+
isSubmitting={fieldOptions.isSubmitting}
|
|
41
42
|
texts={texts}
|
|
42
43
|
onFindPasswordClick={onFindPasswordLinkClick}
|
|
43
44
|
/>
|
|
@@ -7,17 +7,20 @@ import type { AuthLoginLinkButtonsProps } from "../types";
|
|
|
7
7
|
* @component
|
|
8
8
|
* @param {AuthLoginLinkButtonsProps} props
|
|
9
9
|
* @param {AuthLoginLinkOptions} [props.linkOptions] 계정 관련 링크 옵션
|
|
10
|
+
* @param {boolean} [props.isSubmitting] 외부 로그인 요청 pending 여부
|
|
10
11
|
* @param {AuthLoginLinkTexts} [props.texts] 링크/버튼 문구 옵션
|
|
11
12
|
* @param {() => void} [props.onFindPasswordClick] 비밀번호 찾기 커스텀 클릭 핸들러
|
|
12
13
|
*/
|
|
13
14
|
export default function AuthLoginLinkButtons({
|
|
14
15
|
linkOptions,
|
|
16
|
+
isSubmitting,
|
|
15
17
|
texts,
|
|
16
18
|
onFindPasswordClick,
|
|
17
19
|
}: AuthLoginLinkButtonsProps) {
|
|
18
20
|
const hrefFindId = linkOptions?.find?.id;
|
|
19
21
|
const hrefFindPassword = linkOptions?.find?.password;
|
|
20
22
|
const hrefSignup = linkOptions?.signup;
|
|
23
|
+
const isLinkInteractionDisabled = Boolean(isSubmitting);
|
|
21
24
|
|
|
22
25
|
if (!hrefFindId && !hrefFindPassword && !hrefSignup) {
|
|
23
26
|
return null;
|
|
@@ -27,14 +30,23 @@ export default function AuthLoginLinkButtons({
|
|
|
27
30
|
<div className="auth-login-util-container">
|
|
28
31
|
{(hrefFindId || hrefFindPassword) && (
|
|
29
32
|
<div className="auth-login-find-account">
|
|
30
|
-
{hrefFindId &&
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
{hrefFindId &&
|
|
34
|
+
(isLinkInteractionDisabled ? (
|
|
35
|
+
<button
|
|
36
|
+
type="button"
|
|
37
|
+
className="auth-login-find-account-button auth-find-id-button"
|
|
38
|
+
disabled
|
|
39
|
+
>
|
|
40
|
+
<span>{texts?.findId ?? "아이디 찾기"}</span>
|
|
41
|
+
</button>
|
|
42
|
+
) : (
|
|
43
|
+
<Link
|
|
44
|
+
href={hrefFindId}
|
|
45
|
+
className="auth-login-find-account-button auth-find-id-button"
|
|
46
|
+
>
|
|
47
|
+
<span>{texts?.findId ?? "아이디 찾기"}</span>
|
|
48
|
+
</Link>
|
|
49
|
+
))}
|
|
38
50
|
{hrefFindId && hrefFindPassword && <Divider />}
|
|
39
51
|
{/* 비밀번호 찾기 링크가 있을 때만 버튼/링크를 선택적으로 노출한다. */}
|
|
40
52
|
{hrefFindPassword &&
|
|
@@ -42,10 +54,19 @@ export default function AuthLoginLinkButtons({
|
|
|
42
54
|
<button
|
|
43
55
|
type="button"
|
|
44
56
|
className="auth-login-find-account-button auth-find-password-button"
|
|
57
|
+
disabled={isLinkInteractionDisabled}
|
|
45
58
|
onClick={onFindPasswordClick}
|
|
46
59
|
>
|
|
47
60
|
<span>{texts?.findPassword ?? "비밀번호 찾기"}</span>
|
|
48
61
|
</button>
|
|
62
|
+
) : isLinkInteractionDisabled ? (
|
|
63
|
+
<button
|
|
64
|
+
type="button"
|
|
65
|
+
className="auth-login-find-account-button auth-find-password-button"
|
|
66
|
+
disabled
|
|
67
|
+
>
|
|
68
|
+
<span>{texts?.findPassword ?? "비밀번호 찾기"}</span>
|
|
69
|
+
</button>
|
|
49
70
|
) : (
|
|
50
71
|
<Link
|
|
51
72
|
href={hrefFindPassword}
|
|
@@ -59,15 +80,27 @@ export default function AuthLoginLinkButtons({
|
|
|
59
80
|
{hrefSignup && (
|
|
60
81
|
<div className="auth-login-signup">
|
|
61
82
|
{/* 회원가입 링크가 있을 때만 signup CTA를 유지한다. */}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
83
|
+
{isLinkInteractionDisabled ? (
|
|
84
|
+
<Button.Rounded
|
|
85
|
+
type="button"
|
|
86
|
+
disabled
|
|
87
|
+
className="auth-login-signup-button"
|
|
88
|
+
priority="tertiary"
|
|
89
|
+
size="small"
|
|
90
|
+
>
|
|
91
|
+
{texts?.signup ?? "회원가입"}
|
|
92
|
+
</Button.Rounded>
|
|
93
|
+
) : (
|
|
94
|
+
<Button.Rounded
|
|
95
|
+
as={Link}
|
|
96
|
+
href={hrefSignup}
|
|
97
|
+
className="auth-login-signup-button"
|
|
98
|
+
priority="tertiary"
|
|
99
|
+
size="small"
|
|
100
|
+
>
|
|
101
|
+
{texts?.signup ?? "회원가입"}
|
|
102
|
+
</Button.Rounded>
|
|
103
|
+
)}
|
|
71
104
|
</div>
|
|
72
105
|
)}
|
|
73
106
|
</div>
|
|
@@ -28,18 +28,30 @@
|
|
|
28
28
|
.auth-login-find-account-button {
|
|
29
29
|
flex: 1;
|
|
30
30
|
|
|
31
|
+
background: none;
|
|
32
|
+
border: 0;
|
|
33
|
+
cursor: pointer;
|
|
31
34
|
font-size: 13px;
|
|
32
35
|
line-height: 1em;
|
|
33
36
|
font-weight: 400;
|
|
34
37
|
padding-inline: var(--spacing-padding-1);
|
|
38
|
+
text-decoration: none;
|
|
35
39
|
|
|
36
40
|
&:hover {
|
|
37
41
|
color: var(--color-primary-standard);
|
|
38
42
|
}
|
|
39
43
|
|
|
44
|
+
&:disabled {
|
|
45
|
+
cursor: default;
|
|
46
|
+
}
|
|
47
|
+
|
|
40
48
|
span {
|
|
41
49
|
color: var(--color-label-standard);
|
|
42
50
|
}
|
|
51
|
+
|
|
52
|
+
&:disabled span {
|
|
53
|
+
color: var(--color-label-neutral);
|
|
54
|
+
}
|
|
43
55
|
}
|
|
44
56
|
|
|
45
57
|
.auth-find-id-button {
|
|
@@ -353,6 +353,7 @@ export interface AuthLoginLinkOptions {
|
|
|
353
353
|
/**
|
|
354
354
|
* 로그인 링크 버튼 props
|
|
355
355
|
* @property {AuthLoginLinkOptions} [linkOptions] 계정 관련 링크 옵션
|
|
356
|
+
* @property {boolean} [isSubmitting] 외부 로그인 요청 pending 여부
|
|
356
357
|
* @property {AuthLoginLinkTexts} [texts] 링크/버튼 문구 옵션
|
|
357
358
|
* @property {() => void} [onFindPasswordClick] 비밀번호 찾기 링크버튼 클릭 콜백 이벤트
|
|
358
359
|
*/
|
|
@@ -361,6 +362,10 @@ export interface AuthLoginLinkButtonsProps {
|
|
|
361
362
|
* 계정 관련 링크 옵션
|
|
362
363
|
*/
|
|
363
364
|
linkOptions?: AuthLoginLinkOptions;
|
|
365
|
+
/**
|
|
366
|
+
* 외부 로그인 요청 pending 여부
|
|
367
|
+
*/
|
|
368
|
+
isSubmitting?: boolean;
|
|
364
369
|
/**
|
|
365
370
|
* 링크/버튼 문구 옵션
|
|
366
371
|
*/
|
package/src/cctv/apis/client.ts
CHANGED
|
@@ -16,11 +16,13 @@ export const getClientCctvCompanyList = async ({
|
|
|
16
16
|
|
|
17
17
|
export const useQueryCctvCompanyList = ({
|
|
18
18
|
url,
|
|
19
|
+
queryKeyDeps = [],
|
|
19
20
|
}: {
|
|
20
21
|
url?: string;
|
|
22
|
+
queryKeyDeps?: readonly unknown[];
|
|
21
23
|
}): UseQueryResult<API_Res_CctvCompany> =>
|
|
22
24
|
useQuery({
|
|
23
|
-
queryKey: ["cctv_company_list", url],
|
|
25
|
+
queryKey: ["cctv_company_list", url, ...queryKeyDeps],
|
|
24
26
|
queryFn: () => getClientCctvCompanyList({ url }),
|
|
25
27
|
});
|
|
26
28
|
|
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
* @hook
|
|
15
15
|
* @param {UseCctvCompanyDataParams} [params] 훅 파라미터
|
|
16
16
|
* @property {string} [url] 회사 리스트 API URL (Provider에서 주입된 기본값 대신 사용)
|
|
17
|
+
* @property {readonly unknown[]} [queryKeyDeps] 회사 리스트 캐시 분리용 query key deps
|
|
17
18
|
* @return {UseCctvCompanyDataReturn} 회사 리스트 쿼리 반환값
|
|
18
19
|
* @desc
|
|
19
20
|
* return {
|
|
@@ -26,8 +27,8 @@ import type {
|
|
|
26
27
|
export default function useCctvCompanyData(
|
|
27
28
|
params?: UseCctvCompanyDataParams,
|
|
28
29
|
): UseCctvCompanyDataReturn {
|
|
29
|
-
// 변경: list 조회 계약은 URL
|
|
30
|
-
const { url } = params || {};
|
|
30
|
+
// 변경: list 조회 계약은 URL override와 캐시 분리 deps만 소비한다.
|
|
31
|
+
const { url, queryKeyDeps } = params || {};
|
|
31
32
|
|
|
32
33
|
const { listUrl } = useCctvApiUrl();
|
|
33
34
|
const resolvedUrl = useMemo(() => url ?? listUrl, [url, listUrl]);
|
|
@@ -36,6 +37,7 @@ export default function useCctvCompanyData(
|
|
|
36
37
|
// URL에 맞춰 회사 리스트 API를 호출한다.
|
|
37
38
|
const { data, isFetching, isError, ...rest } = useQueryCctvCompanyList({
|
|
38
39
|
url: resolvedUrl,
|
|
40
|
+
queryKeyDeps,
|
|
39
41
|
});
|
|
40
42
|
|
|
41
43
|
// 응답 데이터를 react-hook-form rawData 필드로 반영한다.
|
package/src/cctv/types/hook.ts
CHANGED
|
@@ -114,12 +114,17 @@ export interface UseCctvRtcStreamReturn extends UseCctvRtcStreamState {
|
|
|
114
114
|
/**
|
|
115
115
|
* CCTV; useCctvCompanyData params
|
|
116
116
|
* @property {string} [url] 업체 리스트 API URL
|
|
117
|
+
* @property {readonly unknown[]} [queryKeyDeps] 업체 리스트 캐시 분리용 query key deps
|
|
117
118
|
*/
|
|
118
119
|
export interface UseCctvCompanyDataParams {
|
|
119
120
|
/**
|
|
120
121
|
* 업체 리스트 API URL
|
|
121
122
|
*/
|
|
122
123
|
url?: string;
|
|
124
|
+
/**
|
|
125
|
+
* 업체 리스트 캐시 분리용 query key deps
|
|
126
|
+
*/
|
|
127
|
+
queryKeyDeps?: readonly unknown[];
|
|
123
128
|
}
|
|
124
129
|
|
|
125
130
|
/**
|