fix: api call and change the props of components
This commit is contained in:
23
src/App.tsx
23
src/App.tsx
@@ -21,29 +21,6 @@ function App() {
|
||||
<LanguageManager />
|
||||
<UserCompletionForm />
|
||||
<ThemeToggleButton />
|
||||
{/* <div style={{ padding: '16px' }}>
|
||||
<Typography variant="h3">{t('helloWorld')}</Typography>
|
||||
<Box
|
||||
sx={{ display: 'flex', flexDirection: 'column', gap: '10px', mt: 5 }}
|
||||
>
|
||||
<Button color="secondary" variant="contained">
|
||||
secondary button
|
||||
</Button>
|
||||
<TextField label={t('helloWorld')} />
|
||||
<Alert severity="success" variant="filled">
|
||||
success
|
||||
</Alert>
|
||||
<Alert severity="warning" variant="filled">
|
||||
warning
|
||||
</Alert>
|
||||
<Alert severity="info" variant="filled">
|
||||
info
|
||||
</Alert>
|
||||
<Alert severity="error" variant="filled">
|
||||
error
|
||||
</Alert>
|
||||
</Box>
|
||||
</div> */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<Date | null>(null);
|
||||
// const [birthDate, setBirthDate] = useState<Date | null>(null);
|
||||
|
||||
const Adapter = useMemo(() => {
|
||||
return isFarsi ? AdapterDateFnsJalali : AdapterDateFns;
|
||||
@@ -18,8 +22,8 @@ export function DateOfBirth() {
|
||||
<LocalizationProvider dateAdapter={Adapter}>
|
||||
<DatePicker
|
||||
label={t('completion.dateOfBirth')}
|
||||
value={birthDate}
|
||||
onChange={(newValue) => setBirthDate(newValue)}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
slotProps={{
|
||||
textField: {
|
||||
fullWidth: true,
|
||||
|
||||
@@ -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<SetStateAction<'female' | 'male'>>;
|
||||
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}
|
||||
/>
|
||||
<TextField
|
||||
label={t('completion.familyName')}
|
||||
placeholder={t('completion.familyName')}
|
||||
variant="outlined"
|
||||
value={lastName}
|
||||
onChange={(e) => setLastName(e.target.value)}
|
||||
sx={fieldSx}
|
||||
/>
|
||||
</Box>
|
||||
@@ -127,6 +147,8 @@ export function PersonalInfoFields({
|
||||
<TextField
|
||||
label={t('completion.optionalNationalCode')}
|
||||
placeholder={t('completion.optionalNationalCode')}
|
||||
value={nationalId}
|
||||
onChange={(e) => setNationalId(e.target.value)}
|
||||
variant="outlined"
|
||||
sx={fieldSx}
|
||||
/>
|
||||
@@ -181,7 +203,7 @@ export function PersonalInfoFields({
|
||||
/>
|
||||
|
||||
<Box sx={fieldSx}>
|
||||
<DateOfBirth />
|
||||
<DateOfBirth value={birthDate} onChange={setBirthDate} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
@@ -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')}
|
||||
</Typography>
|
||||
|
||||
<Button
|
||||
{/* <Button
|
||||
variant="contained"
|
||||
sx={{
|
||||
width: { xs: '100%', sm: '247px' },
|
||||
@@ -80,12 +82,20 @@ export function SubmitSection() {
|
||||
}}
|
||||
>
|
||||
{t('completion.registerButton')}
|
||||
</Button> */}
|
||||
<Button variant="contained" onClick={onSubmit} disabled={loading}>
|
||||
{loading
|
||||
? t('completion.submitting')
|
||||
: success
|
||||
? t('completion.success')
|
||||
: t('completion.registerButton')}
|
||||
</Button>
|
||||
{error && <Typography color="error">{error}</Typography>}
|
||||
</Box>
|
||||
|
||||
<Dialog
|
||||
open={openDialog}
|
||||
onClose={handleCloseDialog}
|
||||
onClose={() => setOpenDialog(false)}
|
||||
fullWidth
|
||||
maxWidth="md"
|
||||
dir={i18n.language.startsWith('fa') ? 'rtl' : 'ltr'}
|
||||
|
||||
@@ -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<Date | null>(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<string | null>(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 (
|
||||
<Box
|
||||
@@ -140,14 +190,20 @@ export function UserCompletionForm() {
|
||||
{t('completion.description')}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<PersonalInfoFields
|
||||
firstName={firstName}
|
||||
setFirstName={setFirstName}
|
||||
lastName={lastName}
|
||||
setLastName={setLastName}
|
||||
nationalId={nationalId}
|
||||
setNationalId={setNationalId}
|
||||
birthDate={birthDate}
|
||||
setBirthDate={setBirthDate}
|
||||
sex={sex}
|
||||
setSex={setSex}
|
||||
country={country}
|
||||
setCountry={setCountry}
|
||||
/>
|
||||
|
||||
<PasswordSection
|
||||
showPasswordSection={showPasswordSection}
|
||||
setShowPasswordSection={setShowPasswordSection}
|
||||
@@ -163,7 +219,6 @@ export function UserCompletionForm() {
|
||||
validPassword={validPassword}
|
||||
showValidations={showPasswordValidations}
|
||||
/>
|
||||
|
||||
<EmailSection
|
||||
showEmail={showEmail}
|
||||
setShowEmail={setShowEmail}
|
||||
@@ -181,8 +236,12 @@ export function UserCompletionForm() {
|
||||
isVerifyingCode={isVerifyingCode}
|
||||
handleEditEmail={handleEditEmail}
|
||||
/>
|
||||
|
||||
<SubmitSection />
|
||||
<SubmitSection
|
||||
onSubmit={handleSubmit}
|
||||
loading={loading}
|
||||
error={error}
|
||||
success={success}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user