feat: add api to connect user completion form to backend

This commit is contained in:
Koosha Lahouti
2025-08-05 18:59:54 -07:00
parent 0f9ef06742
commit 3e23fae993
3 changed files with 66 additions and 37 deletions

View File

@@ -1,4 +1,4 @@
import { useState, useMemo } from 'react';
import { useMemo } from 'react';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
@@ -12,7 +12,6 @@ interface DateOfBirthProps {
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 Adapter = useMemo(() => {
return isFarsi ? AdapterDateFnsJalali : AdapterDateFns;

View File

@@ -1,15 +1,17 @@
import React, { useEffect, useState } from 'react';
import { Box, Typography } from '@mui/material';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import Logo from '@/components/Logo';
import { PersonalInfoFields } from './PersonalInfoFields';
import { PasswordSection } from './PasswordSection';
import { EmailSection } from './EmailSection';
import { SubmitSection } from './SubmitSection';
import Logo from '@/components/Logo';
import apiClient from '@/lib/apiClient';
import { loginWithPassword } from '@/lib/authToken';
export function UserCompletionForm() {
const { t } = useTranslation('completionForm');
const USERNAME = '+989353989651';
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
@@ -61,11 +63,9 @@ export function UserCompletionForm() {
}, [password, validPassword]);
useEffect(() => {
let timer: ReturnType<typeof setInterval>;
let timer: NodeJS.Timeout;
if (buttonState === 'counting' && countdown > 0) {
timer = setInterval(() => {
setCountdown((prev) => prev - 1);
}, 1000);
timer = setInterval(() => setCountdown((prev) => prev - 1), 1000);
}
if (countdown === 0) {
setButtonState('default');
@@ -74,7 +74,7 @@ export function UserCompletionForm() {
}, [buttonState, countdown]);
const toPersianDigits = (str: string) =>
str.replace(/\d/g, (d: string) => '۰۱۲۳۴۵۶۷۸۹'[parseInt(d)]);
str.replace(/\d/g, (d) => '۰۱۲۳۴۵۶۷۸۹'[parseInt(d, 10)]);
const getButtonLabel = () => {
if (buttonState === 'sent') return t('completion.sent');
@@ -108,40 +108,39 @@ export function UserCompletionForm() {
setCodeSent(false);
setEmailVerified(false);
};
const STATICTOKEN = 'Bearer abcdef1234567890';
const handleSubmit = async () => {
setLoading(true);
setError(null);
setSuccess(false);
try {
await loginWithPassword(USERNAME, password);
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 } },
);
}>('/User/CompleteUserInformation', {
firstName,
lastName,
gender: sex === 'female' ? 2 : 1,
nationalId,
savePassword: showPasswordSection,
password: showPasswordSection ? password : undefined,
saveEmail: showEmail,
email: showEmail ? email : undefined,
birthDate,
});
if (data.success) {
setSuccess(true);
} else {
setError(data.message || 'Validation error');
}
} catch (err) {
setError((err as Error).message || 'An error occurred');
} catch (err: any) {
setError(err.message || 'An error occurred');
} finally {
setLoading(false);
}
@@ -152,8 +151,8 @@ export function UserCompletionForm() {
sx={{
backgroundColor: 'background.default',
minHeight: '100vh',
flexDirection: 'column',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
p: { xs: 1, sm: 2, md: 3 },
@@ -165,7 +164,7 @@ export function UserCompletionForm() {
<Box
sx={{
width: '100%',
maxWidth: '730px',
maxWidth: 730,
backgroundColor: 'background.paper',
border: '1px solid #ccc',
display: 'flex',
@@ -175,14 +174,7 @@ export function UserCompletionForm() {
py: { xs: 3, sm: 4 },
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'column',
width: '100%',
gap: 1,
}}
>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography variant="h5" color="text.primary">
{t('completion.title')}
</Typography>
@@ -190,6 +182,7 @@ export function UserCompletionForm() {
{t('completion.description')}
</Typography>
</Box>
<PersonalInfoFields
firstName={firstName}
setFirstName={setFirstName}
@@ -204,6 +197,7 @@ export function UserCompletionForm() {
country={country}
setCountry={setCountry}
/>
<PasswordSection
showPasswordSection={showPasswordSection}
setShowPasswordSection={setShowPasswordSection}
@@ -219,6 +213,7 @@ export function UserCompletionForm() {
validPassword={validPassword}
showValidations={showPasswordValidations}
/>
<EmailSection
showEmail={showEmail}
setShowEmail={setShowEmail}
@@ -236,6 +231,7 @@ export function UserCompletionForm() {
isVerifyingCode={isVerifyingCode}
handleEditEmail={handleEditEmail}
/>
<SubmitSection
onSubmit={handleSubmit}
loading={loading}

34
src/lib/authToken.ts Normal file
View File

@@ -0,0 +1,34 @@
// src/lib/authService.ts
import axios from 'axios';
export interface TokenResponse {
access_token: string;
expires_in: number;
refresh_token: string;
}
const authClient = axios.create({
baseURL: 'https://account.business-harmony.com',
timeout: 10000,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
});
export async function loginWithPassword(
username: string,
password: string,
): Promise<TokenResponse> {
const body = new URLSearchParams();
body.set('grant_type', 'password');
body.set('username', username);
body.set('password', password);
body.set('client_id', 'harmony_identity');
body.set('scope', 'openid harmony_identity profile offline_access');
const { data } = await authClient.post<TokenResponse>(
'/connect/token',
body.toString(),
);
localStorage.setItem('authToken', data.access_token);
return data;
}