@mesob/auth-react 0.5.7 → 0.5.9
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/{chunk-YP5V56LW.js → chunk-22KICA5N.js} +3 -3
- package/dist/{chunk-XLPPZKU2.js → chunk-22WSB5V2.js} +15 -5
- package/dist/chunk-22WSB5V2.js.map +1 -0
- package/dist/{chunk-GQFTH5DQ.js → chunk-25DJGLNU.js} +12 -8
- package/dist/chunk-25DJGLNU.js.map +1 -0
- package/dist/{chunk-W2HMARW4.js → chunk-2BF2JIDK.js} +3 -3
- package/dist/{chunk-4LHFPVAY.js → chunk-4YPLJ2P6.js} +7 -13
- package/dist/chunk-4YPLJ2P6.js.map +1 -0
- package/dist/{chunk-SA6HTWCL.js → chunk-5FNUPWPO.js} +2 -2
- package/dist/{chunk-6AV6I5B4.js → chunk-75K2SCNC.js} +3 -3
- package/dist/{chunk-YCVDEX5U.js → chunk-7QJBDRTL.js} +6 -5
- package/dist/chunk-7QJBDRTL.js.map +1 -0
- package/dist/{chunk-FCPN2FD7.js → chunk-B7BS57X7.js} +10 -4
- package/dist/chunk-B7BS57X7.js.map +1 -0
- package/dist/{chunk-FLGP4ROM.js → chunk-CBR5NTFM.js} +14 -8
- package/dist/chunk-CBR5NTFM.js.map +1 -0
- package/dist/chunk-DBTKXQV7.js +13 -0
- package/dist/chunk-DBTKXQV7.js.map +1 -0
- package/dist/{chunk-PUOQX6DR.js → chunk-DQB4WY5T.js} +4 -4
- package/dist/{chunk-TPG4RW7H.js → chunk-DRAUYDZ5.js} +2 -2
- package/dist/{chunk-IBRB7ABJ.js → chunk-G2RWFKGF.js} +2 -2
- package/dist/{chunk-EIJFTUTM.js → chunk-GP4XI5KB.js} +3 -3
- package/dist/{chunk-22AQI2FA.js → chunk-GWRMQSME.js} +5 -5
- package/dist/{chunk-XO5LLEGV.js → chunk-HOROLWBY.js} +2 -2
- package/dist/{chunk-YVHMCTLM.js → chunk-I46PN4JU.js} +2 -2
- package/dist/{chunk-VS5FEGMX.js → chunk-IUCTHMVY.js} +2 -2
- package/dist/{chunk-IFFWIROT.js → chunk-J7NROVB4.js} +2 -2
- package/dist/{chunk-FU4K62DS.js → chunk-KL2XZKDU.js} +2 -2
- package/dist/{chunk-VMAGFUOK.js → chunk-LI7WPOVY.js} +3 -3
- package/dist/{chunk-I34SXFQJ.js → chunk-LYCBL2W3.js} +4 -4
- package/dist/{chunk-A5ON3RKH.js → chunk-M2K6O5CN.js} +2 -2
- package/dist/chunk-M2K6O5CN.js.map +1 -0
- package/dist/{chunk-G4VPR4UC.js → chunk-M677DPBR.js} +2 -2
- package/dist/{chunk-BX75EFF3.js → chunk-MPZAPUVR.js} +4 -4
- package/dist/{chunk-V7HCZDJ4.js → chunk-NJGVOQIU.js} +4 -4
- package/dist/{chunk-HBQK5PAH.js → chunk-NPA7L57G.js} +2 -2
- package/dist/{chunk-TAJQ7O3U.js → chunk-ORQZZUVL.js} +2 -2
- package/dist/{chunk-5B6GREDA.js → chunk-OT2H5EHA.js} +2 -2
- package/dist/{chunk-NTDVUVZO.js → chunk-QNPK2H5A.js} +3 -3
- package/dist/{chunk-MDM3QYPM.js → chunk-QRYUUXNJ.js} +7 -6
- package/dist/chunk-QRYUUXNJ.js.map +1 -0
- package/dist/{chunk-Z4FXOZEJ.js → chunk-R7VVXH5U.js} +3 -3
- package/dist/{chunk-3GFTD46V.js → chunk-SLIIENXJ.js} +2 -2
- package/dist/{chunk-VWYJI2FU.js → chunk-TT3V6PC7.js} +4 -4
- package/dist/{chunk-ZOKBN5H4.js → chunk-UIXR5GF3.js} +2 -2
- package/dist/{chunk-XZAYLXLS.js → chunk-UV7JR3YU.js} +2 -2
- package/dist/{chunk-SX6WAVQS.js → chunk-VTANFZKG.js} +5 -5
- package/dist/{chunk-5XCUGCW7.js → chunk-VWGOCWRF.js} +9 -6
- package/dist/chunk-VWGOCWRF.js.map +1 -0
- package/dist/{chunk-WOJ3HM5R.js → chunk-WAMZL5CS.js} +4 -4
- package/dist/{chunk-DCWKYK3D.js → chunk-WY2F7475.js} +18 -10
- package/dist/chunk-WY2F7475.js.map +1 -0
- package/dist/{chunk-OMTV6IOB.js → chunk-XTLFZ77E.js} +2 -2
- package/dist/chunk-XTLFZ77E.js.map +1 -0
- package/dist/{chunk-H2W42KYL.js → chunk-Y6KURGWG.js} +2 -2
- package/dist/chunk-YR6SS2CC.js +11 -0
- package/dist/chunk-YR6SS2CC.js.map +1 -0
- package/dist/{chunk-BM3YKYGC.js → chunk-ZIUAYN37.js} +2 -2
- package/dist/components/auth/countdown.js +3 -3
- package/dist/components/auth/forgot-password.js +5 -3
- package/dist/components/auth/reset-password-form.js +3 -3
- package/dist/components/auth/set-password.js +5 -4
- package/dist/components/auth/sign-in.js +5 -4
- package/dist/components/auth/sign-up.js +5 -3
- package/dist/components/auth/verification-form.js +4 -4
- package/dist/components/auth/verify-email.js +5 -5
- package/dist/components/auth/verify-phone.js +5 -5
- package/dist/components/authorization/deny.js +2 -2
- package/dist/components/authorization/grant.js +2 -2
- package/dist/components/iam/domains-page.js +6 -6
- package/dist/components/iam/iam-guard.js +3 -3
- package/dist/components/iam/permission-selector.js +2 -2
- package/dist/components/iam/permissions-page.js +4 -4
- package/dist/components/iam/permissions.js +2 -2
- package/dist/components/iam/role-detail-layout.js +2 -2
- package/dist/components/iam/role-detail-page.js +4 -4
- package/dist/components/iam/role-permissions-page.js +5 -5
- package/dist/components/iam/roles-page.js +6 -6
- package/dist/components/iam/roles.js +2 -2
- package/dist/components/iam/sessions-page.js +6 -6
- package/dist/components/iam/sessions.js +2 -2
- package/dist/components/iam/tenants-page.js +6 -6
- package/dist/components/iam/tenants.js +2 -2
- package/dist/components/iam/users-page.js +7 -7
- package/dist/components/iam/users.js +2 -2
- package/dist/components/profile/account.js +2 -2
- package/dist/components/profile/change-email-form.js +8 -8
- package/dist/components/profile/change-password-form.js +2 -2
- package/dist/components/profile/change-phone-form.js +9 -9
- package/dist/components/profile/otp-verification-modal.js +5 -5
- package/dist/components/profile/profile-layout.js +3 -3
- package/dist/components/profile/request-change-email-form.js +2 -2
- package/dist/components/profile/request-change-phone-form.js +3 -3
- package/dist/components/profile/security.js +14 -14
- package/dist/components/profile/verify-change-email-form.js +6 -6
- package/dist/components/profile/verify-change-phone-form.js +6 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.js +48 -44
- package/dist/index.js.map +1 -1
- package/dist/pages/auth/layout.js +1 -1
- package/dist/pages/iam/tenants/tenant-selector.js +3 -3
- package/dist/pages/iam/users/user-selector.js +4 -4
- package/dist/pages/profile/account.js +1 -1
- package/dist/pages/profile/security.js +1 -1
- package/dist/utils/normalize-email.d.ts +2 -0
- package/dist/utils/normalize-phone.d.ts +1 -0
- package/package.json +4 -4
- package/dist/chunk-4LHFPVAY.js.map +0 -1
- package/dist/chunk-5XCUGCW7.js.map +0 -1
- package/dist/chunk-A5ON3RKH.js.map +0 -1
- package/dist/chunk-DCWKYK3D.js.map +0 -1
- package/dist/chunk-FCPN2FD7.js.map +0 -1
- package/dist/chunk-FLGP4ROM.js.map +0 -1
- package/dist/chunk-GQFTH5DQ.js.map +0 -1
- package/dist/chunk-MDM3QYPM.js.map +0 -1
- package/dist/chunk-OMTV6IOB.js.map +0 -1
- package/dist/chunk-V2W3WPCZ.js +0 -22
- package/dist/chunk-V2W3WPCZ.js.map +0 -1
- package/dist/chunk-XLPPZKU2.js.map +0 -1
- package/dist/chunk-YCVDEX5U.js.map +0 -1
- /package/dist/{chunk-YP5V56LW.js.map → chunk-22KICA5N.js.map} +0 -0
- /package/dist/{chunk-W2HMARW4.js.map → chunk-2BF2JIDK.js.map} +0 -0
- /package/dist/{chunk-SA6HTWCL.js.map → chunk-5FNUPWPO.js.map} +0 -0
- /package/dist/{chunk-6AV6I5B4.js.map → chunk-75K2SCNC.js.map} +0 -0
- /package/dist/{chunk-PUOQX6DR.js.map → chunk-DQB4WY5T.js.map} +0 -0
- /package/dist/{chunk-TPG4RW7H.js.map → chunk-DRAUYDZ5.js.map} +0 -0
- /package/dist/{chunk-IBRB7ABJ.js.map → chunk-G2RWFKGF.js.map} +0 -0
- /package/dist/{chunk-EIJFTUTM.js.map → chunk-GP4XI5KB.js.map} +0 -0
- /package/dist/{chunk-22AQI2FA.js.map → chunk-GWRMQSME.js.map} +0 -0
- /package/dist/{chunk-XO5LLEGV.js.map → chunk-HOROLWBY.js.map} +0 -0
- /package/dist/{chunk-YVHMCTLM.js.map → chunk-I46PN4JU.js.map} +0 -0
- /package/dist/{chunk-VS5FEGMX.js.map → chunk-IUCTHMVY.js.map} +0 -0
- /package/dist/{chunk-IFFWIROT.js.map → chunk-J7NROVB4.js.map} +0 -0
- /package/dist/{chunk-FU4K62DS.js.map → chunk-KL2XZKDU.js.map} +0 -0
- /package/dist/{chunk-VMAGFUOK.js.map → chunk-LI7WPOVY.js.map} +0 -0
- /package/dist/{chunk-I34SXFQJ.js.map → chunk-LYCBL2W3.js.map} +0 -0
- /package/dist/{chunk-G4VPR4UC.js.map → chunk-M677DPBR.js.map} +0 -0
- /package/dist/{chunk-BX75EFF3.js.map → chunk-MPZAPUVR.js.map} +0 -0
- /package/dist/{chunk-V7HCZDJ4.js.map → chunk-NJGVOQIU.js.map} +0 -0
- /package/dist/{chunk-HBQK5PAH.js.map → chunk-NPA7L57G.js.map} +0 -0
- /package/dist/{chunk-TAJQ7O3U.js.map → chunk-ORQZZUVL.js.map} +0 -0
- /package/dist/{chunk-5B6GREDA.js.map → chunk-OT2H5EHA.js.map} +0 -0
- /package/dist/{chunk-NTDVUVZO.js.map → chunk-QNPK2H5A.js.map} +0 -0
- /package/dist/{chunk-Z4FXOZEJ.js.map → chunk-R7VVXH5U.js.map} +0 -0
- /package/dist/{chunk-3GFTD46V.js.map → chunk-SLIIENXJ.js.map} +0 -0
- /package/dist/{chunk-VWYJI2FU.js.map → chunk-TT3V6PC7.js.map} +0 -0
- /package/dist/{chunk-ZOKBN5H4.js.map → chunk-UIXR5GF3.js.map} +0 -0
- /package/dist/{chunk-XZAYLXLS.js.map → chunk-UV7JR3YU.js.map} +0 -0
- /package/dist/{chunk-SX6WAVQS.js.map → chunk-VTANFZKG.js.map} +0 -0
- /package/dist/{chunk-WOJ3HM5R.js.map → chunk-WAMZL5CS.js.map} +0 -0
- /package/dist/{chunk-H2W42KYL.js.map → chunk-Y6KURGWG.js.map} +0 -0
- /package/dist/{chunk-BM3YKYGC.js.map → chunk-ZIUAYN37.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/auth/verify-phone.tsx"],"sourcesContent":["'use client';\n\nimport { Alert, AlertDescription, AlertTitle } from '@mesob/ui/components';\nimport { useMesob } from '@mesob/ui/providers';\nimport { IconAlertCircle } from '@tabler/icons-react';\nimport { useEffect, useState } from 'react';\nimport { toast } from 'sonner';\nimport { useTranslator } from '../../hooks/use-translator';\nimport { useApi, useConfig } from '../../provider';\nimport type { AuthResponse } from '../../types';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport { handleError } from '../../utils/handle-error';\nimport { AuthLayout } from './auth-layout';\nimport { VerificationForm } from './verification-form';\n\ntype VerifyPhoneProps = {\n verificationId: string;\n context: 'sign-in' | 'sign-up';\n phone?: string;\n redirectUrl?: string;\n};\n\nexport const VerifyPhone = ({\n verificationId,\n context,\n phone = '',\n redirectUrl,\n}: VerifyPhoneProps) => {\n const { hooks, refresh, setAuth } = useApi();\n const { config } = useConfig();\n const mesob = useMesob();\n const Link = mesob?.navigation?.Link;\n const t = useTranslator('Auth.verification');\n const common = useTranslator('Common');\n const footer = useTranslator('Auth.forgotPassword.footer');\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthErrorContent | null>(null);\n\n const verifyPhoneMutation = hooks.useMutation(\n 'post',\n '/phone/verification/confirm',\n );\n const requestPhoneMutation = hooks.useMutation(\n 'post',\n '/phone/verification/request',\n );\n\n const signInLink = config.navigation?.links?.signIn || '/auth/sign-in';\n const onNavigate =\n config.navigation?.onNavigate ||\n ((path: string) => {\n if (typeof window !== 'undefined') {\n window.location.href = path;\n }\n });\n const logoImage = config.ui.logoImage;\n const defaultRedirect =\n redirectUrl || config.navigation?.defaultRedirectUrl || '/';\n\n useEffect(() => {\n if (error) {\n toast.error(error.title || 'Error', {\n description: error.description,\n });\n }\n }, [error]);\n\n const handleSubmit = async (values: { code: string }) => {\n if (!verificationId) {\n setError({\n title: t('errors.fallback'),\n description: t('errors.fallback'),\n });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const res = await verifyPhoneMutation.mutateAsync({\n body: {\n verificationId,\n code: values.code,\n context,\n },\n });\n if (res && 'user' in res && 'session' in res && res.session) {\n setAuth(res as AuthResponse);\n onNavigate(defaultRedirect);\n return;\n }\n await refresh();\n onNavigate(defaultRedirect);\n } catch (err) {\n handleError(err, setError, t);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleResend = async () => {\n setError(null);\n try {\n const targetPhone = context === 'sign-up' ? phone : null;\n if (!targetPhone) {\n setError({\n title: t('errors.fallback'),\n description: t('phone.missingPhone'),\n });\n return;\n }\n const res = await requestPhoneMutation.mutateAsync({\n body: {\n phone: targetPhone,\n context,\n },\n });\n if (res && 'verificationId' in res && res.verificationId) {\n onNavigate(\n `/auth/verify-phone?context=${context}&verificationId=${res.verificationId}&phone=${targetPhone}`,\n );\n return;\n }\n setError({\n title: t('errors.fallback'),\n description: t('phone.resendFailed'),\n });\n } catch (err) {\n handleError(err, setError, t);\n }\n };\n\n if (!verificationId) {\n return (\n <AuthLayout\n title={common('invalidLinkTitle')}\n description={common('invalidLinkDescription')}\n footer={\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {footer('backToSignIn')}\n </Link>\n }\n >\n <div />\n </AuthLayout>\n );\n }\n\n let errorContent: AuthErrorContent | null = null;\n if (error) {\n if (typeof error === 'string') {\n errorContent = { title: 'Error', description: error };\n } else {\n errorContent = error;\n }\n }\n\n return (\n <AuthLayout\n title={config.ui.name}\n description={t('phone.description', {\n target: phone || t('phone.missingPhone'),\n })}\n logoImage={logoImage}\n footer={\n Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {footer('backToSignIn')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {footer('backToSignIn')}\n </a>\n )\n }\n >\n <VerificationForm\n verificationId={verificationId}\n onSubmit={handleSubmit}\n onResend={handleResend}\n isLoading={\n isLoading ||\n verifyPhoneMutation.isPending ||\n requestPhoneMutation.isPending\n }\n error={error}\n />\n {errorContent && (\n <Alert variant=\"destructive\" className=\"mt-4\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>{errorContent.title}</AlertTitle>\n <AlertDescription>{errorContent.description}</AlertDescription>\n </Alert>\n )}\n </AuthLayout>\n );\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/auth/verify-email.tsx"],"sourcesContent":["'use client';\n\nimport { Alert, AlertDescription, AlertTitle } from '@mesob/ui/components';\nimport { useMesob } from '@mesob/ui/providers';\nimport { IconAlertCircle } from '@tabler/icons-react';\nimport { useEffect, useState } from 'react';\nimport { toast } from 'sonner';\nimport { useTranslator } from '../../hooks/use-translator';\nimport { useApi, useConfig } from '../../provider';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport { handleError } from '../../utils/handle-error';\nimport { AuthLayout } from './auth-layout';\nimport { VerificationForm } from './verification-form';\n\ntype VerifyEmailProps = {\n verificationId: string;\n email: string;\n redirectUrl?: string;\n};\n\nexport const VerifyEmail = ({\n verificationId,\n email,\n redirectUrl,\n}: VerifyEmailProps) => {\n const { hooks, setAuth } = useApi();\n const { config } = useConfig();\n const mesob = useMesob();\n const t = useTranslator('Auth.verification');\n const common = useTranslator('Common');\n const footer = useTranslator('Auth.forgotPassword.footer');\n const Link = mesob?.navigation?.Link;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthErrorContent | null>(null);\n\n const verifyEmailMutation = hooks.useMutation(\n 'post',\n '/email/verification/confirm',\n );\n const requestEmailMutation = hooks.useMutation(\n 'post',\n '/email/verification/request',\n );\n\n const signInLink = config.navigation?.links?.signIn || '/auth/sign-in';\n const onNavigate =\n config.navigation?.onNavigate ||\n ((path: string) => {\n if (typeof window !== 'undefined') {\n window.location.href = path;\n }\n });\n const logoImage = config.ui.logoImage;\n const defaultRedirect =\n redirectUrl || config.navigation?.defaultRedirectUrl || '/';\n\n useEffect(() => {\n if (error) {\n toast.error(error.title || 'Error', {\n description: error.description,\n });\n }\n }, [error]);\n\n const handleSubmit = async (values: { code: string }) => {\n if (!verificationId) {\n setError({\n title: t('errors.fallback'),\n description: t('errors.missingVerificationId'),\n });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const res = await verifyEmailMutation.mutateAsync({\n body: {\n verificationId,\n code: values.code,\n },\n });\n if ('user' in res && 'session' in res) {\n setAuth(res);\n }\n onNavigate(defaultRedirect);\n } catch (err) {\n handleError(err, setError, t);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleResend = async () => {\n setError(null);\n try {\n const res = await requestEmailMutation.mutateAsync({\n body: {\n email,\n },\n });\n if (res.verificationId) {\n onNavigate(\n `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(email)}`,\n );\n } else {\n setError({\n title: t('errors.fallback'),\n description: t('errors.resendFailed'),\n });\n }\n } catch (err) {\n handleError(err, setError, t);\n }\n };\n\n if (!verificationId) {\n return (\n <AuthLayout\n title={common('invalidLinkTitle')}\n description={common('invalidLinkDescription')}\n footer={\n Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {footer('backToSignIn')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {footer('backToSignIn')}\n </a>\n )\n }\n >\n <div />\n </AuthLayout>\n );\n }\n\n let errorContent: AuthErrorContent | null = null;\n if (error) {\n if (typeof error === 'string') {\n errorContent = { title: 'Error', description: error };\n } else {\n errorContent = error;\n }\n }\n\n return (\n <AuthLayout\n title={config.ui.name}\n description={t('email.description')}\n logoImage={logoImage}\n footer={\n Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {footer('backToSignIn')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {footer('backToSignIn')}\n </a>\n )\n }\n >\n <VerificationForm\n verificationId={verificationId}\n onSubmit={handleSubmit}\n onResend={handleResend}\n isLoading={\n isLoading ||\n verifyEmailMutation.isPending ||\n requestEmailMutation.isPending\n }\n error={error}\n />\n {errorContent && (\n <Alert variant=\"destructive\" className=\"mt-4\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>{errorContent.title}</AlertTitle>\n <AlertDescription>{errorContent.description}</AlertDescription>\n </Alert>\n )}\n </AuthLayout>\n );\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/auth/sign-in.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n Alert,\n AlertDescription,\n AlertTitle,\n Button,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n useFormField,\n} from '@mesob/ui/components';\nimport { useMesob } from '@mesob/ui/providers';\nimport { IconAlertCircle, IconEye, IconEyeOff } from '@tabler/icons-react';\nimport type { ChangeEvent, ComponentProps } from 'react';\nimport { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useTranslator } from '../../hooks/use-translator';\nimport { useApi, useConfig } from '../../provider';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport {\n handleError,\n normalizeOpenapiErrorBody,\n} from '../../utils/handle-error';\nimport { normalizePhone } from '../../utils/normalize-phone';\nimport { AuthLayout } from './auth-layout';\n\nconst isPhone = (s: string) => /^\\+?[0-9()[\\]\\s-]{6,}$/.test(s);\n\ntype PasswordInputProps = {\n field: ComponentProps<'input'> & {\n value: string;\n onChange: (e: ChangeEvent<HTMLInputElement>) => void;\n onBlur: () => void;\n };\n show: boolean;\n onToggle: () => void;\n};\n\nfunction PasswordInput({ field, show, onToggle }: PasswordInputProps) {\n const { formItemId, error } = useFormField();\n return (\n <div className=\"relative\">\n <Input\n {...field}\n id={formItemId}\n type={show ? 'text' : 'password'}\n autoComplete=\"current-password\"\n aria-invalid={!!error}\n className=\"pr-10\"\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-0 top-0 h-full px-3 text-muted-foreground hover:text-foreground\"\n onClick={onToggle}\n aria-label={show ? 'Hide password' : 'Show password'}\n >\n {show ? (\n <IconEyeOff className=\"h-4 w-4\" />\n ) : (\n <IconEye className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n );\n}\n\ntype SignInProps = {\n redirectUrl?: string;\n};\n\ntype SignInValidationOptions = {\n phoneRegex: RegExp;\n allowEmailSignIn: boolean;\n allowPhoneSignIn: boolean;\n};\n\nconst signInSchema = (\n t: (key: string) => string,\n options: SignInValidationOptions,\n) =>\n z.object({\n username: z\n .string()\n .trim()\n .min(1, { message: t('errors.requiredField') })\n .superRefine((value, ctx) => {\n const emailInput = z.email().safeParse(value).success;\n const phoneInput = options.phoneRegex.test(value);\n if (!(emailInput || phoneInput)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: t('errors.invalidEmailOrPhone'),\n });\n return;\n }\n if (emailInput && !options.allowEmailSignIn) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'Email sign in is disabled',\n });\n return;\n }\n if (phoneInput && !options.allowPhoneSignIn) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'Phone sign in is disabled',\n });\n }\n }),\n password: z\n .union([\n z.literal(''),\n z\n .string()\n .min(8, t('errors.passwordLength'))\n .max(128, t('errors.longPasswordError')),\n ])\n .optional(),\n });\n\ntype SignInFormValues = z.infer<ReturnType<typeof signInSchema>>;\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: multi-step form with two form contexts\nexport const SignIn = ({ redirectUrl }: SignInProps = {}) => {\n const { hooks, setAuth } = useApi();\n const { config } = useConfig();\n const mesob = useMesob();\n const t = useTranslator('Auth.signIn');\n const Link = mesob?.navigation?.Link;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthErrorContent | null>(null);\n const [showPasswordField, setShowPasswordField] = useState(false);\n const [showPassword, setShowPassword] = useState(false);\n const [username, setUsername] = useState('');\n const [isChecking, setIsChecking] = useState(false);\n\n const checkUserMutation = hooks.useMutation('post', '/check-account');\n const signInMutation = hooks.useMutation('post', '/sign-in');\n\n const phoneRegex =\n typeof config.phoneRegex === 'string'\n ? new RegExp(config.phoneRegex)\n : config.phoneRegex || /^(\\+2519|\\+2517|2519|2517|09|07)\\d{8}$/;\n const allowEmailSignIn = config.features?.enableEmailSignIn !== false;\n const allowPhoneSignIn = config.features?.enablePhoneSignIn !== false;\n const enableSignup = config.features?.enableSignup !== false;\n const allowEmailSignup = config.features?.enableEmailSignup !== false;\n const allowPhoneSignup = config.features?.enablePhoneSignup !== false;\n const hasSignInIdentifierChannel = allowEmailSignIn || allowPhoneSignIn;\n\n const defaultRedirect =\n redirectUrl || config.navigation?.defaultRedirectUrl || '/';\n const forgotPasswordLink =\n config.navigation?.links?.forgotPassword || '/auth/forgot-password';\n const signUpLink = config.navigation?.links?.signUp || '/auth/sign-up';\n const setPasswordLink =\n config.navigation?.links?.setPassword || '/auth/set-password';\n const onNavigate =\n config.navigation?.onNavigate ||\n ((path: string) => {\n if (typeof window !== 'undefined') {\n window.location.href = path;\n }\n });\n const logoImage = config.ui.logoImage;\n\n const form = useForm<SignInFormValues>({\n resolver: zodResolver(\n signInSchema(t, {\n phoneRegex,\n allowEmailSignIn,\n allowPhoneSignIn,\n }),\n ),\n defaultValues: { username: '', password: '' },\n mode: 'onSubmit',\n reValidateMode: 'onSubmit',\n });\n\n useEffect(() => {\n if (error) {\n toast.error(error.title || 'Error', {\n description: error.description,\n });\n }\n }, [error]);\n\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: auth branching is intentional\n const handleCheckAccount = async (usernameValue: string) => {\n if (!hasSignInIdentifierChannel) {\n form.setError('username', {\n message: 'Sign in is unavailable for email and phone',\n });\n return;\n }\n setIsChecking(true);\n try {\n const normalizedUsername = phoneRegex.test(usernameValue)\n ? normalizePhone(usernameValue)\n : usernameValue;\n const emailInput = z.email().safeParse(normalizedUsername).success;\n if (emailInput) {\n if (!allowEmailSignIn) {\n form.setError('username', { message: 'Email sign in is disabled' });\n return;\n }\n } else if (!allowPhoneSignIn) {\n form.setError('username', { message: 'Phone sign in is disabled' });\n return;\n }\n\n const result = await checkUserMutation.mutateAsync({\n body: {\n username: normalizedUsername,\n },\n });\n\n if (result.exists) {\n if (result.requiresPasswordSetup) {\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n onNavigate(\n `${setPasswordLink}?identifier=${encodeURIComponent(normalizedUsername)}${redirectParam}`,\n );\n return;\n }\n\n if (\n !result.verified &&\n result.needsVerification &&\n result.verificationId\n ) {\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n const verifyPath = isPhone(normalizedUsername)\n ? `/auth/verify-phone?context=sign-in&verificationId=${result.verificationId}&identifier=${encodeURIComponent(normalizedUsername)}${redirectParam}`\n : `/auth/verify-email?verificationId=${result.verificationId}&email=${encodeURIComponent(normalizedUsername)}${redirectParam}`;\n onNavigate(verifyPath);\n return;\n }\n\n setUsername(normalizedUsername);\n form.setValue('username', normalizedUsername);\n setShowPasswordField(true);\n } else {\n if (!enableSignup) {\n form.setError('username', { message: 'Sign up is disabled' });\n return;\n }\n const email = isPhone(normalizedUsername) ? '' : normalizedUsername;\n if (email) {\n if (!allowEmailSignup) {\n form.setError('username', { message: 'Email sign up is disabled' });\n return;\n }\n } else if (!allowPhoneSignup) {\n form.setError('username', { message: 'Phone sign up is disabled' });\n return;\n }\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n if (email) {\n onNavigate(\n `${signUpLink}?email=${encodeURIComponent(email)}${redirectParam}`,\n );\n } else {\n onNavigate(\n `${signUpLink}?phone=${encodeURIComponent(normalizedUsername)}${redirectParam}`,\n );\n }\n }\n } catch (err) {\n if (normalizeOpenapiErrorBody(err)) {\n handleError(err, setError, t);\n } else {\n form.setError('username', { message: t('errors.checkAccountFailed') });\n }\n } finally {\n setIsChecking(false);\n }\n };\n\n const onSubmit = async (values: SignInFormValues) => {\n if (showPasswordField) {\n const pwd = values.password;\n if (!pwd || pwd.length < 8) {\n form.setError('password', { message: t('errors.passwordLength') });\n return;\n }\n await handlePasswordSubmit({ password: pwd });\n } else {\n await handleCheckAccount(values.username);\n }\n };\n\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: auth branching is intentional\n const handlePasswordSubmit = async (values: { password: string }) => {\n setIsLoading(true);\n setError(null);\n\n try {\n const res = await signInMutation.mutateAsync({\n body: {\n identifier: username,\n password: values.password,\n },\n });\n\n if ('verificationId' in res && res.verificationId) {\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n const verifyPath = isPhone(username)\n ? `/auth/verify-phone?context=sign-in&verificationId=${res.verificationId}&identifier=${encodeURIComponent(username)}${redirectParam}`\n : `/auth/verify-email?verificationId=${res.verificationId}${redirectParam}`;\n onNavigate(verifyPath);\n return;\n }\n\n if ('user' in res && 'session' in res) {\n setAuth(res);\n }\n onNavigate(defaultRedirect);\n } catch (err) {\n const authError = err as { code?: string; message?: string };\n const errorCode = authError.code || authError.message;\n if (errorCode === 'HAS_NO_PASSWORD') {\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n onNavigate(\n `${setPasswordLink}?identifier=${encodeURIComponent(username)}${redirectParam}`,\n );\n return;\n }\n handleError(err, setError, t, { signIn: true });\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleBack = () => {\n setShowPasswordField(false);\n setUsername('');\n form.setValue('password', '');\n };\n\n const isSubmitting =\n isLoading ||\n checkUserMutation.isPending ||\n signInMutation.isPending ||\n isChecking;\n\n let submitLabel = t('form.continue');\n if (isSubmitting) {\n submitLabel = showPasswordField ? t('form.submitting') : t('form.checking');\n } else if (showPasswordField) {\n submitLabel = t('form.submit');\n }\n\n let accountLabel = t('form.accountLabel');\n if (allowEmailSignIn && !allowPhoneSignIn) {\n accountLabel = 'Email';\n } else if (!allowEmailSignIn && allowPhoneSignIn) {\n accountLabel = 'Phone';\n }\n\n let errorContent: AuthErrorContent | null = null;\n if (error) {\n if (typeof error === 'string') {\n errorContent = { title: 'Error', description: error };\n } else {\n errorContent = error;\n }\n }\n\n const formContent = (\n <Form {...form}>\n <form\n id=\"sign-in-form\"\n autoComplete=\"on\"\n onSubmit={form.handleSubmit(onSubmit)}\n className=\"space-y-4\"\n >\n {showPasswordField ? (\n <>\n <FormItem>\n <FormLabel className=\"flex justify-between items-center\">\n {accountLabel}\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"sm\"\n className=\"p-0 m-0 h-auto\"\n onClick={handleBack}\n >\n {t('changeAccount')}\n </Button>\n </FormLabel>\n <Input\n id=\"sign-in-username\"\n type=\"text\"\n value={username}\n autoComplete=\"username\"\n disabled\n />\n </FormItem>\n <FormField\n control={form.control}\n name=\"password\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.passwordLabel')}</FormLabel>\n <PasswordInput\n field={{ ...field, value: field.value ?? '' }}\n show={showPassword}\n onToggle={() => setShowPassword(!showPassword)}\n />\n <FormMessage />\n </FormItem>\n )}\n />\n </>\n ) : (\n <FormField\n control={form.control}\n name=\"username\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{accountLabel}</FormLabel>\n <FormControl>\n <Input\n {...field}\n type={\n allowEmailSignIn && !allowPhoneSignIn ? 'email' : 'text'\n }\n autoComplete={\n allowEmailSignIn && !allowPhoneSignIn\n ? 'email'\n : 'username'\n }\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n )}\n <Button\n type=\"submit\"\n className=\"w-full\"\n disabled={isSubmitting}\n loading={isSubmitting}\n >\n {submitLabel}\n </Button>\n </form>\n </Form>\n );\n\n return (\n <div className=\"space-y-4\">\n <AuthLayout\n title={config.ui.name}\n description={t('description')}\n logoImage={logoImage}\n footer={\n showPasswordField ? (\n <div className=\"flex items-center justify-center w-full\">\n {Link ? (\n <Link\n href={forgotPasswordLink}\n className=\"text-primary inline-block hover:underline\"\n >\n {t('footer.forgotPassword')}\n </Link>\n ) : (\n <a\n href={forgotPasswordLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(forgotPasswordLink);\n }}\n className=\"text-primary inline-block hover:underline\"\n >\n {t('footer.forgotPassword')}\n </a>\n )}\n </div>\n ) : undefined\n }\n >\n {formContent}\n {errorContent && (\n <Alert variant=\"destructive\" className=\"mt-4\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>{errorContent.title}</AlertTitle>\n <AlertDescription>{errorContent.description}</AlertDescription>\n </Alert>\n )}\n </AuthLayout>\n </div>\n );\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/iam/roles-page.tsx","../src/pages/iam/roles/_components/role-form.tsx","../src/pages/iam/roles/_components/roles-list.tsx","../src/pages/iam/roles/_components/role-card.tsx"],"sourcesContent":["'use client';\n\nimport {\n Button,\n EntityDrawerTrigger,\n EntityFilter,\n EntityHeader,\n EntitySearch,\n EntitySort,\n EntityViewToggle,\n PageBody,\n PageContainer,\n useBreadcrumbs,\n useEntityPagination,\n useEntityParams,\n} from '@mesob/ui/components';\nimport { IconShield } from '@tabler/icons-react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useState } from 'react';\nimport { toast } from 'sonner';\nimport type { paths } from '../../data/openapi';\nimport { defaultEntityQueryOptions } from '../../lib/query-options';\nimport { RoleForm } from '../../pages/iam/roles/_components/role-form';\nimport { RolesList } from '../../pages/iam/roles/_components/roles-list';\nimport { useApi, useConfig } from '../../provider';\nimport { IAMGuard } from './iam-guard';\n\nexport function RolesPage() {\n return (\n <IAMGuard>\n <RolesPageContent />\n </IAMGuard>\n );\n}\n\nfunction RolesPageContent() {\n const { hooks } = useApi();\n const { config } = useConfig();\n const homeHref = config.navigation?.defaultRedirectUrl || '/';\n const qc = useQueryClient();\n useBreadcrumbs({\n items: [\n { label: 'Home', href: homeHref },\n { label: 'IAM', href: '/iam/roles' },\n { label: 'Roles' },\n ],\n });\n\n const [createOpen, setCreateOpen] = useState(false);\n const { queryConfig, params, setParams } = useEntityParams({\n searchKey: 'search',\n });\n const rolesQuery = queryConfig as {\n params: {\n query: NonNullable<paths['/roles']['get']['parameters']['query']>;\n };\n };\n\n const { data, isPending, isFetching } = hooks.useQuery(\n 'get',\n '/roles',\n rolesQuery,\n defaultEntityQueryOptions,\n );\n\n const seedRoles = hooks.useMutation('post', '/roles/seed', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/roles'] });\n toast.success('Roles seeded');\n },\n onError: () => {\n toast.error('Failed to seed roles');\n },\n });\n\n const isLoading = isPending || isFetching;\n const roles = data?.roles ?? [];\n const { total, pageCount } = useEntityPagination({\n items: roles,\n total: data?.total,\n pageSize: params.pageSize,\n });\n\n return (\n <PageContainer className=\"flex flex-1 flex-col gap-4 p-4 pt-0\">\n <PageBody className=\"px-0\">\n <EntityHeader\n icon={<IconShield className=\"h-5 w-5\" />}\n title=\"Roles\"\n actions={\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"outline\"\n onClick={() => seedRoles.mutate({})}\n loading={seedRoles.isPending}\n >\n Seed Roles\n </Button>\n <EntityDrawerTrigger\n mode=\"new\"\n entity=\"Role\"\n open={createOpen}\n onOpenChange={setCreateOpen}\n >\n {(open, onClose) => (\n <RoleForm mode=\"new\" open={open} onClose={onClose} />\n )}\n </EntityDrawerTrigger>\n </div>\n }\n search={\n <EntitySearch paramKey=\"search\" placeholder=\"Search roles...\" />\n }\n filter={\n <EntityFilter\n options={[\n { label: 'All', value: '' },\n { label: 'By Code', value: 'code' },\n ]}\n placeholder=\"Filter\"\n />\n }\n sort={\n <EntitySort\n options={[\n { label: 'Created', value: 'createdAt' },\n { label: 'Updated', value: 'updatedAt' },\n { label: 'Code', value: 'code' },\n ]}\n />\n }\n view={<EntityViewToggle views={['table', 'card']} />}\n />\n <RolesList\n data={roles}\n isLoading={isLoading}\n view={(params.view || 'table') as 'table' | 'card'}\n pageIndex={params.page - 1}\n pageSize={params.pageSize}\n pageCount={pageCount}\n totalRows={total}\n onCreateNew={() => setCreateOpen(true)}\n onPageChange={(p) => setParams({ page: p + 1 })}\n onPageSizeChange={(size) => setParams({ pageSize: size, page: 1 })}\n />\n </PageBody>\n </PageContainer>\n );\n}\n","'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n EntityDrawer,\n EntityFormActions,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n LocaleInputText,\n LocaleInputTextarea,\n Skeleton,\n} from '@mesob/ui/components';\nimport { useLocaleConfig, useLocaleSchemas } from '@mesob/ui/providers';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useEffect, useMemo } from 'react';\nimport type { Resolver } from 'react-hook-form';\nimport { useForm, useWatch } from 'react-hook-form';\nimport { z } from 'zod';\nimport { authApi$ } from '../../shared/page-helpers';\n\ntype RoleFormData = {\n name: Record<string, string>;\n code: string;\n description: Record<string, string>;\n permissionIds: string[];\n};\n\ntype RoleFormProps = {\n mode: 'new' | 'edit';\n roleId?: string;\n open: boolean;\n onClose: () => void;\n onSuccess?: () => void;\n};\n\nexport function RoleForm({\n mode,\n roleId,\n open,\n onClose,\n onSuccess,\n}: RoleFormProps) {\n const qc = useQueryClient();\n const { localeInputDefault, requiredSchema, optionalSchema } =\n useLocaleSchemas();\n const { defaultLanguage } = useLocaleConfig();\n const schema = useMemo(\n () =>\n z.object({\n name: requiredSchema,\n code: z.string().min(1, 'Code is required'),\n description: optionalSchema,\n permissionIds: z.array(z.string()),\n }),\n [requiredSchema, optionalSchema],\n );\n const defaults: RoleFormData = useMemo(\n () => ({\n name: { ...localeInputDefault },\n code: '',\n description: { ...localeInputDefault },\n permissionIds: [],\n }),\n [localeInputDefault],\n );\n\n const { data, isLoading } = authApi$.useQuery(\n 'get',\n '/roles/{id}',\n { params: { path: { id: roleId ?? '' } } },\n { enabled: mode === 'edit' && !!roleId },\n );\n const create = authApi$.useMutation('post', '/roles', {\n onSuccess: () => qc.invalidateQueries({ queryKey: ['get', '/roles'] }),\n });\n const update = authApi$.useMutation('put', '/roles/{id}', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/roles'] });\n if (roleId) {\n qc.invalidateQueries({ queryKey: ['get', '/roles/{id}'] });\n }\n },\n });\n const del = authApi$.useMutation('delete', '/roles/{id}', {\n onSuccess: () => qc.invalidateQueries({ queryKey: ['get', '/roles'] }),\n });\n\n const form = useForm<RoleFormData>({\n resolver: zodResolver(schema) as Resolver<RoleFormData>,\n defaultValues: defaults,\n });\n\n const { reset, formState, control, register, setValue } = form;\n const nameVal = useWatch({ control, name: 'name' });\n const codeVal = useWatch({ control, name: 'code' });\n\n useEffect(() => {\n const nameDefault =\n typeof nameVal === 'object' &&\n nameVal !== null &&\n defaultLanguage in nameVal\n ? ((nameVal as Record<string, string>)[defaultLanguage] ?? '')\n : '';\n if (\n mode === 'new' &&\n typeof nameDefault === 'string' &&\n nameDefault.trim().length > 0 &&\n !codeVal\n ) {\n const code = nameDefault\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '');\n if (code) {\n setValue('code', code);\n }\n }\n }, [mode, nameVal, setValue, codeVal, defaultLanguage]);\n\n useEffect(() => {\n if (!open) {\n return;\n }\n if (mode === 'edit' && data?.role && !isLoading) {\n const r = data.role;\n reset({\n name: (r.name ?? {}) as RoleFormData['name'],\n code: r.code,\n description: (r.description ?? {}) as RoleFormData['description'],\n permissionIds: r.permissionIds ?? [],\n });\n } else {\n reset({ ...defaults, permissionIds: [] });\n }\n }, [mode, data, open, isLoading, reset, defaults]);\n\n const onSubmit = form.handleSubmit(async (d) => {\n const body = {\n name: d.name,\n code: d.code,\n description: d.description ?? undefined,\n permissionIds: d.permissionIds,\n };\n if (mode === 'new') {\n await create.mutateAsync({ body });\n } else if (roleId) {\n await update.mutateAsync({\n params: { path: { id: roleId } },\n body,\n });\n }\n onSuccess?.();\n onClose();\n });\n\n const onDelete = async () => {\n if (!roleId) {\n return;\n }\n await del.mutateAsync({ params: { path: { id: roleId } } });\n onSuccess?.();\n onClose();\n };\n\n const editable = mode === 'new' || data?.role?.isEditable !== false;\n\n return (\n <EntityDrawer\n title={mode === 'new' ? 'New role' : 'Edit role'}\n open={open}\n onClose={onClose}\n isDirty={formState.isDirty}\n size=\"md\"\n form={\n isLoading ? (\n <FormSkeleton />\n ) : (\n <Form {...form}>\n <form onSubmit={onSubmit} className=\"space-y-4\">\n <LocaleInputText\n label=\"Name\"\n field=\"name\"\n required\n register={register}\n errors={formState.errors}\n placeholder=\"e.g. Administrator\"\n disabled={!editable}\n />\n <FormField\n control={control}\n name=\"code\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n Code <span className=\"text-destructive\">*</span>\n </FormLabel>\n <FormControl>\n <Input\n placeholder=\"e.g. admin\"\n disabled={!editable}\n {...field}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <LocaleInputTextarea\n label=\"Description\"\n field=\"description\"\n register={register}\n errors={formState.errors}\n placeholder=\"Description\"\n rows={3}\n disabled={!editable}\n />\n </form>\n </Form>\n )\n }\n actions={\n <EntityFormActions\n mode={mode}\n onSubmit={onSubmit}\n onReset={mode === 'new' ? () => reset(defaults) : undefined}\n onDelete={mode === 'edit' ? onDelete : undefined}\n isSubmitting={create.isPending || update.isPending}\n isDeleting={del.isPending}\n disabled={isLoading || !editable}\n itemName=\"role\"\n />\n }\n />\n );\n}\n\nfunction FormSkeleton() {\n return (\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-16\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-14\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-20 w-full\" />\n </div>\n </div>\n );\n}\n","'use client';\n\nimport {\n Badge,\n DataTableAction,\n DataTablePagination,\n DisplayTable,\n EntityEmptyState,\n EntityLoadingState,\n Tbody,\n Td,\n Th,\n Thead,\n Tr,\n} from '@mesob/ui/components';\nimport { IconCalendar, IconShield } from '@tabler/icons-react';\nimport { useState } from 'react';\nimport { Link } from '../../shared/page-helpers';\nimport { RoleCard } from './role-card';\nimport { RoleForm } from './role-form';\nimport type { Role } from './roles-data';\nimport { str } from './roles-data';\n\nconst TABLE_COLUMN_COUNT = 5;\n\ntype RolesListProps = {\n data: Role[];\n isLoading?: boolean;\n view: 'table' | 'card';\n pageIndex: number;\n pageSize: number;\n pageCount: number;\n totalRows: number;\n onPageChange: (page: number) => void;\n onPageSizeChange: (size: number) => void;\n onCreateNew?: () => void;\n};\n\nexport function RolesList({\n data,\n isLoading,\n view,\n pageIndex,\n pageSize,\n pageCount,\n totalRows,\n onPageChange,\n onPageSizeChange,\n onCreateNew,\n}: RolesListProps) {\n const [drawerRole, setDrawerRole] = useState<Role | null>(null);\n\n if (isLoading) {\n return (\n <EntityLoadingState\n view={view}\n rowCount={pageSize}\n columnCount={TABLE_COLUMN_COUNT}\n cardCount={pageSize}\n />\n );\n }\n if (totalRows === 0) {\n return (\n <EntityEmptyState\n icon={IconShield}\n entityName=\"role\"\n title=\"No roles yet\"\n description=\"Create your first role to get started.\"\n onAction={onCreateNew}\n />\n );\n }\n if (view === 'table') {\n return (\n <div className=\"space-y-4\">\n {drawerRole ? (\n <RoleForm\n mode=\"edit\"\n roleId={drawerRole.id}\n open\n onClose={() => setDrawerRole(null)}\n onSuccess={() => setDrawerRole(null)}\n />\n ) : null}\n <DisplayTable withTableBorder>\n <Thead>\n <Tr>\n <Th>Role</Th>\n <Th>Description</Th>\n <Th>Access</Th>\n <Th>Created</Th>\n <Th className=\"w-[50px]\" />\n </Tr>\n </Thead>\n <Tbody>\n {data.map((role) => (\n <Tr key={role.id} className=\"group\">\n <Td>\n <Link\n href={`/iam/roles/${role.id}`}\n className=\"block text-left font-medium hover:text-primary hover:underline cursor-pointer\"\n >\n <p>{str(role.name) || role.code}</p>\n </Link>\n </Td>\n <Td>\n <span className=\"text-muted-foreground line-clamp-1 max-w-[200px]\">\n {str(role.description) || '—'}\n </span>\n </Td>\n <Td>\n <div className=\"flex flex-wrap gap-2\">\n {role.isSystem ? <Badge>System</Badge> : null}\n <Badge variant=\"secondary\">\n {role.permissionCount ?? role.permissionIds?.length ?? 0}{' '}\n permissions\n </Badge>\n </div>\n </Td>\n <Td>\n <div className=\"flex items-center gap-1 text-muted-foreground\">\n <IconCalendar className=\"h-4 w-4\" />\n {new Date(role.createdAt).toLocaleDateString()}\n </div>\n </Td>\n <Td>\n <DataTableAction onClick={() => setDrawerRole(role)} />\n </Td>\n </Tr>\n ))}\n </Tbody>\n </DisplayTable>\n <DataTablePagination\n pageIndex={pageIndex}\n pageSize={pageSize}\n pageCount={pageCount}\n totalRows={totalRows}\n onPageChange={onPageChange}\n onPageSizeChange={onPageSizeChange}\n />\n </div>\n );\n }\n return (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n {data.map((r) => (\n <RoleCard key={r.id} role={r} />\n ))}\n </div>\n <DataTablePagination\n pageIndex={pageIndex}\n pageSize={pageSize}\n pageCount={pageCount}\n totalRows={totalRows}\n onPageChange={onPageChange}\n onPageSizeChange={onPageSizeChange}\n />\n </div>\n );\n}\n","'use client';\n\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n} from '@mesob/ui/components';\nimport { IconDots, IconExternalLink } from '@tabler/icons-react';\nimport { useRouter } from '../../shared/page-helpers';\nimport type { Role } from './roles-data';\nimport { str } from './roles-data';\n\ntype RoleCardProps = {\n role: Role;\n mode?: 'navigate' | 'static';\n};\n\nexport function RoleCard({ role, mode = 'navigate' }: RoleCardProps) {\n const router = useRouter();\n const canNavigate = mode === 'navigate';\n\n return (\n <Card className=\"group transition-shadow hover:shadow-md\">\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-start justify-between\">\n <button\n type=\"button\"\n onClick={() => {\n if (canNavigate) {\n router.push(`/iam/roles/${role.id}`);\n }\n }}\n className=\"text-left font-semibold hover:text-primary hover:underline\"\n >\n {str(role.name) || role.code}\n </button>\n {canNavigate ? (\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 opacity-0 transition-opacity group-hover:opacity-100\"\n />\n }\n >\n <IconDots className=\"h-4 w-4\" />\n </DropdownMenuTrigger>\n <DropdownMenuPortal>\n <DropdownMenuContent>\n <DropdownMenuItem\n onClick={() => router.push(`/iam/roles/${role.id}`)}\n >\n <IconExternalLink className=\"mr-2 h-4 w-4\" />\n Open\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenuPortal>\n </DropdownMenu>\n ) : null}\n </div>\n <Badge variant=\"outline\" className=\"text-xs\">\n {role.code}\n </Badge>\n </CardHeader>\n <CardContent>\n <div className=\"mb-3 flex flex-wrap gap-2\">\n {role.isSystem ? <Badge>System</Badge> : null}\n <Badge variant=\"secondary\">\n {role.permissionCount ?? role.permissionIds?.length ?? 0}{' '}\n permissions\n </Badge>\n <Badge variant=\"outline\">{role.userCount ?? 0} users</Badge>\n </div>\n {str(role.description) && (\n <p className=\"line-clamp-2 text-sm text-muted-foreground\">\n {str(role.description)}\n </p>\n )}\n <p className=\"mt-2 text-xs text-muted-foreground\">\n Created {new Date(role.createdAt).toLocaleDateString()}\n </p>\n </CardContent>\n </Card>\n );\n}\n"],"mappings":"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","names":["Button","IconShield","useQueryClient","useState","Badge","jsx","jsxs","jsx","jsxs","Badge","jsx","jsxs","useQueryClient","useState","IconShield","Button"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pages/iam/users/_components/user-card.tsx","../src/pages/iam/users/_components/user-form.tsx"],"sourcesContent":["'use client';\n\nimport {\n Button,\n Card,\n CardContent,\n CardHeader,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@mesob/ui/components';\nimport { IconCircleCheck, IconDots, IconPencil } from '@tabler/icons-react';\nimport { useState } from 'react';\nimport { Link } from '../../shared/page-helpers';\nimport { UserForm } from './user-form';\nimport type { User } from './users-data';\n\ntype UserCardProps = { user: User };\n\nexport function UserCard({ user }: UserCardProps) {\n const [editOpen, setEditOpen] = useState(false);\n return (\n <>\n <Card className=\"group hover:shadow-md transition-shadow\">\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-start justify-between\">\n <Link\n href={`/iam/users/${user.id}`}\n className=\"text-left font-semibold hover:text-primary hover:underline\"\n >\n {user.fullName}\n </Link>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 opacity-0 group-hover:opacity-100 transition-opacity\"\n />\n }\n >\n <IconDots className=\"h-4 w-4\" />\n </DropdownMenuTrigger>\n <DropdownMenuPortal>\n <DropdownMenuContent>\n <DropdownMenuItem onClick={() => setEditOpen(true)}>\n <IconPencil className=\"mr-2 h-4 w-4\" />\n Edit\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenuPortal>\n </DropdownMenu>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {user.email && (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm\">{user.email}</span>\n {user.emailVerified && (\n <Tooltip>\n <TooltipTrigger>\n <IconCircleCheck className=\"size-4 text-muted-foreground\" />\n </TooltipTrigger>\n <TooltipContent>Email verified</TooltipContent>\n </Tooltip>\n )}\n </div>\n )}\n <p className=\"text-xs text-muted-foreground\">\n Last sign in{' '}\n {user.lastSignInAt\n ? new Date(user.lastSignInAt).toLocaleDateString()\n : 'never'}\n </p>\n </CardContent>\n </Card>\n {editOpen && (\n <UserForm\n mode=\"edit\"\n userId={user.id}\n open={editOpen}\n onClose={() => setEditOpen(false)}\n />\n )}\n </>\n );\n}\n","'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n Button,\n Checkbox,\n EntityDrawer,\n EntityFormActions,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n Skeleton,\n Stack,\n} from '@mesob/ui/components';\nimport { IconBan, IconUserCheck } from '@tabler/icons-react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useForm, useWatch } from 'react-hook-form';\nimport { z } from 'zod';\nimport type { Role } from '../../roles/_components/roles-data';\nimport { str } from '../../roles/_components/roles-data';\nimport { authApi$ } from '../../shared/page-helpers';\n\nconst schema = z.object({\n fullName: z.string().trim().min(1, 'Full name is required'),\n email: z.string().email('Invalid email').nullable().or(z.literal('')),\n phone: z.string().nullable(),\n emailVerified: z.boolean(),\n phoneVerified: z.boolean(),\n roleIds: z.array(z.string().uuid()),\n});\n\ntype FormData = z.infer<typeof schema>;\n\nconst defaults: FormData = {\n fullName: '',\n email: '',\n phone: null,\n emailVerified: false,\n phoneVerified: false,\n roleIds: [],\n};\n\ntype UserFormProps = {\n mode: 'new' | 'edit';\n userId?: string;\n open: boolean;\n onClose: () => void;\n onSuccess?: () => void;\n};\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: form + roles section\nexport function UserForm({\n mode,\n userId,\n open,\n onClose,\n onSuccess,\n}: UserFormProps) {\n const qc = useQueryClient();\n const { data: userData, isLoading: userLoading } = authApi$.useQuery(\n 'get',\n '/users/{id}',\n { params: { path: { id: userId ?? '' } } },\n {\n enabled: mode === 'edit' && !!userId && open,\n refetchOnMount: 'always',\n },\n );\n const { data: rolesData } = authApi$.useQuery(\n 'get',\n '/roles',\n { params: { query: { limit: 100 } } },\n { enabled: open },\n );\n const allRoles = rolesData?.roles ?? [];\n const roles = allRoles\n .filter((r: Role) => (r.code ?? '').toLowerCase() !== 'owner')\n .sort((a: Role, b: Role) =>\n (str(a.name) || a.code)\n .toLowerCase()\n .localeCompare((str(b.name) || b.code).toLowerCase()),\n );\n const user = userData?.user;\n\n const form = useForm<FormData>({\n resolver: zodResolver(schema),\n defaultValues: defaults,\n });\n const { control, formState, reset, setValue } = form;\n const email = useWatch({ control, name: 'email' }) ?? '';\n const phone = useWatch({ control, name: 'phone' }) ?? '';\n const roleIds = useWatch({ control, name: 'roleIds' }) ?? [];\n const hasEmail = (email ?? '').toString().trim().length > 0;\n const hasPhone = (phone ?? '').toString().trim().length > 0;\n\n useEffect(() => {\n if (!hasEmail) {\n setValue('emailVerified', false, { shouldDirty: false });\n }\n if (!hasPhone) {\n setValue('phoneVerified', false, { shouldDirty: false });\n }\n }, [hasEmail, hasPhone, setValue]);\n\n useEffect(() => {\n if (!open) {\n return;\n }\n if (mode === 'edit' && user && !userLoading) {\n reset({\n fullName: user.fullName,\n email: user.email ?? '',\n phone: user.phone ?? null,\n emailVerified: user.emailVerified ?? false,\n phoneVerified: user.phoneVerified ?? false,\n roleIds: user.roles ?? [],\n });\n } else {\n reset(defaults);\n }\n }, [mode, user, open, userLoading, reset]);\n\n const create = authApi$.useMutation('post', '/users', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/users'] });\n },\n });\n const update = authApi$.useMutation('put', '/users/{id}', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/users'] });\n qc.invalidateQueries({ queryKey: ['get', '/users/{id}'] });\n },\n });\n const del = authApi$.useMutation('delete', '/users/{id}', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/users'] });\n },\n });\n const ban = authApi$.useMutation('post', '/users/{id}/ban', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/users'] });\n qc.invalidateQueries({ queryKey: ['get', '/users/{id}'] });\n },\n });\n const bannedUntil = (user as { bannedUntil?: string | null } | undefined)\n ?.bannedUntil;\n const isBanned = !!bannedUntil && new Date(bannedUntil) > new Date();\n\n const onSubmit = form.handleSubmit(async (d) => {\n const base = {\n fullName: d.fullName,\n email: d.email?.trim() || undefined,\n phone: d.phone?.trim() || undefined,\n emailVerified: d.emailVerified,\n phoneVerified: d.phoneVerified,\n };\n if (mode === 'new') {\n await create.mutateAsync({\n body: {\n ...base,\n email: base.email || undefined,\n phone: base.phone || undefined,\n },\n });\n } else if (userId) {\n await update.mutateAsync({\n params: { path: { id: userId } },\n body: {\n ...base,\n email: base.email ?? null,\n phone: base.phone ?? null,\n roleIds: d.roleIds,\n },\n });\n }\n onSuccess?.();\n onClose();\n });\n\n const onDelete = async () => {\n if (!userId) {\n return;\n }\n await del.mutateAsync({ params: { path: { id: userId } } });\n onSuccess?.();\n onClose();\n };\n\n const onBanUnban = async () => {\n if (!userId) {\n return;\n }\n await ban.mutateAsync({\n params: { path: { id: userId } },\n body: {\n bannedUntil: isBanned ? null : '9999-12-31T23:59:59.999Z',\n },\n });\n onSuccess?.();\n };\n\n const toggleRole = (roleId: string, checked: boolean) => {\n const next = checked\n ? [...roleIds, roleId]\n : roleIds.filter((id) => id !== roleId);\n setValue('roleIds', next, { shouldDirty: true });\n };\n\n const isSubmitting = create.isPending || update.isPending;\n const isBanning = ban.isPending;\n\n return (\n <EntityDrawer\n title={mode === 'new' ? 'New user' : 'Edit user'}\n open={open}\n onClose={onClose}\n isDirty={formState.isDirty}\n size=\"lg\"\n form={\n userLoading && mode === 'edit' ? (\n <FormSkeleton />\n ) : (\n <Form {...form}>\n <form onSubmit={onSubmit} className=\"space-y-6\">\n <Stack>\n <FormField\n control={control}\n name=\"fullName\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n Full name <span className=\"text-destructive\">*</span>\n </FormLabel>\n <FormControl>\n <Input placeholder=\"Full name\" {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <FormField\n control={control}\n name=\"email\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>Email</FormLabel>\n <FormControl>\n <Input\n type=\"email\"\n placeholder=\"user@example.com\"\n {...field}\n value={field.value ?? ''}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <FormField\n control={control}\n name=\"phone\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>Phone</FormLabel>\n <FormControl>\n <Input\n placeholder=\"+251911223344\"\n {...field}\n value={field.value ?? ''}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <div className=\"space-y-4\">\n <FormLabel>Verification</FormLabel>\n <div className=\"flex flex-wrap gap-6 pt-1\">\n <FormField\n control={control}\n name=\"emailVerified\"\n render={({ field }) => (\n <FormItem className=\"flex flex-row items-center gap-2 space-y-0\">\n <FormControl>\n <Checkbox\n size=\"lg\"\n checked={field.value}\n disabled={!hasEmail}\n onCheckedChange={(c) =>\n field.onChange(c === true)\n }\n />\n </FormControl>\n <FormLabel className=\"cursor-pointer font-normal\">\n Email verified\n </FormLabel>\n <FormMessage />\n </FormItem>\n )}\n />\n <FormField\n control={control}\n name=\"phoneVerified\"\n render={({ field }) => (\n <FormItem className=\"flex flex-row items-center gap-2 space-y-0\">\n <FormControl>\n <Checkbox\n size=\"lg\"\n checked={field.value}\n disabled={!hasPhone}\n onCheckedChange={(c) =>\n field.onChange(c === true)\n }\n />\n </FormControl>\n <FormLabel className=\"cursor-pointer font-normal\">\n Phone verified\n </FormLabel>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n </div>\n </Stack>\n\n {mode === 'edit' && roles.length > 0 && (\n <div className=\"space-y-4\">\n <FormLabel>Roles</FormLabel>\n <div className=\"flex flex-col gap-3 pt-1\">\n {roles.map((role: Role) => {\n const desc = str(role.description);\n return (\n <div key={role.id} className=\"flex items-start gap-3\">\n <Checkbox\n size=\"lg\"\n id={`role-${role.id}`}\n checked={roleIds.includes(role.id)}\n onCheckedChange={(c) =>\n toggleRole(role.id, c === true)\n }\n className=\"mt-0.5\"\n />\n <label\n htmlFor={`role-${role.id}`}\n className=\"flex min-w-0 flex-1 cursor-pointer flex-col gap-0.5\"\n >\n <span className=\"text-sm font-medium\">\n {str(role.name) || role.code}\n </span>\n {desc ? (\n <span className=\"text-xs text-muted-foreground\">\n {desc}\n </span>\n ) : null}\n </label>\n </div>\n );\n })}\n </div>\n </div>\n )}\n </form>\n </Form>\n )\n }\n actions={\n <div className=\"flex items-center gap-2\">\n <EntityFormActions\n mode={mode}\n onSubmit={onSubmit}\n onReset={mode === 'new' ? () => reset(defaults) : undefined}\n onDelete={mode === 'edit' ? onDelete : undefined}\n isSubmitting={isSubmitting}\n isDeleting={del.isPending}\n disabled={userLoading && mode === 'edit'}\n itemName=\"user\"\n />\n {mode === 'edit' && userId && (\n <AlertDialog>\n <AlertDialogTrigger\n render={\n <Button\n variant=\"outline\"\n disabled={userLoading}\n loading={isBanning}\n className=\"cursor-pointer\"\n leftIcon={\n isBanned ? (\n <IconUserCheck className=\"size-4\" />\n ) : (\n <IconBan className=\"size-4\" />\n )\n }\n />\n }\n >\n {isBanned ? 'Unban' : 'Ban'}\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {isBanned ? 'Unban user?' : 'Ban user?'}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {isBanned\n ? 'This user will be able to sign in again.'\n : 'This user will not be able to sign in until unbanned.'}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={onBanUnban}\n variant={isBanned ? undefined : 'destructive'}\n >\n {isBanned ? 'Unban' : 'Ban'}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n )}\n </div>\n }\n />\n );\n}\n\nfunction FormSkeleton() {\n return (\n <div className=\"space-y-4\">\n {[1, 2, 3, 4, 5].map((i) => (\n <div key={i} className=\"space-y-2\">\n <Skeleton className=\"h-4 w-20\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n ))}\n </div>\n );\n}\n"],"mappings":"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","names":["Button","jsx","jsxs","Button"]}
|
package/dist/chunk-V2W3WPCZ.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
// src/utils/normalize-phone.ts
|
|
2
|
-
function normalizePhone(phone) {
|
|
3
|
-
const cleaned = phone.trim().replace(/\s/g, "");
|
|
4
|
-
if (cleaned.startsWith("+2519") || cleaned.startsWith("+2517")) {
|
|
5
|
-
return cleaned;
|
|
6
|
-
}
|
|
7
|
-
if (cleaned.startsWith("2519") || cleaned.startsWith("2517")) {
|
|
8
|
-
return `+${cleaned}`;
|
|
9
|
-
}
|
|
10
|
-
if (cleaned.startsWith("09") || cleaned.startsWith("07")) {
|
|
11
|
-
return `+251${cleaned.slice(1)}`;
|
|
12
|
-
}
|
|
13
|
-
if ((cleaned.startsWith("9") || cleaned.startsWith("7")) && cleaned.length === 9) {
|
|
14
|
-
return `+251${cleaned}`;
|
|
15
|
-
}
|
|
16
|
-
return cleaned;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export {
|
|
20
|
-
normalizePhone
|
|
21
|
-
};
|
|
22
|
-
//# sourceMappingURL=chunk-V2W3WPCZ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/normalize-phone.ts"],"sourcesContent":["export function normalizePhone(phone: string): string {\n const cleaned = phone.trim().replace(/\\s/g, '');\n if (cleaned.startsWith('+2519') || cleaned.startsWith('+2517')) {\n return cleaned;\n }\n if (cleaned.startsWith('2519') || cleaned.startsWith('2517')) {\n return `+${cleaned}`;\n }\n if (cleaned.startsWith('09') || cleaned.startsWith('07')) {\n return `+251${cleaned.slice(1)}`;\n }\n if (\n (cleaned.startsWith('9') || cleaned.startsWith('7')) &&\n cleaned.length === 9\n ) {\n return `+251${cleaned}`;\n }\n return cleaned;\n}\n"],"mappings":";AAAO,SAAS,eAAe,OAAuB;AACpD,QAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,OAAO,EAAE;AAC9C,MAAI,QAAQ,WAAW,OAAO,KAAK,QAAQ,WAAW,OAAO,GAAG;AAC9D,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,WAAW,MAAM,KAAK,QAAQ,WAAW,MAAM,GAAG;AAC5D,WAAO,IAAI,OAAO;AAAA,EACpB;AACA,MAAI,QAAQ,WAAW,IAAI,KAAK,QAAQ,WAAW,IAAI,GAAG;AACxD,WAAO,OAAO,QAAQ,MAAM,CAAC,CAAC;AAAA,EAChC;AACA,OACG,QAAQ,WAAW,GAAG,KAAK,QAAQ,WAAW,GAAG,MAClD,QAAQ,WAAW,GACnB;AACA,WAAO,OAAO,OAAO;AAAA,EACvB;AACA,SAAO;AACT;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/auth/forgot-password.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n Alert,\n AlertDescription,\n AlertTitle,\n Button,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n} from '@mesob/ui/components';\nimport { useMesob } from '@mesob/ui/providers';\nimport { IconAlertCircle } from '@tabler/icons-react';\nimport { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useTranslator } from '../../hooks/use-translator';\nimport { useApi, useConfig } from '../../provider';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport { handleError } from '../../utils/handle-error';\nimport { AuthLayout } from './auth-layout';\n\ntype ForgotPasswordFormValues = {\n account: string;\n};\n\nconst forgotPasswordSchema = (t: (key: string) => string) =>\n z.object({\n account: z.string().min(1, t('errors.accountRequired')),\n });\n\nexport const ForgotPassword = () => {\n const { hooks } = useApi();\n const { config } = useConfig();\n const mesob = useMesob();\n const t = useTranslator('Auth.forgotPassword');\n const Link = mesob?.navigation?.Link;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthErrorContent | null>(null);\n\n const forgotPasswordMutation = hooks.useMutation('post', '/password/forgot');\n\n const signInLink = config.navigation?.links?.signIn || '/auth/sign-in';\n const onNavigate =\n config.navigation?.onNavigate ||\n ((path: string) => {\n if (typeof window !== 'undefined') {\n window.location.href = path;\n }\n });\n const logoImage = config.ui.logoImage;\n\n const form = useForm<ForgotPasswordFormValues>({\n resolver: zodResolver(forgotPasswordSchema(t)),\n defaultValues: {\n account: '',\n },\n });\n\n useEffect(() => {\n if (error) {\n toast.error(error.title || 'Error', {\n description: error.description,\n });\n }\n }, [error]);\n\n const handleSubmit = form.handleSubmit(async (values) => {\n setIsLoading(true);\n setError(null);\n\n try {\n const res = await forgotPasswordMutation.mutateAsync({\n body: {\n identifier: values.account,\n },\n });\n\n if ('verificationId' in res && res.verificationId) {\n onNavigate(`/auth/reset-password?verificationId=${res.verificationId}`);\n } else {\n onNavigate(\n `/auth/reset-password?identifier=${encodeURIComponent(values.account)}`,\n );\n }\n } catch (err) {\n handleError(err, setError, t);\n } finally {\n setIsLoading(false);\n }\n });\n\n let errorContent: AuthErrorContent | null = null;\n if (error) {\n if (typeof error === 'string') {\n errorContent = { title: 'Error', description: error };\n } else {\n errorContent = error;\n }\n }\n\n return (\n <AuthLayout\n title={config.ui.name}\n description={t('description')}\n logoImage={logoImage}\n footer={\n Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {t('footer.backToSignIn')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {t('footer.backToSignIn')}\n </a>\n )\n }\n >\n <Form {...form}>\n <form\n id=\"forgot-password-form\"\n onSubmit={handleSubmit}\n className=\"space-y-4\"\n >\n <FormField\n control={form.control}\n name=\"account\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.accountLabel')}</FormLabel>\n <FormControl>\n <Input {...field} type=\"text\" />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <Button\n type=\"submit\"\n form=\"forgot-password-form\"\n className=\"w-full\"\n disabled={isLoading || forgotPasswordMutation.isPending}\n loading={isLoading || forgotPasswordMutation.isPending}\n >\n {isLoading || forgotPasswordMutation.isPending\n ? t('form.submitting')\n : t('form.submit')}\n </Button>\n </form>\n </Form>\n {errorContent && (\n <Alert variant=\"destructive\" className=\"mt-4\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>{errorContent.title}</AlertTitle>\n <AlertDescription>{errorContent.description}</AlertDescription>\n </Alert>\n )}\n </AuthLayout>\n );\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/iam/role-detail-page.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n EntityFormActions,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n LocaleInputText,\n LocaleInputTextarea,\n Section,\n Skeleton,\n} from '@mesob/ui/components';\nimport { useLocaleSchemas } from '@mesob/ui/providers';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useEffect, useMemo } from 'react';\nimport type { Resolver } from 'react-hook-form';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useApi, useConfig } from '../../provider';\nimport { IAMGuard } from './iam-guard';\n\ntype RoleFormData = {\n name: Record<string, string>;\n code: string;\n description: Record<string, string>;\n};\n\ntype RoleDetailPageProps = {\n roleId: string;\n basePath?: string;\n};\n\nexport function RoleDetailPage({\n roleId,\n basePath = '/iam/roles',\n}: RoleDetailPageProps) {\n return (\n <IAMGuard>\n <RoleDetailPageContent roleId={roleId} basePath={basePath} />\n </IAMGuard>\n );\n}\n\nfunction RoleDetailPageContent({\n roleId,\n basePath = '/iam/roles',\n}: RoleDetailPageProps) {\n const { hooks } = useApi();\n const { config } = useConfig();\n const qc = useQueryClient();\n const { localeInputDefault, requiredSchema, optionalSchema } =\n useLocaleSchemas();\n const schema = useMemo(\n () =>\n z.object({\n name: requiredSchema,\n code: z.string().min(1, 'Code is required'),\n description: optionalSchema,\n }),\n [requiredSchema, optionalSchema],\n );\n const defaults: RoleFormData = useMemo(\n () => ({\n name: { ...localeInputDefault },\n code: '',\n description: { ...localeInputDefault },\n }),\n [localeInputDefault],\n );\n\n const { data, isLoading } = hooks.useQuery(\n 'get',\n '/roles/{id}',\n { params: { path: { id: roleId } } },\n { enabled: !!roleId },\n );\n\n const update = hooks.useMutation('put', '/roles/{id}', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/roles'] });\n qc.invalidateQueries({ queryKey: ['get', '/roles/{id}'] });\n toast.success('Role updated');\n },\n onError: () => {\n toast.error('Failed to update role');\n },\n });\n const remove = hooks.useMutation('delete', '/roles/{id}', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/roles'] });\n toast.success('Role deleted');\n config.navigation?.onNavigate?.(basePath);\n },\n onError: () => {\n toast.error('Failed to delete role');\n },\n });\n\n const form = useForm<RoleFormData>({\n resolver: zodResolver(schema) as Resolver<RoleFormData>,\n defaultValues: defaults,\n });\n\n const { reset, formState, control, register } = form;\n\n useEffect(() => {\n if (!data?.role) {\n return;\n }\n const r = data.role;\n reset({\n name: (r.name ?? {}) as RoleFormData['name'],\n code: r.code,\n description: (r.description ?? {}) as RoleFormData['description'],\n });\n }, [data?.role, reset]);\n\n if (!roleId) {\n return null;\n }\n\n const role = data?.role;\n const editable = role?.isEditable !== false;\n const deletable = role?.isDeletable !== false;\n const onSubmit = form.handleSubmit(async (d) => {\n await update.mutateAsync({\n params: { path: { id: roleId } },\n body: {\n name: d.name,\n code: d.code,\n description: d.description ?? undefined,\n },\n });\n });\n\n const footer = role ? (\n <EntityFormActions\n mode=\"edit\"\n onSubmit={onSubmit}\n onDelete={\n deletable\n ? () =>\n remove.mutate({\n params: { path: { id: roleId } },\n })\n : undefined\n }\n isSubmitting={update.isPending}\n isDeleting={remove.isPending}\n disabled={!editable}\n itemName=\"role\"\n />\n ) : null;\n\n return (\n <Section title=\"Role details\" footer={footer} defaultOpen>\n {isLoading || !role ? (\n <RoleDetailSkeleton />\n ) : (\n <Form {...form}>\n <form onSubmit={onSubmit} className=\"space-y-4\">\n <LocaleInputText\n label=\"Name\"\n field=\"name\"\n required\n register={register}\n errors={formState.errors}\n placeholder=\"e.g. Administrator\"\n disabled={!editable}\n />\n <FormField\n control={control}\n name=\"code\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n Code <span className=\"text-destructive\">*</span>\n </FormLabel>\n <FormControl>\n <Input\n placeholder=\"e.g. admin\"\n disabled={!editable}\n {...field}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <LocaleInputTextarea\n label=\"Description\"\n field=\"description\"\n register={register}\n errors={formState.errors}\n placeholder=\"Description\"\n rows={3}\n disabled={!editable}\n />\n </form>\n </Form>\n )}\n </Section>\n );\n}\n\nfunction RoleDetailSkeleton() {\n return (\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-16\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-14\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-20 w-full\" />\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|