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
No known key found for this signature in database
GPG Key ID: CFD53CE570D42DF5
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 { 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
});
}
};

View File

@ -25,6 +25,7 @@ import {
removeFromCartMutation, removeFromCartMutation,
setCartAttributesMutation setCartAttributesMutation
} from './mutations/cart'; } from './mutations/cart';
import { createFileMutation, createStageUploads } from './mutations/file';
import { getCartQuery } from './queries/cart'; import { getCartQuery } from './queries/cart';
import { import {
getCollectionProductsQuery, getCollectionProductsQuery,
@ -50,6 +51,7 @@ import {
Collection, Collection,
Connection, Connection,
Customer, Customer,
FileCreateInput,
Filter, Filter,
Fulfillment, Fulfillment,
Image, Image,
@ -71,6 +73,7 @@ import {
ShopifyCollectionProductsOperation, ShopifyCollectionProductsOperation,
ShopifyCollectionsOperation, ShopifyCollectionsOperation,
ShopifyCreateCartOperation, ShopifyCreateCartOperation,
ShopifyCreateFileOperation,
ShopifyCustomer, ShopifyCustomer,
ShopifyCustomerOperation, ShopifyCustomerOperation,
ShopifyCustomerOrderOperation, ShopifyCustomerOrderOperation,
@ -92,9 +95,11 @@ import {
ShopifyProductsOperation, ShopifyProductsOperation,
ShopifyRemoveFromCartOperation, ShopifyRemoveFromCartOperation,
ShopifySetCartAttributesOperation, ShopifySetCartAttributesOperation,
ShopifyStagedUploadOperation,
ShopifyUpdateCartOperation, ShopifyUpdateCartOperation,
Transaction, Transaction,
TransmissionType TransmissionType,
UploadInput
} from './types'; } from './types';
const domain = process.env.SHOPIFY_STORE_DOMAIN const domain = process.env.SHOPIFY_STORE_DOMAIN
@ -1044,3 +1049,28 @@ export const getImage = async (id: string): Promise<Image> => {
return res.body.data.node.image; return res.body.data.node.image;
}; };
export const stageUploadFile = async (params: UploadInput) => {
const res = await adminFetch<ShopifyStagedUploadOperation>({
query: createStageUploads,
variables: { input: [params] }
});
return res.body.data.stagedUploadsCreate.stagedTargets;
};
export const uploadFile = async ({ url, formData }: { url: string; formData: FormData }) => {
return await fetch(url, {
method: 'POST',
body: formData
});
};
export const createFile = async (params: FileCreateInput) => {
const res = await adminFetch<ShopifyCreateFileOperation>({
query: createFileMutation,
variables: { files: [params] }
});
return res.body.data;
};

View File

@ -0,0 +1,31 @@
export const createStageUploads = /* GraphQL */ `
mutation stagedUploadsCreate($input: [StagedUploadInput!]!) {
stagedUploadsCreate(input: $input) {
stagedTargets {
url
resourceUrl
parameters {
name
value
}
}
}
}
`;
export const createFileMutation = /* GraphQL */ `
mutation fileCreate($files: [FileCreateInput!]!) {
fileCreate(files: $files) {
files {
fileStatus
... on MediaImage {
id
}
}
userErrors {
field
message
}
}
}
`;

View File

@ -783,3 +783,45 @@ export type CartAttributeInput = {
key: string; key: string;
value: string; value: string;
}; };
export type UploadInput = {
filename: string;
mimeType: string;
httpMethod: 'POST' | 'PUT';
fileSize: string;
resource: 'FILE' | 'IMAGE';
};
export type StagedUploadsCreatePayload = {
parameters: {
name: string;
value: string;
}[];
resourceUrl: string;
url: string;
};
export type ShopifyStagedUploadOperation = {
data: {
stagedUploadsCreate: {
stagedTargets: StagedUploadsCreatePayload[];
};
};
variables: { input: UploadInput[] };
};
export type FileCreateInput = {
alt: string;
contentType: 'FILE' | 'IMAGE';
originalSource: string;
};
export type ShopifyCreateFileOperation = {
data: {
fileCreate: {
files: { fileStatus: string; id: string }[];
userErrors: { code: string; field: string; message: string }[];
};
};
variables: { files: FileCreateInput[] };
};