mirror of
https://github.com/vercel/commerce.git
synced 2025-07-22 20:26:49 +00:00
implement upload form functions
Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
38
components/form/file-input/actions.ts
Normal file
38
components/form/file-input/actions.ts
Normal 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);
|
||||
}
|
||||
};
|
42
components/form/file-input/index.tsx
Normal file
42
components/form/file-input/index.tsx
Normal 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;
|
42
components/form/file-input/utils.ts
Normal file
42
components/form/file-input/utils.ts
Normal 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
|
||||
});
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user