update links page to use scrollarea component

pull/3/head
TZGyn 2 years ago
parent a177b5d22d
commit 0ebd62f3bd
Signed by: TZGyn
GPG Key ID: 122EAF77AE81FD4A

Binary file not shown.

@ -36,7 +36,7 @@
"dependencies": { "dependencies": {
"@types/he": "^1.2.3", "@types/he": "^1.2.3",
"apexcharts": "^3.44.0", "apexcharts": "^3.44.0",
"bits-ui": "^0.19.6", "bits-ui": "^0.19.7",
"clsx": "^2.0.0", "clsx": "^2.0.0",
"cmdk-sv": "^0.0.13", "cmdk-sv": "^0.0.13",
"drizzle-orm": "^0.29.0", "drizzle-orm": "^0.29.0",

@ -0,0 +1,10 @@
import { default as Scrollbar } from "./scroll-area-scrollbar.svelte";
import { default as Root } from "./scroll-area.svelte";
export {
Root,
Scrollbar,
//,
Root as ScrollArea,
Scrollbar as ScrollAreaScrollbar,
};

@ -0,0 +1,27 @@
<script lang="ts">
import { ScrollArea as ScrollAreaPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
type $$Props = ScrollAreaPrimitive.ScrollbarProps & {
orientation?: "vertical" | "horizontal";
};
let className: $$Props["class"] = undefined;
export let orientation: $$Props["orientation"] = "vertical";
export { className as class };
</script>
<ScrollAreaPrimitive.Scrollbar
{orientation}
class={cn(
"flex touch-none select-none transition-colors",
orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-px",
orientation === "horizontal" && "h-2.5 w-full border-t border-t-transparent p-px",
className
)}
>
<slot />
<ScrollAreaPrimitive.Thumb
class={cn("relative rounded-full bg-border", orientation === "vertical" && "flex-1")}
/>
</ScrollAreaPrimitive.Scrollbar>

@ -0,0 +1,32 @@
<script lang="ts">
import { ScrollArea as ScrollAreaPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
import { Scrollbar } from "./index.js";
type $$Props = ScrollAreaPrimitive.Props & {
orientation?: "vertical" | "horizontal" | "both";
scrollbarXClasses?: string;
scrollbarYClasses?: string;
};
let className: $$Props["class"] = undefined;
export { className as class };
export let orientation = "vertical";
export let scrollbarXClasses: string = "";
export let scrollbarYClasses: string = "";
</script>
<ScrollAreaPrimitive.Root {...$$restProps} class={cn("relative overflow-hidden", className)}>
<ScrollAreaPrimitive.Viewport class="h-full w-full rounded-[inherit]">
<ScrollAreaPrimitive.Content>
<slot />
</ScrollAreaPrimitive.Content>
</ScrollAreaPrimitive.Viewport>
{#if orientation === "vertical" || orientation === "both"}
<Scrollbar orientation="vertical" class={scrollbarYClasses} />
{/if}
{#if orientation === "horizontal" || orientation === "both"}
<Scrollbar orientation="horizontal" class={scrollbarXClasses} />
{/if}
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>

@ -19,7 +19,8 @@
} }
</script> </script>
<div class="flex h-screen w-full flex-col"> <div
class="max-w-screen flex h-screen max-h-screen w-full flex-col overflow-hidden">
<div class="flex border-b"> <div class="flex border-b">
<div <div
class="flex h-20 w-full items-center justify-between gap-6 p-4"> class="flex h-20 w-full items-center justify-between gap-6 p-4">
@ -59,61 +60,59 @@
</div> </div>
</div> </div>
<div class="flex h-full"> <div
<Sidebar class="hidden lg:flex" /> class="block w-full border-b bg-background px-4 py-2 lg:hidden">
<div <Sheet.Root bind:open={sheetOpen}>
class="flex h-full max-h-screen w-full flex-col overflow-hidden"> <Sheet.Trigger asChild let:builder>
<div <Button builders={[builder]} variant="ghost" class="p-2">
class="block w-full border-b bg-background px-4 py-2 lg:hidden"> <Menu />
<Sheet.Root bind:open={sheetOpen}> </Button>
<Sheet.Trigger asChild let:builder> </Sheet.Trigger>
<Button builders={[builder]} variant="ghost" class="p-2"> <Sheet.Content side="left" class="flex flex-col">
<Menu /> <Sheet.Header class="pb-16">
</Button> <Sheet.Title>Shortener</Sheet.Title>
</Sheet.Trigger> </Sheet.Header>
<Sheet.Content side="left" class="flex flex-col"> <div class="flex grow flex-col gap-4">
<Sheet.Header class="pb-16"> <Button
<Sheet.Title>Shortener</Sheet.Title> on:click={closeSheet}
</Sheet.Header> variant="ghost"
<div class="flex grow flex-col gap-4"> href="/"
<Button class="justify-start text-base">Home</Button>
on:click={closeSheet} <Button
variant="ghost" on:click={closeSheet}
href="/" variant="ghost"
class="justify-start text-base">Home</Button> href="/links"
<Button class="justify-start text-base">Links</Button>
on:click={closeSheet} <Button
variant="ghost" on:click={closeSheet}
href="/links" variant="ghost"
class="justify-start text-base">Links</Button> href="/projects"
<Button class="justify-start text-base ">Projects</Button>
on:click={closeSheet} <Button
variant="ghost" on:click={closeSheet}
href="/projects" variant="ghost"
class="justify-start text-base ">Projects</Button> href="/settings"
<Button class="justify-start text-base ">Settings</Button>
on:click={closeSheet} </div>
variant="ghost" <div class="flex flex-col justify-between">
href="/settings" <div></div>
class="justify-start text-base ">Settings</Button> <div class="flex flex-col gap-4">
<Separator />
<div class="flex items-center justify-between">
<UserIcon
email={data.user.email}
onClick={closeSheet} />
</div> </div>
<div class="flex flex-col justify-between"> </div>
<div></div> </div>
<div class="flex flex-col gap-4"> </Sheet.Content>
<Separator /> </Sheet.Root>
<div class="flex items-center justify-between"> </div>
<UserIcon
email={data.user.email} <div class="flex flex-grow overflow-hidden">
onClick={closeSheet} /> <Sidebar class="hidden lg:flex" />
</div> <div class="flex h-auto w-full flex-col">
</div> <slot />
</div>
</Sheet.Content>
</Sheet.Root>
</div>
<div class="flex h-full w-full flex-col overflow-hidden">
<slot />
</div>
</div> </div>
</div> </div>
</div> </div>

@ -27,6 +27,7 @@
import Qr from '$lib/components/QR.svelte' import Qr from '$lib/components/QR.svelte'
import AddShortenerDialog from './(component)/AddShortenerDialog.svelte' import AddShortenerDialog from './(component)/AddShortenerDialog.svelte'
import { toast } from 'svelte-sonner' import { toast } from 'svelte-sonner'
import ScrollArea from '$lib/components/ui/scroll-area/scroll-area.svelte'
export let data: PageData export let data: PageData
@ -167,94 +168,96 @@
</div> </div>
{:then shorteners} {:then shorteners}
{#if shorteners.length > 0} {#if shorteners.length > 0}
<div class="flex flex-wrap gap-4 overflow-scroll p-4"> <ScrollArea>
{#each shorteners as shortener} <div class="flex flex-wrap gap-4 p-4">
<Card.Root class="w-full max-w-[500px]"> {#each shorteners as shortener}
<Card.Header> <Card.Root class="w-full max-w-[500px]">
<Card.Title <Card.Header>
class="flex items-center justify-between gap-2"> <Card.Title
<div class="flex items-center gap-2"> class="flex items-center justify-between gap-2">
<a <div class="flex items-center gap-2">
href={'https://' + <a
data.shortener_url + href={'https://' +
'/' + data.shortener_url +
shortener.code} '/' +
target="_blank" shortener.code}
class="hover:underline"> target="_blank"
{data.shortener_url + '/' + shortener.code} class="hover:underline">
</a> {data.shortener_url + '/' + shortener.code}
<ExternalLink size={16} /> </a>
<ExternalLink size={16} />
</div>
<div class="flex gap-4">
<Badge variant="outline" class="flex gap-2">
{#if shortener.active}
<span
class="relative inline-flex h-2 w-2 rounded-full bg-green-400"
></span>
Active
{:else}
<span
class="relative inline-flex h-2 w-2 rounded-full bg-gray-600"
></span>
Inactive
{/if}
</Badge>
<Badge variant="secondary"
>{shortener.project
? shortener.project.name
: 'Uncategorized'}</Badge>
</div>
</Card.Title>
<Card.Description>{shortener.link}</Card.Description>
</Card.Header>
<Card.Content>
<div class="flex items-center justify-between">
<div class="flex gap-2">
<Button
href={`/links/${shortener.code}`}
class="flex h-8 items-center justify-center gap-1 rounded bg-secondary text-sm">
<BarChart size={20} />
<div>
{shortener.visitor.length} visits
</div>
</Button>
<Button
class="flex h-8 items-center justify-center gap-1 rounded bg-secondary text-sm"
on:click={() => openQRDialog(shortener.code)}>
<QrCode size={20} />
</Button>
</div>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<MoreVertical />
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Group>
<DropdownMenu.Item
on:click={() =>
openEditDialog(
shortener.code,
shortener.link,
shortener.projectId,
shortener.project?.name,
shortener.active,
)}>
Edit
</DropdownMenu.Item>
<DropdownMenu.Item
on:click={() =>
openDeleteDialog(shortener.code)}
class="text-destructive data-[highlighted]:bg-destructive">
Delete
</DropdownMenu.Item>
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Root>
</div> </div>
<div class="flex gap-4"> </Card.Content>
<Badge variant="outline" class="flex gap-2"> </Card.Root>
{#if shortener.active} {/each}
<span </div>
class="relative inline-flex h-2 w-2 rounded-full bg-green-400" </ScrollArea>
></span>
Active
{:else}
<span
class="relative inline-flex h-2 w-2 rounded-full bg-gray-600"
></span>
Inactive
{/if}
</Badge>
<Badge variant="secondary"
>{shortener.project
? shortener.project.name
: 'Uncategorized'}</Badge>
</div>
</Card.Title>
<Card.Description>{shortener.link}</Card.Description>
</Card.Header>
<Card.Content>
<div class="flex items-center justify-between">
<div class="flex gap-2">
<Button
href={`/links/${shortener.code}`}
class="flex h-8 items-center justify-center gap-1 rounded bg-secondary text-sm">
<BarChart size={20} />
<div>
{shortener.visitor.length} visits
</div>
</Button>
<Button
class="flex h-8 items-center justify-center gap-1 rounded bg-secondary text-sm"
on:click={() => openQRDialog(shortener.code)}>
<QrCode size={20} />
</Button>
</div>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<MoreVertical />
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Group>
<DropdownMenu.Item
on:click={() =>
openEditDialog(
shortener.code,
shortener.link,
shortener.projectId,
shortener.project?.name,
shortener.active,
)}>
Edit
</DropdownMenu.Item>
<DropdownMenu.Item
on:click={() =>
openDeleteDialog(shortener.code)}
class="text-destructive data-[highlighted]:bg-destructive">
Delete
</DropdownMenu.Item>
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Root>
</div>
</Card.Content>
</Card.Root>
{/each}
</div>
{:else} {:else}
<div>No Data</div> <div>No Data</div>
{/if} {/if}

Loading…
Cancel
Save