inquiry ui
This commit is contained in:
@@ -23,7 +23,7 @@
|
||||
</Dialog.Description>
|
||||
</Dialog.Header>
|
||||
|
||||
<form method="post" action="?/inquire">
|
||||
<form method="post" action="?/claim">
|
||||
<Field.Group>
|
||||
<div class="flex gap-4">
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Label } from '$lib/components/ui/label';
|
||||
import * as Field from '$lib/components/ui/field';
|
||||
import { Separator } from '$lib/components/ui/separator';
|
||||
|
||||
import TrashIcon from '@lucide/svelte/icons/trash';
|
||||
import ImageUpload from '$lib/components/custom/image-upload/image-upload.svelte';
|
||||
import { genDescription } from '$lib/db/items.remote';
|
||||
import { EMAIL_REGEX_STRING } from '$lib/consts';
|
||||
@@ -14,6 +14,9 @@
|
||||
import { Textarea } from '$lib/components/ui/textarea';
|
||||
import * as Card from '$lib/components/ui/card';
|
||||
import { dateFormatOptions } from '$lib/shared';
|
||||
import { Badge } from '$lib/components/ui/badge';
|
||||
import { deleteInquiry } from '$lib/db/inquiries.remote';
|
||||
import { invalidateAll } from '$app/navigation';
|
||||
|
||||
let { open = $bindable(), item = $bindable() }: { open: boolean, item: Item | undefined } = $props();
|
||||
|
||||
@@ -32,7 +35,7 @@
|
||||
</script>
|
||||
|
||||
<Dialog.Root bind:open>
|
||||
<Dialog.Content class="max-w-[calc(100%-2rem)] md:max-w-3xl">
|
||||
<Dialog.Content class={item?.threads ? 'max-w-[calc(100%-2rem)] md:max-w-3xl' : ''}>
|
||||
<Dialog.Header>
|
||||
<Dialog.Title>Manage Item</Dialog.Title>
|
||||
<Dialog.Description>
|
||||
@@ -122,16 +125,30 @@
|
||||
|
||||
<h2 class="text-lg leading-none font-semibold">Item inquiries:</h2>
|
||||
{#each item.threads as thread (thread)}
|
||||
<a href="/items/{item.id}/inquiries/{thread.id}" class="mt-4">
|
||||
|
||||
<Card.Root>
|
||||
<Card.Header>
|
||||
<Card.Title>Date</Card.Title>
|
||||
<Card.Content>Inquirer: {thread.messages[0].body}
|
||||
</Card.Content>
|
||||
</Card.Header>
|
||||
</Card.Root>
|
||||
</a>
|
||||
<Card.Root class="mt-4">
|
||||
<Card.Header>
|
||||
<Card.Title>{thread.createdAt.toLocaleDateString('en-US', dateFormatOptions)}
|
||||
<!--{#if thread.messages[thread.messages.length - 1].sender === 'inquirer'}-->
|
||||
<!-- t-->
|
||||
<!--{/if}-->
|
||||
</Card.Title>
|
||||
<Card.Description
|
||||
>{thread.messages[0].body}
|
||||
</Card.Description
|
||||
>
|
||||
|
||||
<Card.Action class="items-center flex gap-2">
|
||||
<a href="/items/{item.id}/inquiries/{thread.id}"
|
||||
class="{buttonVariants({variant: 'ghost'})} text-action">Reply?</a>
|
||||
<Button variant="ghost" class="text-destructive"
|
||||
onclick={() => {deleteInquiry(thread.id); invalidateAll();}}>
|
||||
<TrashIcon />
|
||||
</Button>
|
||||
</Card.Action>
|
||||
|
||||
</Card.Header>
|
||||
</Card.Root>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
|
||||
let { open = $bindable(), item }: { open: boolean, item: Item | undefined } = $props();
|
||||
|
||||
</script>
|
||||
|
||||
<Dialog.Root bind:open>
|
||||
@@ -23,7 +24,7 @@
|
||||
</Dialog.Description>
|
||||
</Dialog.Header>
|
||||
|
||||
<form method="post" action="?/inquire">
|
||||
<form method="post" action={'?/inquire&id=' + item?.id}>
|
||||
<Field.Group>
|
||||
<div class="flex gap-4">
|
||||
|
||||
@@ -53,7 +54,7 @@
|
||||
</div>
|
||||
|
||||
<Field.Field>
|
||||
<Field.Label for="description">
|
||||
<Field.Label for="inquiry">
|
||||
Please describe your inquiry <span class="text-error">*</span>
|
||||
</Field.Label>
|
||||
<Input
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
Deny
|
||||
</Button>
|
||||
{/if}
|
||||
<Button variant="ghost" class="text-edit"
|
||||
<Button variant="ghost" class="text-action"
|
||||
onclick={() => {editCallback(item)}}>
|
||||
<PencilIcon />
|
||||
Manage
|
||||
@@ -107,7 +107,7 @@
|
||||
</div>
|
||||
{:else}
|
||||
<div class="mt-2 justify-between flex">
|
||||
<Button variant="ghost" class="text-edit"
|
||||
<Button variant="ghost" class="text-action"
|
||||
onclick={() => {inquireCallback(item)}}>
|
||||
<NotebookPenIcon />
|
||||
Inquire
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</Dialog.Description>
|
||||
</Dialog.Header>
|
||||
|
||||
<form method="post" action="?/create" enctype="multipart/form-data">
|
||||
<form method="post" action="/items?/create" enctype="multipart/form-data">
|
||||
<Field.Group>
|
||||
<ImageUpload onSelect={onSelect} required />
|
||||
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ export const EXPIRE_REMINDER_DAYS = 30;
|
||||
// /(?:[a-z0-9!#$%&'*+\/=?^`\{-\}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`\{-\}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
|
||||
|
||||
const EMAIL_REGEX =
|
||||
/^(?!\.)(?!.*\.\.)([a-z0-9_'+\-.]*)[a-z0-9_'+-]@([a-z0-9][a-z0-9-]*\.)+[a-z]{2,}$/i;
|
||||
/^(?!\.)(?!.*\.\.)([a-z0-9_'+\-\.]*)[a-z0-9_'+\-]@([a-z0-9][a-z0-9\-]*\.)+[a-z]{2,}$/i;
|
||||
|
||||
// Replace single quote with HTML entity or remove it from the character class
|
||||
export const EMAIL_REGEX_STRING = EMAIL_REGEX.source.replace(/'/g, ''');
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { getRequestEvent, query } from '$app/server';
|
||||
import * as v from 'valibot';
|
||||
import sql from '$lib/db/db.server';
|
||||
import { verifyJWT } from '$lib/auth/index.server';
|
||||
|
||||
export const deleteInquiry = query(v.number(), async (id) => {
|
||||
const { cookies } = getRequestEvent();
|
||||
verifyJWT(cookies);
|
||||
|
||||
await sql`DELETE FROM inquiry_threads WHERE id = ${id};`;
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getRequestEvent, query } from '$app/server';
|
||||
import { command, getRequestEvent, query } from '$app/server';
|
||||
import * as v from 'valibot';
|
||||
import sql from '$lib/db/db.server';
|
||||
import { verifyJWT } from '$lib/auth/index.server';
|
||||
@@ -9,7 +9,7 @@ export const genDescription = query(async () => {
|
||||
return 'A matte black water bottle with a black lid and a "BKLYN BENTO" logo on the side, resting on a tree trunk in a forest.';
|
||||
});
|
||||
|
||||
export const approveDenyItem = query(
|
||||
export const approveDenyItem = command(
|
||||
v.object({ id: v.number(), approved: v.boolean() }),
|
||||
async ({ id, approved }) => {
|
||||
const { cookies } = getRequestEvent();
|
||||
|
||||
Reference in New Issue
Block a user