Skip to content

Commit

Permalink
feat: delete upload and fix minor bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
HungLV46 committed Aug 19, 2024
1 parent 6d7f753 commit 8ffc3a9
Show file tree
Hide file tree
Showing 25 changed files with 281 additions and 155 deletions.
4 changes: 2 additions & 2 deletions src/lib/apis/product/delete-product.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { config } from '$lib/public-config';

export async function deleteProduct(id: number): Promise<void> {
await fetch(`${config}/products/${id}`, {
export async function deleteProduct(id: number): Promise<Response> {
return fetch(`${config.apiEndpoint}/products/${id}`, {
method: 'DELETE',
headers: {
'Content-type': 'application/json; charset=UTF-8'
Expand Down
27 changes: 15 additions & 12 deletions src/lib/apis/user/create-user.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import { config } from '$lib/public-config';

export interface CreateProductRequest {
name: string;
owner_id: number;
avatar_img: string;
banner_img: string;
category: string;
description: string;
metadata: { previews?: string[]; cta_link?: string };
featured?: boolean;
export interface UserCreateRequest {
name?: string;
email?: string;
bio?: string;
wallet_address?: string;
banner_img?: string;
avatar_img?: string;
additional_info?: {
headline?: string;
location?: string;
socials?: { name: string; url: string }[];
wallets?: { address: string }[];
};
attributes?: { name: string; value: string }[];
collections?: { chain_id: string; contract_address: string }[];
}

export async function createProduct(data: CreateProductRequest): Promise<Response> {
return fetch(`${config.apiEndpoint}/products`, {
export async function createUser(data: UserCreateRequest): Promise<Response> {
return fetch(`${config.apiEndpoint}/users`, {
method: 'POST',
body: JSON.stringify(data),
headers: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { config } from '$lib/public-config';

export async function deleteProduct(id: number): Promise<void> {
await fetch(`${config}/products/${id}`, {
export async function deleteUser(id: number): Promise<Response> {
return fetch(`${config.apiEndpoint}/users/${id}`, {
method: 'DELETE',
headers: {
'Content-type': 'application/json; charset=UTF-8'
Expand Down
31 changes: 17 additions & 14 deletions src/lib/apis/user/get-user.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { config } from '$lib/public-config';

export interface UserGetResponseData {
id: number;
id?: number;
name?: string;
email?: string;
bio?: string;
Expand All @@ -11,26 +11,29 @@ export interface UserGetResponseData {
headline?: string;
location?: string;
socials?: { name: string; url: string }[];
wallets: { address: string }[];
};
attributes: { name: string; value: string }[];
attributes?: { name: string; value: string }[];
}

export async function getUserById(id: number): Promise<UserGetResponseData> {
const operationName = 'getUserById';

const operationsDoc = `
query getUserById($id: Int = 0) {
ipscan_ipscan_user(where: {id: {_eq: $id}}) {
id
name
email
bio
banner_img
avatar_img
additional_info
}
}
query ${operationName}($id: Int = 13) {
ipscan_ipscan_user(where: {id: {_eq: $id}}) {
id
name
email
bio
banner_img
avatar_img
additional_info
attributes {
name
value
}
}
}
`;

return fetch(config.graphqlEndpoint, {
Expand Down
10 changes: 6 additions & 4 deletions src/lib/apis/user/list-user-attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ export interface UserAttribute {
value: string;
}

export async function listUserAttributes(): Promise<ListResponse<UserAttribute>> {
export async function listUserAttributes(
includeNames: string[]
): Promise<ListResponse<UserAttribute>> {
const operationName = 'listUserAttributes';

const operationsDoc = `
query ${operationName} {
ipscan_user_attributes(distinct_on: [name, value]) {
query ${operationName}($names: [String!] = "") {
ipscan_user_attributes(distinct_on: [name, value], where: {name: {_in: $names}}) {
name
value
}
Expand All @@ -22,7 +24,7 @@ export async function listUserAttributes(): Promise<ListResponse<UserAttribute>>
method: 'POST',
body: JSON.stringify({
query: operationsDoc,
variables: {},
variables: { names: includeNames },
operationName: operationName
})
})
Expand Down
3 changes: 0 additions & 3 deletions src/lib/apis/user/list-users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ export async function listUser(
): Promise<ListWithPagingResponse<UserResponse>> {
const operationName = 'ipscanListCreators';

console.log(variables);

// TODO check query performance
const operationsDoc = `
query ${operationName}($name: String, $limit: Int = 10, $offset: Int = 0) {
Expand Down Expand Up @@ -71,7 +69,6 @@ export async function listUser(
})
.then((response) => response.json())
.then((response) => {
console.log('response', response);
const items = [];
// sum all number of collections & nfts
for (const user of response.data.ipscan_ipscan_user) {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/apis/user/update-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface UserUpdateRequest {
headline?: string;
location?: string;
socials?: { name: string; url: string }[];
wallets: { address: string }[];
wallets?: { address: string }[];
};
attributes?: { name: string; value: string }[];
}
Expand Down
6 changes: 3 additions & 3 deletions src/lib/apis/utils/upload.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// import { config } from "$lib/public-config";

import { config } from '$lib/public-config';

export async function upload(file: File) {
const formData = new FormData();
formData.append('file', file);

// TODO use config
// const response = await fetch(`${config.apiEndpoint}/upload`, {
const response = await fetch(`http://localhost:3000/upload`, {
const response = await fetch(`${config.apiEndpoint}/upload`, {
method: 'POST',
body: formData
});
Expand Down
7 changes: 5 additions & 2 deletions src/lib/ui-components/forms/image-input.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { Gallery, Input, Label, type ImgType } from 'flowbite-svelte';
import { Gallery, Helper, Input, Label, type ImgType } from 'flowbite-svelte';
import _ from 'underscore';
export let labelProps: typeof $$props | undefined = undefined;
Expand All @@ -26,7 +26,10 @@
{#if name}
<Label class="mb-1 ml-3" {...labelProps}>{name}</Label>
{/if}
<input type="hidden" name={`prev_${name}`} value={JSON.stringify(selectedFiles)} />
<input type="hidden" name={`prev_${inputProps?.name}`} value={JSON.stringify(selectedFiles)} />
<Input type="file" on:change={handleFileChange} multiple {...inputProps} />
<Helper class="mb-2 ml-3" color="red"
>{@html 'When updating, select new files will remove all existed ones'}</Helper
>
<Gallery bind:items={selectedFiles} class="grid-cols-2 gap-4 md:grid-cols-3" />
</div>
20 changes: 20 additions & 0 deletions src/routes/(sidebar)/crud/products/+page.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { deleteProduct } from '$lib/apis/product/delete-product';
import { fail, redirect } from '@sveltejs/kit';

export const actions = {
delete: async ({ request }) => {
const id = (await request.formData()).get('deleteId')?.toString();

console.log('id', id);

if (!id) return fail(400, { missingId: true });

const resposne = await deleteProduct(parseInt(id));

console.log(resposne);

if (resposne.status === 200) {
throw redirect(303, '/crud/products');
}
}
};
19 changes: 14 additions & 5 deletions src/routes/(sidebar)/crud/products/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
}
let openDelete: boolean = false;
let deleteId: string | undefined = undefined;
</script>

<MetaTag {path} {description} {title} {subtitle} />
Expand Down Expand Up @@ -97,7 +98,6 @@
<!-- Product data section -->
<Table>
<TableHead class="border-y border-gray-200 bg-gray-100 dark:border-gray-700">
<TableHeadCell class="w-4 p-4"><Checkbox /></TableHeadCell>
{#each ['Name', 'Type', 'Chain', 'Creator', 'Featured', 'Actions'] as title}
<TableHeadCell class="p-4 font-medium">{title}</TableHeadCell>
{/each}
Expand All @@ -106,8 +106,6 @@
<TableBody>
{#each data.items as product}
<TableBodyRow class="text-base">
<TableBodyCell class="w-4 p-4"><Checkbox /></TableBodyCell>

<TableBodyCell class="mr-12 flex items-center space-x-6 whitespace-nowrap p-4">
<Avatar src={product.avatar_img} />
<div class="text-sm font-normal text-gray-500 dark:text-gray-400">
Expand Down Expand Up @@ -152,7 +150,15 @@
<Button color="blue" size="sm" class="gap-2 px-3" href="/crud/products/{product.id}">
<EyeOutline size="sm" /> View
</Button>
<Button color="red" size="sm" class="gap-2 px-3">
<Button
color="red"
size="sm"
class="gap-2 px-3"
on:click={() => {
openDelete = true;
deleteId = product.id;
}}
>
<TrashBinSolid size="sm" /> Delete
</Button>
</TableBodyCell>
Expand All @@ -170,4 +176,7 @@
}}
/>

<Delete bind:open={openDelete} />
<form method="POST" action="?/delete">
<input name="deleteId" type="hidden" bind:value={deleteId} />
<Delete bind:open={openDelete} />
</form>
3 changes: 2 additions & 1 deletion src/routes/(sidebar)/crud/products/Delete.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts">
import { enhance } from '$app/forms';
import { Button, Modal } from 'flowbite-svelte';
import { ExclamationCircleOutline } from 'flowbite-svelte-icons';
export let open: boolean = false; // modal control
Expand All @@ -12,7 +13,7 @@
</h3>

<div class="flex items-center justify-center">
<Button href="/" color="red" class="mr-2">Yes, I'm sure</Button>
<Button type="submit" color="red" class="mr-2">Yes, I'm sure</Button>
<Button color="alternative" on:click={() => (open = false)}>No, cancel</Button>
</div>
</Modal>
10 changes: 8 additions & 2 deletions src/routes/(sidebar)/crud/products/Product.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
let openDelete: boolean = false;
$: isViewMode = mode === PAGE_MODE.VIEW || form?.reload;
let deleteId: string | undefined = undefined;
</script>

<MetaTag {path} {description} {title} {subtitle} />
Expand All @@ -47,7 +49,7 @@
{#if form?.reload}
{window.location.reload()}
{/if}
<form method="POST" enctype="multipart/form-data" use:enhance>
<form method="POST" action="?/upsert" enctype="multipart/form-data" use:enhance>
<main class="relative h-full w-full overflow-y-auto bg-white dark:bg-gray-800">
<div class="mt-10 p-4">
{#if form?.error}
Expand Down Expand Up @@ -117,6 +119,7 @@
size="sm"
class="w-36 gap-2 px-3"
on:click={() => {
deleteId = data.product.id?.toString();
openDelete = true;
}}
>
Expand Down Expand Up @@ -271,4 +274,7 @@
</main>
</form>

<Delete bind:open={openDelete} />
<form method="POST" action="?/delete">
<input name="deleteId" type="hidden" bind:value={deleteId} />
<Delete bind:open={openDelete} />
</form>
33 changes: 25 additions & 8 deletions src/routes/(sidebar)/crud/products/[id]/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { deleteProduct } from '$lib/apis/product/delete-product';
import { updateProduct } from '$lib/apis/product/update-product.js';
import { upload } from '$lib/apis/utils/upload';
import { PAGE_MODE } from '$lib/constants.js';
import { fail } from '@sveltejs/kit';
import { fail, redirect } from '@sveltejs/kit';

export const actions = {
default: async ({ params, request }) => {
upsert: async ({ params, request }) => {
const id = parseInt(params.id);
const data = await request.formData();

console.log('form data', data);
console.log('form', data);

let banner = data.get('banner_img') as File;
let avatar = data.get('avatar_img') as File;
Expand All @@ -32,8 +33,11 @@ export const actions = {
metadata: {
previews: uploadedFiles[2]
? uploadedFiles.slice(2).map((file) => file?.data.s3_url as string)
: undefined,
cta_url: data.get('cta_url')?.toString()
: JSON.parse(data.get('prev_previews')?.toString() || '[]').map(
(img: { src: string }) => img.src
),
cta_url: data.get('cta_url')?.toString(),
socials: JSON.parse(data.get('socials')?.toString() || '[]')
},
attributes: [
...JSON.parse(data.get('statuses')?.toString() || '[]').map((value: string) => ({
Expand All @@ -55,19 +59,32 @@ export const actions = {
]
};

console.log('requestData', requestData);
console.log('request', requestData);

const updateResponse = await updateProduct(id, requestData);

const responseData = await updateResponse.json();

console.log('responseData', responseData); // TODO remove

if (updateResponse.status === 200) {
// TODO find a more systematical way to reload a page
return fail(responseData.statusCode, { reload: true, mode: PAGE_MODE.VIEW });
} else {
return fail(responseData.statusCode, responseData);
}
},
delete: async ({ request }) => {
const id = (await request.formData()).get('deleteId')?.toString();

console.log('id', id);

if (!id) return fail(400, { missingId: true });

const resposne = await deleteProduct(parseInt(id));

console.log(resposne);

if (resposne.status === 200) {
throw redirect(303, '/crud/products');
}
}
};
Loading

0 comments on commit 8ffc3a9

Please sign in to comment.