feat(clients): align client form with first and last name API fields
This commit is contained in:
2
next-env.d.ts
vendored
2
next-env.d.ts
vendored
@@ -1,6 +1,6 @@
|
|||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
import "./.next/dev/types/routes.d.ts";
|
import "./.next/types/routes.d.ts";
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||||
|
|||||||
@@ -19,10 +19,12 @@ export function useClientColumns(): ColumnDef<Client>[] {
|
|||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
accessorKey: 'name',
|
accessorKey: 'first_name',
|
||||||
header: 'Client',
|
header: 'Client',
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<span className="font-medium">{row.original.name}</span>
|
<span className="font-medium">
|
||||||
|
{`${row.original.first_name} ${row.original.last_name}`.trim()}
|
||||||
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,7 +40,12 @@ export function ClientSheet({
|
|||||||
canSubmit,
|
canSubmit,
|
||||||
isSaving,
|
isSaving,
|
||||||
}: ClientSheetProps) {
|
}: ClientSheetProps) {
|
||||||
const nameErrorMessage = isSubmitted ? errors.name?.message : undefined;
|
const firstNameErrorMessage = isSubmitted
|
||||||
|
? errors.first_name?.message
|
||||||
|
: undefined;
|
||||||
|
const lastNameErrorMessage = isSubmitted
|
||||||
|
? errors.last_name?.message
|
||||||
|
: undefined;
|
||||||
const emailErrorMessage = isSubmitted ? errors.email?.message : undefined;
|
const emailErrorMessage = isSubmitted ? errors.email?.message : undefined;
|
||||||
const landlineErrorMessage = isSubmitted
|
const landlineErrorMessage = isSubmitted
|
||||||
? errors.landline_number?.message
|
? errors.landline_number?.message
|
||||||
@@ -68,23 +73,43 @@ export function ClientSheet({
|
|||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<form onSubmit={onSubmit} className="flex min-h-0 flex-1 flex-col">
|
<form
|
||||||
|
noValidate
|
||||||
|
onSubmit={onSubmit}
|
||||||
|
className="flex min-h-0 flex-1 flex-col"
|
||||||
|
>
|
||||||
<div className="max-h-[58vh] space-y-5 overflow-y-auto px-6 py-4">
|
<div className="max-h-[58vh] space-y-5 overflow-y-auto px-6 py-4">
|
||||||
<div className="grid gap-4 md:grid-cols-2">
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
<FormField
|
<FormField
|
||||||
id="client-name"
|
id="client-first-name"
|
||||||
label="Client Name"
|
label="First Name"
|
||||||
required
|
required
|
||||||
error={nameErrorMessage}
|
error={firstNameErrorMessage}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
id="client-name"
|
id="client-first-name"
|
||||||
placeholder="Enter client name"
|
placeholder="Enter first name"
|
||||||
aria-invalid={!!nameErrorMessage}
|
aria-invalid={!!firstNameErrorMessage}
|
||||||
{...register('name')}
|
{...register('first_name')}
|
||||||
/>
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
id="client-last-name"
|
||||||
|
label="Last Name"
|
||||||
|
required
|
||||||
|
error={lastNameErrorMessage}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
id="client-last-name"
|
||||||
|
placeholder="Enter last name"
|
||||||
|
aria-invalid={!!lastNameErrorMessage}
|
||||||
|
{...register('last_name')}
|
||||||
|
/>
|
||||||
|
</FormField>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
<FormField
|
<FormField
|
||||||
id="client-email"
|
id="client-email"
|
||||||
label="Company Email"
|
label="Company Email"
|
||||||
@@ -94,14 +119,12 @@ export function ClientSheet({
|
|||||||
<Input
|
<Input
|
||||||
id="client-email"
|
id="client-email"
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="info@example.com"
|
placeholder="Enter company email"
|
||||||
aria-invalid={!!emailErrorMessage}
|
aria-invalid={!!emailErrorMessage}
|
||||||
{...register('email')}
|
{...register('email')}
|
||||||
/>
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid gap-4 md:grid-cols-2">
|
|
||||||
<FormField
|
<FormField
|
||||||
id="landline-number"
|
id="landline-number"
|
||||||
label="Landline Number"
|
label="Landline Number"
|
||||||
@@ -110,11 +133,12 @@ export function ClientSheet({
|
|||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
id="landline-number"
|
id="landline-number"
|
||||||
placeholder="+91-22-12345678"
|
placeholder="Enter landline number"
|
||||||
aria-invalid={!!landlineErrorMessage}
|
aria-invalid={!!landlineErrorMessage}
|
||||||
{...register('landline_number')}
|
{...register('landline_number')}
|
||||||
/>
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
</div>
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
id="address"
|
id="address"
|
||||||
@@ -124,28 +148,35 @@ export function ClientSheet({
|
|||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
id="address"
|
id="address"
|
||||||
placeholder="12 MG Road, Mumbai, MH 400001"
|
placeholder="Enter address"
|
||||||
aria-invalid={!!addressErrorMessage}
|
aria-invalid={!!addressErrorMessage}
|
||||||
{...register('address')}
|
{...register('address')}
|
||||||
/>
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid gap-4 md:grid-cols-3">
|
<div className="grid gap-4 md:grid-cols-3">
|
||||||
<FormField id="gst" label="GST">
|
<FormField id="gst" label="GST">
|
||||||
<Input
|
<Input
|
||||||
id="gst"
|
id="gst"
|
||||||
placeholder="27ABCDE1234F1Z5"
|
placeholder="Enter GST number"
|
||||||
{...register('gst')}
|
{...register('gst')}
|
||||||
/>
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<FormField id="pan" label="PAN">
|
<FormField id="pan" label="PAN">
|
||||||
<Input id="pan" placeholder="ABCDE1234F" {...register('pan')} />
|
<Input
|
||||||
|
id="pan"
|
||||||
|
placeholder="Enter PAN number"
|
||||||
|
{...register('pan')}
|
||||||
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<FormField id="tan" label="TAN">
|
<FormField id="tan" label="TAN">
|
||||||
<Input id="tan" placeholder="MUMA12345B" {...register('tan')} />
|
<Input
|
||||||
|
id="tan"
|
||||||
|
placeholder="Enter TAN number"
|
||||||
|
{...register('tan')}
|
||||||
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -172,7 +203,7 @@ export function ClientSheet({
|
|||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
id="contact-phone-number"
|
id="contact-phone-number"
|
||||||
placeholder="+919876543210"
|
placeholder="Enter contact phone"
|
||||||
aria-invalid={!!contactPhoneErrorMessage}
|
aria-invalid={!!contactPhoneErrorMessage}
|
||||||
{...register('contact_phone_number')}
|
{...register('contact_phone_number')}
|
||||||
/>
|
/>
|
||||||
@@ -187,7 +218,7 @@ export function ClientSheet({
|
|||||||
<Input
|
<Input
|
||||||
id="contact-email"
|
id="contact-email"
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="contact@example.com"
|
placeholder="Enter contact email"
|
||||||
aria-invalid={!!contactEmailErrorMessage}
|
aria-invalid={!!contactEmailErrorMessage}
|
||||||
{...register('contact_email')}
|
{...register('contact_email')}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -9,37 +9,32 @@ import { z } from 'zod';
|
|||||||
import type { Client } from '@/types';
|
import type { Client } from '@/types';
|
||||||
import { useSaveClientMutation } from './useClientMutations';
|
import { useSaveClientMutation } from './useClientMutations';
|
||||||
|
|
||||||
const phoneSchema = z
|
const requiredText = (message: string) => z.string().trim().min(1, message);
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.min(1, 'Phone number is required')
|
|
||||||
.regex(/^\+(?:[0-9] ?|-){6,18}[0-9]$/, 'Please enter a valid phone number');
|
|
||||||
|
|
||||||
const optionalTaxIdSchema = z.string().trim();
|
const optionalTaxIdSchema = z.string().trim();
|
||||||
|
|
||||||
const clientFormSchema = z.object({
|
const clientFormSchema = z.object({
|
||||||
id: z.number().optional(),
|
id: z.number().optional(),
|
||||||
name: z.string().trim().min(1, 'Client name is required'),
|
first_name: requiredText('First name is required'),
|
||||||
email: z.string().trim().min(1, 'Email is required').email('Invalid email'),
|
last_name: requiredText('Last name is required'),
|
||||||
landline_number: phoneSchema,
|
email: requiredText('Email is required').email('Invalid email'),
|
||||||
address: z.string().trim().min(1, 'Address is required'),
|
landline_number: requiredText('Landline number is required'),
|
||||||
|
address: requiredText('Address is required'),
|
||||||
gst: optionalTaxIdSchema,
|
gst: optionalTaxIdSchema,
|
||||||
pan: optionalTaxIdSchema,
|
pan: optionalTaxIdSchema,
|
||||||
tan: optionalTaxIdSchema,
|
tan: optionalTaxIdSchema,
|
||||||
contact_name: z.string().trim().min(1, 'Contact name is required'),
|
contact_name: requiredText('Contact name is required'),
|
||||||
contact_phone_number: phoneSchema,
|
contact_phone_number: requiredText('Contact phone number is required'),
|
||||||
contact_email: z
|
contact_email: requiredText('Contact email is required').email(
|
||||||
.string()
|
'Invalid contact email',
|
||||||
.trim()
|
),
|
||||||
.min(1, 'Contact email is required')
|
|
||||||
.email('Invalid contact email'),
|
|
||||||
is_active: z.boolean(),
|
is_active: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type ClientFormValues = z.infer<typeof clientFormSchema>;
|
export type ClientFormValues = z.infer<typeof clientFormSchema>;
|
||||||
|
|
||||||
const defaultValues: ClientFormValues = {
|
const defaultValues: ClientFormValues = {
|
||||||
name: '',
|
first_name: '',
|
||||||
|
last_name: '',
|
||||||
email: '',
|
email: '',
|
||||||
landline_number: '',
|
landline_number: '',
|
||||||
address: '',
|
address: '',
|
||||||
@@ -73,7 +68,8 @@ export function useClientForm({ onSaved }: { onSaved: () => void }) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const clientId = useWatch({ control, name: 'id' });
|
const clientId = useWatch({ control, name: 'id' });
|
||||||
const name = useWatch({ control, name: 'name' }) || '';
|
const firstName = useWatch({ control, name: 'first_name' }) || '';
|
||||||
|
const lastName = useWatch({ control, name: 'last_name' }) || '';
|
||||||
const email = useWatch({ control, name: 'email' }) || '';
|
const email = useWatch({ control, name: 'email' }) || '';
|
||||||
const landlineNumber = useWatch({ control, name: 'landline_number' }) || '';
|
const landlineNumber = useWatch({ control, name: 'landline_number' }) || '';
|
||||||
const address = useWatch({ control, name: 'address' }) || '';
|
const address = useWatch({ control, name: 'address' }) || '';
|
||||||
@@ -82,7 +78,8 @@ export function useClientForm({ onSaved }: { onSaved: () => void }) {
|
|||||||
useWatch({ control, name: 'contact_phone_number' }) || '';
|
useWatch({ control, name: 'contact_phone_number' }) || '';
|
||||||
const contactEmail = useWatch({ control, name: 'contact_email' }) || '';
|
const contactEmail = useWatch({ control, name: 'contact_email' }) || '';
|
||||||
const canSubmit =
|
const canSubmit =
|
||||||
name.trim().length > 0 &&
|
firstName.trim().length > 0 &&
|
||||||
|
lastName.trim().length > 0 &&
|
||||||
email.trim().length > 0 &&
|
email.trim().length > 0 &&
|
||||||
landlineNumber.trim().length > 0 &&
|
landlineNumber.trim().length > 0 &&
|
||||||
address.trim().length > 0 &&
|
address.trim().length > 0 &&
|
||||||
@@ -111,7 +108,8 @@ export function useClientForm({ onSaved }: { onSaved: () => void }) {
|
|||||||
(client: Client) => {
|
(client: Client) => {
|
||||||
reset({
|
reset({
|
||||||
id: client.id,
|
id: client.id,
|
||||||
name: client.name || '',
|
first_name: client.first_name || '',
|
||||||
|
last_name: client.last_name || '',
|
||||||
email: client.email || '',
|
email: client.email || '',
|
||||||
landline_number: client.landline_number || '',
|
landline_number: client.landline_number || '',
|
||||||
address: client.address || '',
|
address: client.address || '',
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ export function useSaveClientMutation({ onSaved }: { onSaved: () => void }) {
|
|||||||
mutationFn: (values: ClientFormValues) =>
|
mutationFn: (values: ClientFormValues) =>
|
||||||
clientService.saveClient({
|
clientService.saveClient({
|
||||||
id: values.id,
|
id: values.id,
|
||||||
name: values.name.trim(),
|
first_name: values.first_name.trim(),
|
||||||
|
last_name: values.last_name.trim(),
|
||||||
email: values.email.trim(),
|
email: values.email.trim(),
|
||||||
landline_number: values.landline_number.trim(),
|
landline_number: values.landline_number.trim(),
|
||||||
address: values.address.trim(),
|
address: values.address.trim(),
|
||||||
|
|||||||
@@ -83,7 +83,11 @@ export function SegmentDialog({
|
|||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<form onSubmit={onSubmit} className="flex min-h-0 flex-1 flex-col">
|
<form
|
||||||
|
noValidate
|
||||||
|
onSubmit={onSubmit}
|
||||||
|
className="flex min-h-0 flex-1 flex-col"
|
||||||
|
>
|
||||||
<div className="max-h-[58vh] space-y-6 overflow-y-auto px-6 py-4">
|
<div className="max-h-[58vh] space-y-6 overflow-y-auto px-6 py-4">
|
||||||
<section className="space-y-4">
|
<section className="space-y-4">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
|
|||||||
@@ -141,17 +141,7 @@ export function useSegmentForm({ onSaved }: { onSaved: () => void }) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = handleSubmit(
|
const onSubmit = handleSubmit((values) => saveMutation.mutate(values));
|
||||||
(values) => saveMutation.mutate(values),
|
|
||||||
(formErrors) => {
|
|
||||||
const firstMessage = Object.values(formErrors).find(
|
|
||||||
(error) => error?.message,
|
|
||||||
)?.message;
|
|
||||||
if (firstMessage) {
|
|
||||||
toast.error(String(firstMessage));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const openCreate = useCallback(() => {
|
const openCreate = useCallback(() => {
|
||||||
reset(defaultValues);
|
reset(defaultValues);
|
||||||
|
|||||||
@@ -128,7 +128,11 @@ export function TenantSheet({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid gap-4 md:grid-cols-2">
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
<FormField label="Client" required error={fieldError('client_id')}>
|
<FormField
|
||||||
|
label="Client"
|
||||||
|
required
|
||||||
|
error={fieldError('client_id')}
|
||||||
|
>
|
||||||
<Select
|
<Select
|
||||||
value={clientId}
|
value={clientId}
|
||||||
onValueChange={onClientChange}
|
onValueChange={onClientChange}
|
||||||
@@ -146,7 +150,9 @@ export function TenantSheet({
|
|||||||
<SelectContent>
|
<SelectContent>
|
||||||
{clients.map((client) => (
|
{clients.map((client) => (
|
||||||
<SelectItem key={client.id} value={String(client.id)}>
|
<SelectItem key={client.id} value={String(client.id)}>
|
||||||
{client.name}
|
{[client.first_name, client.last_name]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' ')}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { ArrowLeft, BarChart3 } from 'lucide-react';
|
import { ArrowLeft } from 'lucide-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { SparkleButton } from '@/components/ui/sparkle-button';
|
||||||
import { PERMISSIONS } from '@/constants/permissions';
|
import { PERMISSIONS } from '@/constants/permissions';
|
||||||
import { PermissionGuard } from '@/guards';
|
import { PermissionGuard } from '@/guards';
|
||||||
import type { TicketDetail } from '@/types';
|
import type { TicketDetail } from '@/types';
|
||||||
@@ -28,14 +29,12 @@ export function TicketDetailHeader({ ticket }: { ticket: TicketDetail }) {
|
|||||||
<div className="flex shrink-0 items-center gap-2">
|
<div className="flex shrink-0 items-center gap-2">
|
||||||
{ticket.video_id ? (
|
{ticket.video_id ? (
|
||||||
<PermissionGuard permissions={PERMISSIONS.TICKET.ASSIGN}>
|
<PermissionGuard permissions={PERMISSIONS.TICKET.ASSIGN}>
|
||||||
<Button
|
<SparkleButton
|
||||||
variant="outline"
|
className="h-10 min-w-36 px-5"
|
||||||
size="sm"
|
|
||||||
onClick={() => router.push(`/results/${ticket.video_id}`)}
|
onClick={() => router.push(`/results/${ticket.video_id}`)}
|
||||||
>
|
>
|
||||||
<BarChart3 className="size-4" />
|
View Analysis
|
||||||
Analysis
|
</SparkleButton>
|
||||||
</Button>
|
|
||||||
</PermissionGuard>
|
</PermissionGuard>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ import { RepairVideoComparison } from './repair-report/RepairVideoComparison';
|
|||||||
export function TicketRepairReportCard({ ticket }: { ticket: TicketDetail }) {
|
export function TicketRepairReportCard({ ticket }: { ticket: TicketDetail }) {
|
||||||
const repair = ticket.repair;
|
const repair = ticket.repair;
|
||||||
|
|
||||||
|
if (!repair) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="space-y-5">
|
<section className="space-y-5">
|
||||||
<RepairReportPanel ticket={ticket} />
|
<RepairReportPanel ticket={ticket} />
|
||||||
|
|||||||
34
src/components/ui/sparkle-button.tsx
Normal file
34
src/components/ui/sparkle-button.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
|
type SparkleButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>;
|
||||||
|
|
||||||
|
export function SparkleButton({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
type = 'button',
|
||||||
|
...props
|
||||||
|
}: SparkleButtonProps) {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type={type}
|
||||||
|
className={cn(
|
||||||
|
'group inline-flex h-12 min-w-40 shrink-0 cursor-pointer items-center justify-center gap-3 rounded-full border-0 bg-[#1C1A1C] px-6 text-sm font-semibold text-[#AAAAAA] outline-none transition-all duration-500 ease-in-out hover:-translate-y-0.5 hover:bg-[linear-gradient(0deg,#A47CF3,#683FEA)] hover:text-white hover:[box-shadow:inset_0_1px_0_0_rgba(255,255,255,0.4),inset_0_-4px_0_0_rgba(0,0,0,0.2),0_0_0_4px_rgba(255,255,255,0.2),0_0_180px_0_#9917FF] focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
className="size-5 fill-[#AAAAAA] transition-all duration-700 ease-in-out group-hover:scale-125 group-hover:fill-white"
|
||||||
|
>
|
||||||
|
<path d="M10 21.236 6.755 14.745.264 11.5l6.491-3.245L10 1.764l3.245 6.491 6.491 3.245-6.491 3.245L10 21.236ZM18 21l1.5 3 1.5-3 3-1.5-3-1.5-1.5-3-1.5 3-3 1.5 3 1.5ZM19.333 4.667 20.5 7l1.167-2.333L24 3.5l-2.333-1.167L20.5 0l-1.167 2.333L17 3.5l2.333 1.167Z" />
|
||||||
|
</svg>
|
||||||
|
<span>{children}</span>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -40,7 +40,7 @@ export default function VideoPlayerSection({
|
|||||||
isLoading: isVideoLoading,
|
isLoading: isVideoLoading,
|
||||||
isError: isVideoError,
|
isError: isVideoError,
|
||||||
refetch: refetchVideo,
|
refetch: refetchVideo,
|
||||||
} = useAnnotatedVideoQuery(data.annotated_video_url);
|
} = useAnnotatedVideoQuery(data.processed_video_url || '');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import type {
|
|||||||
|
|
||||||
function toClientPayload(payload: ClientRequest) {
|
function toClientPayload(payload: ClientRequest) {
|
||||||
return {
|
return {
|
||||||
name: payload.name,
|
first_name: payload.first_name,
|
||||||
|
last_name: payload.last_name,
|
||||||
email: payload.email,
|
email: payload.email,
|
||||||
landline_number: payload.landline_number,
|
landline_number: payload.landline_number,
|
||||||
address: payload.address,
|
address: payload.address,
|
||||||
@@ -34,7 +35,8 @@ export const clientService = {
|
|||||||
skip: params?.skip ?? 0,
|
skip: params?.skip ?? 0,
|
||||||
limit: params?.limit ?? 10,
|
limit: params?.limit ?? 10,
|
||||||
search_term: params?.search_term,
|
search_term: params?.search_term,
|
||||||
name: params?.name,
|
first_name: params?.first_name,
|
||||||
|
last_name: params?.last_name,
|
||||||
email: params?.email,
|
email: params?.email,
|
||||||
contact_name: params?.contact_name,
|
contact_name: params?.contact_name,
|
||||||
is_active: params?.is_active,
|
is_active: params?.is_active,
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import { DetectionResultLog } from './detection';
|
|||||||
export type CompletedVideoResult = {
|
export type CompletedVideoResult = {
|
||||||
video_id: string;
|
video_id: string;
|
||||||
status: 'completed' | string;
|
status: 'completed' | string;
|
||||||
annotated_video_url: string;
|
// annotated_video_url: string;
|
||||||
|
processed_video_url: string | null;
|
||||||
|
raw_video_url: string | null;
|
||||||
fps: number;
|
fps: number;
|
||||||
duration_seconds: number;
|
duration_seconds: number;
|
||||||
detection_mode?: string;
|
detection_mode?: string;
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import type { PaginationParams } from './common';
|
|||||||
|
|
||||||
export interface Client {
|
export interface Client {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
first_name: string;
|
||||||
|
last_name: string;
|
||||||
email: string;
|
email: string;
|
||||||
landline_number: string;
|
landline_number: string;
|
||||||
address: string;
|
address: string;
|
||||||
@@ -19,7 +20,8 @@ export interface Client {
|
|||||||
|
|
||||||
export interface ClientRequest {
|
export interface ClientRequest {
|
||||||
id?: number;
|
id?: number;
|
||||||
name: string;
|
first_name: string;
|
||||||
|
last_name: string;
|
||||||
email: string;
|
email: string;
|
||||||
landline_number: string;
|
landline_number: string;
|
||||||
address: string;
|
address: string;
|
||||||
@@ -34,7 +36,8 @@ export interface ClientRequest {
|
|||||||
|
|
||||||
export interface ClientListParams extends PaginationParams {
|
export interface ClientListParams extends PaginationParams {
|
||||||
search_term?: string;
|
search_term?: string;
|
||||||
name?: string;
|
first_name?: string;
|
||||||
|
last_name?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
contact_name?: string;
|
contact_name?: string;
|
||||||
is_active?: boolean;
|
is_active?: boolean;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export interface TicketVideo {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string | null;
|
name: string | null;
|
||||||
url: string | null;
|
url: string | null;
|
||||||
|
processed_video_url: string | null;
|
||||||
thumbnail: string | null;
|
thumbnail: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user