From 0f9ef067424e54d715ef3705640967dcbb190895 Mon Sep 17 00:00:00 2001 From: Koosha Lahouti Date: Tue, 5 Aug 2025 14:03:09 -0700 Subject: [PATCH] fix: api call and change the props of components --- src/App.tsx | 23 ------ .../authentication/components/DateOfBirth.tsx | 12 ++- .../components/PersonalInfoFields.tsx | 32 ++++++-- .../components/SubmitSection.tsx | 24 ++++-- .../components/UserCompletionForm.tsx | 73 +++++++++++++++++-- src/lib/apiClient.ts | 2 +- 6 files changed, 119 insertions(+), 47 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 7275da5..dcbf270 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -21,29 +21,6 @@ function App() { - {/*
- {t('helloWorld')} - - - - - success - - - warning - - - info - - - error - - -
*/} ); } diff --git a/src/features/authentication/components/DateOfBirth.tsx b/src/features/authentication/components/DateOfBirth.tsx index 11e0b64..c0bcf42 100644 --- a/src/features/authentication/components/DateOfBirth.tsx +++ b/src/features/authentication/components/DateOfBirth.tsx @@ -5,10 +5,14 @@ import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; import { AdapterDateFnsJalali } from '@mui/x-date-pickers/AdapterDateFnsJalali'; import { useTranslation } from 'react-i18next'; -export function DateOfBirth() { +interface DateOfBirthProps { + value: Date | null; + onChange: (date: Date | null) => void; +} +export function DateOfBirth({ value, onChange }: DateOfBirthProps) { const { t, i18n } = useTranslation('completionForm'); const isFarsi = i18n.language === 'fa' || i18n.language === 'fa-IR'; - const [birthDate, setBirthDate] = useState(null); + // const [birthDate, setBirthDate] = useState(null); const Adapter = useMemo(() => { return isFarsi ? AdapterDateFnsJalali : AdapterDateFns; @@ -18,8 +22,8 @@ export function DateOfBirth() { setBirthDate(newValue)} + value={value} + onChange={onChange} slotProps={{ textField: { fullWidth: true, diff --git a/src/features/authentication/components/PersonalInfoFields.tsx b/src/features/authentication/components/PersonalInfoFields.tsx index ecf7508..7ee8a46 100644 --- a/src/features/authentication/components/PersonalInfoFields.tsx +++ b/src/features/authentication/components/PersonalInfoFields.tsx @@ -9,18 +9,34 @@ import { } from '@mui/material'; import { useTranslation } from 'react-i18next'; import { Woman, Man } from 'iconsax-react'; -import { useState } from 'react'; +import { useState, type Dispatch, type SetStateAction } from 'react'; import { DateOfBirth } from './DateOfBirth'; import { countries } from '../data/Countries'; interface PersonalInfoFieldsProps { - sex: string; - setSex: (sex: string) => void; + firstName: string; + setFirstName: (v: string) => void; + lastName: string; + setLastName: (v: string) => void; + sex: 'male' | 'female'; + setSex: Dispatch>; country: string; setCountry: (country: string) => void; + nationalId: string; + setNationalId: (v: string) => void; + birthDate: Date | null; + setBirthDate: (d: Date | null) => void; } export function PersonalInfoFields({ + firstName, + setFirstName, + lastName, + setLastName, + nationalId, + setNationalId, + birthDate, + setBirthDate, sex, setSex, country, @@ -30,7 +46,7 @@ export function PersonalInfoFields({ const [countryError, setCountryError] = useState(false); const handleChangeSex = (e: any) => { - setSex(e.target.value); + setSex(e.target.value as 'female' | 'male'); }; const handleChangeCountry = (_: any, newValue: any) => { @@ -81,12 +97,16 @@ export function PersonalInfoFields({ label={t('completion.name')} placeholder={t('completion.name')} variant="outlined" + value={firstName} + onChange={(e) => setFirstName(e.target.value)} sx={fieldSx} /> setLastName(e.target.value)} sx={fieldSx} /> @@ -127,6 +147,8 @@ export function PersonalInfoFields({ setNationalId(e.target.value)} variant="outlined" sx={fieldSx} /> @@ -181,7 +203,7 @@ export function PersonalInfoFields({ /> - + diff --git a/src/features/authentication/components/SubmitSection.tsx b/src/features/authentication/components/SubmitSection.tsx index 8cbba50..7239e20 100644 --- a/src/features/authentication/components/SubmitSection.tsx +++ b/src/features/authentication/components/SubmitSection.tsx @@ -7,11 +7,15 @@ import { Dialog, DialogTitle, DialogContent, - DialogActions, } from '@mui/material'; import { useTranslation } from 'react-i18next'; - -export function SubmitSection() { +interface Props { + onSubmit: () => void; + loading: boolean; + error: string | null; + success: boolean; +} +export function SubmitSection({ onSubmit, loading, error, success }: Props) { const { t, i18n } = useTranslation('completionForm'); const [openDialog, setOpenDialog] = useState(false); @@ -20,8 +24,6 @@ export function SubmitSection() { setOpenDialog(true); }; - const handleCloseDialog = () => setOpenDialog(false); - const agreementText = `۱. محرمانگی اطلاعات
 هارمونی متعهد می‌شود تحت هیچ شرایطی اطلاعات هویتی کاربران نظیر شماره تلفن، ایمیل، رمز عبور، شناسه کاربری و هرگونه داده مرتبط را در اختیار اشخاص ثالث قرار ندهد. اطلاعات کاربران صرفاً در چارچوب ارائه خدمات احراز هویت مورد استفاده قرار گرفته و حتی پس از غیرفعال‌سازی حساب یا قطع همکاری، این اطلاعات محرمانه باقی خواهد ماند. هارمونی موظف به پیاده‌سازی تدابیر امنیتی لازم برای جلوگیری از هرگونه دسترسی غیرمجاز می‌باشد. ۲. مسئولیت حفظ اطلاعات ورود
 کاربر موظف است از حساب کاربری خود محافظت کند و رمز عبوری ایمن و غیرقابل حدس انتخاب نماید. تغییر دوره‌ای رمز عبور و اقدام فوری در صورت احساس خطر دسترسی غیرمجاز الزامی است. مسئولیت هرگونه سوءاستفاده از حساب کاربری به دلیل بی‌احتیاطی کاربر، بر عهده خود وی خواهد بود. ۳. رخنه‌های امنیتی و حملات سایبری
 هارمونی در برابر رخنه‌های امنیتی ناشی از حملات سایبری که خارج از کنترل سیستم است، مسئولیتی ندارد. با این حال، هارمونی از به‌روزترین استانداردهای امنیتی و رمزنگاری برای جلوگیری از چنین حوادثی بهره می‌برد. @@ -72,7 +74,7 @@ export function SubmitSection() { {t('completion.agreementPart2')} - */} + + {error && {error}} setOpenDialog(false)} fullWidth maxWidth="md" dir={i18n.language.startsWith('fa') ? 'rtl' : 'ltr'} diff --git a/src/features/authentication/components/UserCompletionForm.tsx b/src/features/authentication/components/UserCompletionForm.tsx index ce7ec85..d35ba09 100644 --- a/src/features/authentication/components/UserCompletionForm.tsx +++ b/src/features/authentication/components/UserCompletionForm.tsx @@ -6,14 +6,22 @@ import { PasswordSection } from './PasswordSection'; import { EmailSection } from './EmailSection'; import { SubmitSection } from './SubmitSection'; import Logo from '@/components/Logo'; +import apiClient from '@/lib/apiClient'; export function UserCompletionForm() { const { t } = useTranslation('completionForm'); - const [sex, setSex] = useState(''); + + const [firstName, setFirstName] = useState(''); + const [lastName, setLastName] = useState(''); + const [nationalId, setNationalId] = useState(''); + const [birthDate, setBirthDate] = useState(null); + const [sex, setSex] = useState<'female' | 'male'>('female'); const [country, setCountry] = useState(''); + const [showPasswordSection, setShowPasswordSection] = useState(false); const [password, setPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); + const [showEmail, setShowEmail] = useState(false); const [email, setEmail] = useState(''); const [codeSent, setCodeSent] = useState(false); @@ -24,6 +32,7 @@ export function UserCompletionForm() { const [countdown, setCountdown] = useState(60); const [emailVerified, setEmailVerified] = useState(false); const [isVerifyingCode, setIsVerifyingCode] = useState(false); + const correctEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); const matchPassword = password === confirmPassword; const hasNumber = /\d/.test(password); @@ -33,7 +42,10 @@ export function UserCompletionForm() { const validPassword = hasNumber && hasMinLength && hasUpperAndLower && hasSpecialChar; const [showPasswordValidations, setShowPasswordValidations] = useState(false); - const correctEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); + + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [success, setSuccess] = useState(false); useEffect(() => { if (password) { @@ -96,6 +108,44 @@ export function UserCompletionForm() { setCodeSent(false); setEmailVerified(false); }; + const STATICTOKEN = 'Bearer abcdef1234567890'; + + const handleSubmit = async () => { + setLoading(true); + setError(null); + setSuccess(false); + try { + const { data } = await apiClient.post<{ + success: boolean; + errorCode: number; + message: string; + validations: { property: string; message: string }[]; + }>( + '/User/CompleteUserInformation', + { + firstName, + lastName, + gender: sex === 'female' ? 2 : 1, + nationalId, + savePassword: showPasswordSection, + password: showPasswordSection ? password : undefined, + saveEmail: showEmail, + email: showEmail ? email : undefined, + birthDate, + }, + { headers: { Authorization: STATICTOKEN } }, + ); + if (data.success) { + setSuccess(true); + } else { + setError(data.message || 'Validation error'); + } + } catch (err) { + setError((err as Error).message || 'An error occurred'); + } finally { + setLoading(false); + } + }; return ( - - - - - + ); diff --git a/src/lib/apiClient.ts b/src/lib/apiClient.ts index 9bf0793..e8ce77a 100644 --- a/src/lib/apiClient.ts +++ b/src/lib/apiClient.ts @@ -5,7 +5,7 @@ const getToken = () => localStorage.getItem('authToken'); const apiClient = axios.create({ // Define the base URL for all API requests - baseURL: 'https://api.yourapp.com/v1', + baseURL: 'https://account.business-harmony.com/api/', // Set a timeout for requests (e.g., 10 seconds) timeout: 10000,