diff --git a/app/(dashboard)/deliveries/create/page.tsx b/app/(dashboard)/deliveries/create/page.tsx
index 5321f78..6dfaa66 100644
--- a/app/(dashboard)/deliveries/create/page.tsx
+++ b/app/(dashboard)/deliveries/create/page.tsx
@@ -1,11 +1,13 @@
export const dynamic = 'force-dynamic';
+import { CreateDeliveryForm } from '@/features/deliveries/components/CreateDeliveryForm';
import { CurrencyConverter } from '@/features/deliveries/components/CurrencyConverter';
export default function CreateDeliveryPage() {
return (
-
+
+
);
-}
\ No newline at end of file
+}
diff --git a/features/deliveries/components/CreateDeliveryForm.tsx b/features/deliveries/components/CreateDeliveryForm.tsx
new file mode 100644
index 0000000..043b9ba
--- /dev/null
+++ b/features/deliveries/components/CreateDeliveryForm.tsx
@@ -0,0 +1,199 @@
+'use client';
+
+import { useCreateDelivery } from '@/hooks/useCreateDelivery';
+
+export function CreateDeliveryForm() {
+ const { form, isSubmitting, isSuccess, onSubmit } = useCreateDelivery();
+
+ const {
+ register,
+ handleSubmit,
+ formState: { errors, isValid },
+ } = form;
+
+ return (
+
+
+
+ Create a new logistics request
+
+
+ Fill in pickup, destination, package details, and recipient contact
+ information.
+
+
+
+
+
+ );
+}
diff --git a/hooks/useCreateDelivery.ts b/hooks/useCreateDelivery.ts
new file mode 100644
index 0000000..90ad54b
--- /dev/null
+++ b/hooks/useCreateDelivery.ts
@@ -0,0 +1,89 @@
+'use client';
+
+import { useForm } from 'react-hook-form';
+import { useMutation, useQueryClient } from '@tanstack/react-query';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { deliveriesService, type CreateDeliveryPayload } from '@/services/deliveries.service';
+import { useToast } from '@/hooks/useToast';
+
+export const createDeliverySchema = z.object({
+ pickupAddress: z
+ .string()
+ .min(5, 'Pickup address is required')
+ .max(250, 'Pickup address must be under 250 characters'),
+ destination: z
+ .string()
+ .min(5, 'Destination address is required')
+ .max(250, 'Destination address must be under 250 characters'),
+ packageSize: z.enum(['small', 'medium', 'large'], {
+ errorMap: () => ({ message: 'Please select a package size' }),
+ }),
+ description: z
+ .string()
+ .min(10, 'Package description is required')
+ .max(500, 'Package description must be under 500 characters'),
+ recipientName: z.string().min(2, 'Recipient name is required'),
+ recipientPhone: z
+ .string()
+ .min(7, 'Recipient phone is required')
+ .max(20, 'Recipient phone must be under 20 characters')
+ .regex(/^[0-9+()\-\.\s]+$/, 'Enter a valid phone number'),
+ recipientEmail: z.string().email('Enter a valid recipient email'),
+});
+
+export type CreateDeliveryFormValues = z.infer
;
+
+export interface UseCreateDeliveryReturn {
+ form: ReturnType>;
+ isSubmitting: boolean;
+ isSuccess: boolean;
+ onSubmit: (values: CreateDeliveryFormValues) => Promise;
+}
+
+export function useCreateDelivery(): UseCreateDeliveryReturn {
+ const queryClient = useQueryClient();
+ const { success, error } = useToast();
+
+ const form = useForm({
+ resolver: zodResolver(createDeliverySchema),
+ mode: 'onChange',
+ defaultValues: {
+ pickupAddress: '',
+ destination: '',
+ packageSize: 'small',
+ description: '',
+ recipientName: '',
+ recipientPhone: '',
+ recipientEmail: '',
+ },
+ });
+
+ const createDelivery = useMutation({
+ mutationFn: (payload: CreateDeliveryPayload) =>
+ deliveriesService.createDelivery(payload),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['deliveries'] });
+ success('Delivery request sent', 'Your logistics request was created successfully.');
+ form.reset();
+ },
+ onError: (err) => {
+ error(
+ 'Unable to create delivery request',
+ err instanceof Error ? err.message : 'Please try again later',
+ );
+ console.error('Create delivery error:', err);
+ },
+ });
+
+ const onSubmit = async (values: CreateDeliveryFormValues) => {
+ await createDelivery.mutateAsync(values);
+ };
+
+ return {
+ form,
+ isSubmitting: createDelivery.isLoading,
+ isSuccess: createDelivery.isSuccess,
+ onSubmit,
+ };
+}
diff --git a/services/deliveries.service.ts b/services/deliveries.service.ts
index e8080d4..30e305a 100644
--- a/services/deliveries.service.ts
+++ b/services/deliveries.service.ts
@@ -1,12 +1,22 @@
import { apiClient } from './api';
import { Delivery, StatusTimeline } from '../types/delivery';
+export interface CreateDeliveryPayload {
+ pickupAddress: string;
+ destination: string;
+ packageSize: 'small' | 'medium' | 'large';
+ description: string;
+ recipientName: string;
+ recipientPhone: string;
+ recipientEmail: string;
+}
+
export const deliveriesService = {
getDeliveries: async (): Promise => {
const { data } = await apiClient.get('/deliveries');
return data;
},
-
+
getDeliveryById: async (id: string): Promise => {
const { data } = await apiClient.get(`/deliveries/${id}`);
return data;