Skip to content

Instantly share code, notes, and snippets.

@azeezat
Last active January 9, 2026 16:09
Show Gist options
  • Select an option

  • Save azeezat/b2880cc2f6163b82b0d157416a8afafa to your computer and use it in GitHub Desktop.

Select an option

Save azeezat/b2880cc2f6163b82b0d157416a8afafa to your computer and use it in GitHub Desktop.
the logical part of the create request page
'use client';
import React, { useState } from 'react';
import { DialogComponent } from '@/frontend/components/dialog/dialog';
import { Form } from 'radix-ui';
import {
FileUploadInput,
MutationcreateRequestArgs,
Request,
RequestCategory,
RequestInput,
UploadedFile,
} from '@/backend/graphql/generated/types.generated';
import { useMutation, useQuery } from '@apollo/client/react';
import { UPLOAD_FILES_MUTATION } from '@/frontend/data/graphql-api/uploads';
import { useToastStore } from '@/frontend/store/toast-store';
import {
CREATE_REQUEST_MUTATION,
GET_REQUESTS_QUERY,
REQUEST_CATEGORY_QUERY,
} from '@/frontend/data/graphql-api/requests';
import { toGraphQLDateTime } from '@/frontend/utils/string-utils';
import { RequestForm } from './request-form';
import { validateFiles } from '@/backend/utils/helpers';
import { errorsByField } from '@/frontend/utils/error-utils';
interface CreateRequestDialogProps {
open: boolean;
setOpen: (value: boolean) => void;
setOpenPaymentMethod: (value: boolean) => void;
setRequestId: (value: string) => void;
}
export const CreateRequestDialog = ({
open,
setOpen,
setOpenPaymentMethod,
setRequestId,
}: CreateRequestDialogProps) => {
const { pushToast } = useToastStore();
const initialCreateRequestData: RequestInput = {
title: '',
description: '',
budget: 0,
numberOfCompanions: 1,
startDateTime: '',
endDateTime: '',
location: '',
categoryId: 0,
companionDistance: 1,
};
const [createRequestData, setCreateRequestData] = useState<RequestInput>(
initialCreateRequestData
);
const [errors, setErrors] = useState<Record<string, string>>({});
const [files, setFiles] = useState<File[]>();
const { data: requestCategories, loading: loadingCategories } = useQuery<{
requestCategories: RequestCategory[];
}>(REQUEST_CATEGORY_QUERY);
/**Create request mutation */
const [createRequestMutation, { loading: creatingRequest }] = useMutation<
{
createRequest: Request;
},
MutationcreateRequestArgs
>(CREATE_REQUEST_MUTATION, {
refetchQueries: [
{
query: GET_REQUESTS_QUERY,
variables: {
page: 1,
limit: 10,
},
},
],
});
const handleCreateRequest = () => {
if (files?.length) {
const fileValidationError = validateFiles(files, 2);
if (fileValidationError) {
pushToast({
type: 'error',
description: fileValidationError,
});
return;
}
}
createRequestMutation({
variables: {
input: {
...createRequestData,
startDateTime: toGraphQLDateTime(
createRequestData.startDateTime as string
),
endDateTime: toGraphQLDateTime(
createRequestData.endDateTime as string
),
},
},
onCompleted: (data) => {
setErrors({});
setRequestId(data.createRequest.id as string);
if (files?.length) {
handleUpload(data.createRequest.id as string);
return;
}
setOpenPaymentMethod(true);
},
onError: (error) => {
//@ts-expect-error Known errors in apollo
const err = errorsByField(error.errors?.[0]?.extensions?.issues || []);
setErrors(err);
pushToast({
type: 'error',
description: `Failed to create request. ${error}`,
});
},
});
};
/**Upload files mutation */
const [uploadFileMutation, { loading: uploadingRequestFiles }] = useMutation<
{
uploadedFiles: UploadedFile[];
},
{ files: File[]; input: FileUploadInput }
>(UPLOAD_FILES_MUTATION);
const handleUpload = (entityId: string) => {
uploadFileMutation({
variables: {
files: files as File[],
input: {
entityId,
purpose: 'REQUEST',
},
},
onCompleted: () => {
setOpenPaymentMethod(true);
},
onError: (error) => {
pushToast({
type: 'error',
description: `Upload failed: ${error.message}`,
});
},
});
};
const resetPage = () => {
setOpen(false);
setFiles(undefined);
setCreateRequestData(initialCreateRequestData);
};
return (
<DialogComponent
open={open}
onOpenChange={(value) => {
setOpen(value);
setFiles(undefined);
setCreateRequestData(initialCreateRequestData);
}}
lock
title="Create Request"
footer={
<div className="flex justify-end gap-2">
<button
onClick={() => resetPage()}
className="rounded-xl border border-neutral-300 px-3 py-2 text-sm hover:bg-neutral-50 dark:border-neutral-700"
disabled={creatingRequest}
>
Cancel
</button>
<Form.Submit asChild>
<button
className="rounded-xl bg-black px-3 py-2 text-sm text-white hover:opacity-90 dark:bg-white dark:text-black"
type="submit"
onClick={handleCreateRequest}
disabled={creatingRequest}
>
{creatingRequest || uploadingRequestFiles
? 'Creating...'
: 'Create Request'}
</button>
</Form.Submit>
</div>
}
>
<RequestForm
files={files as File[]}
setFiles={setFiles}
createRequestData={createRequestData}
setCreateRequestData={setCreateRequestData}
requestCategories={requestCategories?.requestCategories || []}
loadingCategories={loadingCategories}
errors={errors}
/>
</DialogComponent>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment