add health benefit form
fix super admin
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import {
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@kit/ui/form';
|
||||
import { Input } from '@kit/ui/input';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@kit/ui/select';
|
||||
import { Trans } from '@kit/ui/trans';
|
||||
|
||||
const HealthBenefitFields = () => {
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
<FormField
|
||||
name="occurance"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
<Trans i18nKey="billing:healthBenefitForm.title" />
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Select {...field} onValueChange={field.onChange}>
|
||||
<SelectTrigger>
|
||||
<SelectValue
|
||||
placeholder={<Trans i18nKey="common:formField:occurance" />}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="yearly">
|
||||
<Trans i18nKey="billing:occurance.yearly" />
|
||||
</SelectItem>
|
||||
<SelectItem value="quarterly">
|
||||
<Trans i18nKey="billing:occurance.quarterly" />
|
||||
</SelectItem>
|
||||
<SelectItem value="monthly">
|
||||
<Trans i18nKey="billing:occurance.monthly" />
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
name="amount"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
<Trans i18nKey={'common:formField:amount'} />
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="number"
|
||||
onChange={(e) =>
|
||||
field.onChange(
|
||||
e.target.value === '' ? null : Number(e.target.value),
|
||||
)
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default HealthBenefitFields;
|
||||
111
app/home/[account]/billing/_components/health-benefit-form.tsx
Normal file
111
app/home/[account]/billing/_components/health-benefit-form.tsx
Normal file
@@ -0,0 +1,111 @@
|
||||
'use client';
|
||||
|
||||
import { UpdateHealthBenefitSchema } from '@/packages/billing/core/src/schema';
|
||||
import { Database } from '@/packages/supabase/src/database.types';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { PiggyBankIcon } from 'lucide-react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
|
||||
import { Button } from '@kit/ui/button';
|
||||
import { Form } from '@kit/ui/form';
|
||||
import { Spinner } from '@kit/ui/makerkit/spinner';
|
||||
import { Separator } from '@kit/ui/shadcn/separator';
|
||||
import { toast } from '@kit/ui/shadcn/sonner';
|
||||
import { Trans } from '@kit/ui/trans';
|
||||
|
||||
import { cn } from '~/lib/utils';
|
||||
|
||||
import { updateHealthBenefit } from '../_lib/server/server-actions';
|
||||
import HealthBenefitFields from './health-benefit-fields';
|
||||
import YearlyExpensesOverview from './yearly-expenses-overview';
|
||||
|
||||
const HealthBenefitForm = ({
|
||||
account,
|
||||
companyParams,
|
||||
}: {
|
||||
account: Database['medreport']['Tables']['accounts']['Row'];
|
||||
companyParams: Database['medreport']['Tables']['company_params']['Row'];
|
||||
}) => {
|
||||
const form = useForm({
|
||||
resolver: zodResolver(UpdateHealthBenefitSchema),
|
||||
mode: 'onChange',
|
||||
defaultValues: {
|
||||
occurance: companyParams.benefit_occurance || 'yearly',
|
||||
amount: companyParams.benefit_amount || 0,
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form
|
||||
className="flex flex-col gap-6 px-6 text-left"
|
||||
onSubmit={form.handleSubmit((data) => {
|
||||
toast.promise(
|
||||
() => updateHealthBenefit({ ...data, accountId: account.id }),
|
||||
{
|
||||
success: 'success',
|
||||
error: 'error',
|
||||
},
|
||||
);
|
||||
})}
|
||||
>
|
||||
<div className="mt-8 flex items-center justify-between">
|
||||
<div>
|
||||
<h4>
|
||||
<Trans
|
||||
i18nKey="billing:pageTitle"
|
||||
values={{ companyName: account.slug }}
|
||||
/>
|
||||
</h4>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
<Trans i18nKey="billing:description" />
|
||||
</p>
|
||||
</div>
|
||||
<Button type="submit" className="relative">
|
||||
{form.formState.isSubmitting && (
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
)}
|
||||
<div className={cn({ invisible: form.formState.isSubmitting })}>
|
||||
<Trans i18nKey="account:saveChanges" />
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex flex-row gap-6">
|
||||
<div className="border-border w-1/3 rounded-lg border">
|
||||
<div className="p-6">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-orange-100">
|
||||
<PiggyBankIcon className="h-[32px] w-[32px] stroke-orange-400 stroke-2" />
|
||||
</div>
|
||||
<p className="mt-4 text-sm font-medium">
|
||||
<Trans i18nKey="billing:healthBenefitForm.description" />
|
||||
</p>
|
||||
<p className="pt-2 text-2xl font-semibold">
|
||||
{companyParams.benefit_amount || 0} €
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div className="p-6">
|
||||
<HealthBenefitFields />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1">
|
||||
<YearlyExpensesOverview
|
||||
employeeCount={22}
|
||||
companyParams={companyParams}
|
||||
/>
|
||||
<p className="text-muted-foreground mt-2 text-sm">
|
||||
<Trans i18nKey="billing:healthBenefitForm.info" />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default HealthBenefitForm;
|
||||
@@ -0,0 +1,90 @@
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { Database } from '@/packages/supabase/src/database.types';
|
||||
|
||||
import { Trans } from '@kit/ui/makerkit/trans';
|
||||
import { Separator } from '@kit/ui/separator';
|
||||
|
||||
const YearlyExpensesOverview = ({
|
||||
employeeCount = 0,
|
||||
companyParams,
|
||||
}: {
|
||||
employeeCount?: number;
|
||||
companyParams: Database['medreport']['Tables']['company_params']['Row'];
|
||||
}) => {
|
||||
const monthlyExpensePerEmployee = useMemo(() => {
|
||||
if (!companyParams.benefit_amount) {
|
||||
return '0.00';
|
||||
}
|
||||
|
||||
switch (companyParams.benefit_occurance) {
|
||||
case 'yearly':
|
||||
return (companyParams.benefit_amount / 12).toFixed(2);
|
||||
case 'quarterly':
|
||||
return (companyParams.benefit_amount / 4).toFixed(2);
|
||||
case 'monthly':
|
||||
return companyParams.benefit_amount.toFixed(2);
|
||||
default:
|
||||
return '0.00';
|
||||
}
|
||||
}, [companyParams]);
|
||||
|
||||
const maxYearlyExpensePerEmployee = useMemo(() => {
|
||||
if (!companyParams.benefit_amount) {
|
||||
return '0.00';
|
||||
}
|
||||
|
||||
switch (companyParams.benefit_occurance) {
|
||||
case 'yearly':
|
||||
return companyParams.benefit_amount.toFixed(2);
|
||||
case 'quarterly':
|
||||
return (companyParams.benefit_amount * 4).toFixed(2);
|
||||
case 'monthly':
|
||||
return (companyParams.benefit_amount * 12).toFixed(2);
|
||||
default:
|
||||
return '0.00';
|
||||
}
|
||||
}, [companyParams]);
|
||||
|
||||
return (
|
||||
<div className="border-border rounded-lg border p-6">
|
||||
<h5>
|
||||
<Trans i18nKey="billing:expensesOverview.title" />
|
||||
</h5>
|
||||
<div className="mt-5 flex justify-between">
|
||||
<p className="text-sm font-medium">
|
||||
<Trans i18nKey="billing:expensesOverview.monthly" />
|
||||
</p>
|
||||
<span className="text-primary text-sm font-bold">
|
||||
{monthlyExpensePerEmployee} €
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-3 flex justify-between">
|
||||
<p className="text-sm font-medium">
|
||||
<Trans i18nKey="billing:expensesOverview.yearly" />
|
||||
</p>
|
||||
<span className="text-sm font-medium">
|
||||
{maxYearlyExpensePerEmployee} €
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-5 mb-3 flex justify-between">
|
||||
<p className="text-sm font-medium">
|
||||
<Trans
|
||||
i18nKey="billing:expensesOverview.total"
|
||||
values={{ employeeCount: employeeCount || 0 }}
|
||||
/>
|
||||
</p>
|
||||
<span className="text-sm font-medium">
|
||||
{(Number(maxYearlyExpensePerEmployee) * employeeCount).toFixed(2)} €
|
||||
</span>
|
||||
</div>
|
||||
<Separator />
|
||||
<div className="mt-4 flex justify-between">
|
||||
<p className="font-semibold">Kokku</p>
|
||||
<span className="font-semibold">13 200,00 €</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default YearlyExpensesOverview;
|
||||
Reference in New Issue
Block a user