implement upload form functions

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
Chloe
2024-06-25 12:17:55 +07:00
parent 0bf01447f6
commit 5385b5ed67
6 changed files with 184 additions and 1 deletions

View File

@@ -0,0 +1,38 @@
'use server';
import { createFile, stageUploadFile, uploadFile } from 'lib/shopify';
import { UploadInput } from 'lib/shopify/types';
export const createStagedUploadFiles = async (params: UploadInput) => {
try {
const stagedTargets = await stageUploadFile(params);
if (!stagedTargets || stageUploadFile.length === 0) return null;
return JSON.parse(JSON.stringify(stagedTargets[0]));
} catch (error) {
console.log(error);
}
};
export const onUploadFile = async ({
url,
formData,
fileName,
resourceUrl
}: {
url: string;
formData: FormData;
fileName: string;
resourceUrl: string;
}) => {
try {
await uploadFile({ url, formData });
await createFile({
alt: fileName,
contentType: 'FILE',
originalSource: resourceUrl
});
} catch (error) {
console.log(error);
}
};

View File

@@ -0,0 +1,42 @@
import { PhotoIcon } from '@heroicons/react/24/outline';
import { ChangeEvent, useId, useState } from 'react';
type FileInputProps = {
name: string;
label: string;
};
const FileInput = ({ name, label }: FileInputProps) => {
const id = useId();
const [file, setFile] = useState<File | undefined>();
const onFileChange = (e: ChangeEvent<HTMLInputElement>) => {
if (e.target.files && e.target.files.length > 0) {
setFile(e.target.files[0]);
}
};
return (
<div>
<label className="block text-sm font-medium leading-6 text-gray-900">{label}</label>
<div className="mt-2 flex justify-center rounded-lg border border-dashed border-gray-900/25 px-6 py-5">
<div className="text-center">
<PhotoIcon className="mx-auto h-12 w-12 text-gray-300" aria-hidden="true" />
<div className="mt-2 flex text-sm leading-6 text-gray-600">
<label
htmlFor={id}
className="relative cursor-pointer rounded-md bg-white font-semibold text-primary focus-within:outline-none focus-within:ring-2 focus-within:ring-primary/70 focus-within:ring-offset-2"
>
<span>Upload a file</span>
<input id={id} name={name} type="file" className="sr-only" onChange={onFileChange} />
</label>
<p className="pl-1">or drag and drop</p>
</div>
</div>
</div>
{file && <p className="mt-2 text-sm text-gray-500">{file.name}</p>}
</div>
);
};
export default FileInput;

View File

@@ -0,0 +1,42 @@
import { StagedUploadsCreatePayload } from 'lib/shopify/types';
import { createStagedUploadFiles, onUploadFile } from './actions';
export const prepareFilePayload = ({
stagedFileUpload,
file
}: {
stagedFileUpload: StagedUploadsCreatePayload;
file: File;
}) => {
const formData = new FormData();
const url = stagedFileUpload.url;
stagedFileUpload.parameters.forEach(({ name, value }) => {
formData.append(name, value);
});
formData.append('file', file);
return { url, formData };
};
export const handleUploadFile = async ({ file }: { file: File }) => {
if (!file) return;
const stagedTarget = await createStagedUploadFiles({
filename: file.name,
fileSize: String(file.size),
httpMethod: 'POST',
resource: 'FILE',
mimeType: file.type
});
if (stagedTarget) {
const data = prepareFilePayload({ file, stagedFileUpload: stagedTarget });
await onUploadFile({
...data,
fileName: file.name,
resourceUrl: stagedTarget.resourceUrl
});
}
};