manual improvement 2 & add telegram bot
This commit is contained in:
@@ -1,13 +1,19 @@
|
||||
'use client';
|
||||
import { useState } from 'react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { useSnackbar } from 'notistack';
|
||||
import { Box, Stack, TextField, Typography } from '@mui/material';
|
||||
import { AppButton, AppLoading, BankStatusPanel, EmptyState, ErrorState } from '@/components';
|
||||
import { Box, Stack, Typography } from '@mui/material';
|
||||
import { AppButton, AppLoading, BankStatusPanel, EmptyState, ErrorState, RhfTextField } from '@/components';
|
||||
import { useNurseBankAccounts, useAddNurseBankAccount, useSetPrimaryBankAccount } from '@/services/nurse';
|
||||
import { isValidSheba } from '@/services/nurse/iban';
|
||||
import { deriveBankStatus } from '@/services/nurse/types';
|
||||
|
||||
interface BankFormValues {
|
||||
iban: string;
|
||||
holder: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nurse payout bank settings — an **accounts section**, not a one-shot form (ui-phase-8 §3.7): submit
|
||||
* an IBAN (شبا) + account-holder name, then watch the ownership inquiry resolve through its three
|
||||
@@ -26,28 +32,19 @@ export default function NurseBankPage() {
|
||||
const addAccount = useAddNurseBankAccount();
|
||||
const setPrimary = useSetPrimaryBankAccount();
|
||||
|
||||
const [iban, setIban] = useState('');
|
||||
const [holder, setHolder] = useState('');
|
||||
const [ibanError, setIbanError] = useState(false);
|
||||
const [holderError, setHolderError] = useState(false);
|
||||
const [showForm, setShowForm] = useState(false);
|
||||
const form = useForm<BankFormValues>({ mode: 'onTouched', defaultValues: { iban: '', holder: '' } });
|
||||
const { handleSubmit, reset } = form;
|
||||
|
||||
const accounts = data ?? [];
|
||||
const showFormNow = !isLoading && !isError && (accounts.length === 0 || showForm);
|
||||
|
||||
const submit = () => {
|
||||
const ibanInvalid = !isValidSheba(iban);
|
||||
const holderInvalid = holder.trim().length === 0;
|
||||
setIbanError(ibanInvalid);
|
||||
setHolderError(holderInvalid);
|
||||
if (ibanInvalid || holderInvalid) return;
|
||||
|
||||
const submit = (values: BankFormValues) => {
|
||||
addAccount.mutate(
|
||||
{ iban, accountHolderName: holder.trim() },
|
||||
{ iban: values.iban, accountHolderName: values.holder.trim() },
|
||||
{
|
||||
onSuccess: () => {
|
||||
setIban('');
|
||||
setHolder('');
|
||||
reset();
|
||||
setShowForm(false);
|
||||
enqueueSnackbar(t('added'), { variant: 'success' });
|
||||
},
|
||||
@@ -131,51 +128,43 @@ export default function NurseBankPage() {
|
||||
) : null}
|
||||
|
||||
{showFormNow ? (
|
||||
<Stack sx={{ gap: 2 }}>
|
||||
<TextField
|
||||
label={t('iban_label')}
|
||||
value={iban}
|
||||
onChange={(e) => {
|
||||
setIban(e.target.value.toUpperCase());
|
||||
if (ibanError) setIbanError(false);
|
||||
}}
|
||||
error={ibanError}
|
||||
helperText={ibanError ? t('iban_invalid') : t('iban_hint')}
|
||||
slotProps={{ htmlInput: { dir: 'ltr', style: { textAlign: 'start', letterSpacing: 1 } } }}
|
||||
fullWidth
|
||||
/>
|
||||
<TextField
|
||||
label={t('holder_label')}
|
||||
value={holder}
|
||||
onChange={(e) => {
|
||||
setHolder(e.target.value);
|
||||
if (holderError) setHolderError(false);
|
||||
}}
|
||||
error={holderError}
|
||||
helperText={holderError ? t('holder_required') : t('holder_hint')}
|
||||
fullWidth
|
||||
/>
|
||||
<Stack direction="row" sx={{ gap: 1 }}>
|
||||
<AppButton color="primary" variant="contained" startIcon="bank" onClick={submit} disabled={addAccount.isPending}>
|
||||
{addAccount.isPending ? t('submitting') : t('submit')}
|
||||
</AppButton>
|
||||
{accounts.length > 0 ? (
|
||||
<AppButton
|
||||
variant="text"
|
||||
onClick={() => {
|
||||
setShowForm(false);
|
||||
setIban('');
|
||||
setHolder('');
|
||||
setIbanError(false);
|
||||
setHolderError(false);
|
||||
}}
|
||||
disabled={addAccount.isPending}
|
||||
>
|
||||
{tc('cancel')}
|
||||
<FormProvider {...form}>
|
||||
<Stack component="form" noValidate onSubmit={handleSubmit(submit)} sx={{ gap: 2 }}>
|
||||
<RhfTextField<BankFormValues>
|
||||
name="iban"
|
||||
label={t('iban_label')}
|
||||
helperText={t('iban_hint')}
|
||||
transform={(raw) => raw.toUpperCase()}
|
||||
rules={{ validate: (value) => isValidSheba(String(value ?? '')) || t('iban_invalid') }}
|
||||
slotProps={{ htmlInput: { dir: 'ltr', style: { textAlign: 'start', letterSpacing: 1 } } }}
|
||||
fullWidth
|
||||
/>
|
||||
<RhfTextField<BankFormValues>
|
||||
name="holder"
|
||||
label={t('holder_label')}
|
||||
helperText={t('holder_hint')}
|
||||
rules={{ validate: (value) => String(value ?? '').trim().length > 0 || t('holder_required') }}
|
||||
fullWidth
|
||||
/>
|
||||
<Stack direction="row" sx={{ gap: 1 }}>
|
||||
<AppButton type="submit" color="primary" variant="contained" startIcon="bank" disabled={addAccount.isPending}>
|
||||
{addAccount.isPending ? t('submitting') : t('submit')}
|
||||
</AppButton>
|
||||
) : null}
|
||||
{accounts.length > 0 ? (
|
||||
<AppButton
|
||||
variant="text"
|
||||
onClick={() => {
|
||||
setShowForm(false);
|
||||
reset();
|
||||
}}
|
||||
disabled={addAccount.isPending}
|
||||
>
|
||||
{tc('cancel')}
|
||||
</AppButton>
|
||||
) : null}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</FormProvider>
|
||||
) : null}
|
||||
</Box>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user