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

@ -27,6 +27,7 @@
import Qr from '$lib/components/QR.svelte'
import AddShortenerDialog from './(component)/AddShortenerDialog.svelte'
import { toast } from 'svelte-sonner'
import ScrollArea from '$lib/components/ui/scroll-area/scroll-area.svelte'
export let data: PageData
@ -167,94 +168,96 @@
</div>
{:then shorteners}
{#if shorteners.length > 0}
<div class="flex flex-wrap gap-4 overflow-scroll p-4">
{#each shorteners as shortener}
<Card.Root class="w-full max-w-[500px]">
<Card.Header>
<Card.Title
class="flex items-center justify-between gap-2">
<div class="flex items-center gap-2">
<a
href={'https://' +
data.shortener_url +
'/' +
shortener.code}
target="_blank"
class="hover:underline">
{data.shortener_url + '/' + shortener.code}
</a>
<ExternalLink size={16} />
<ScrollArea>
<div class="flex flex-wrap gap-4 p-4">
{#each shorteners as shortener}
<Card.Root class="w-full max-w-[500px]">
<Card.Header>
<Card.Title
class="flex items-center justify-between gap-2">
<div class="flex items-center gap-2">
<a
href={'https://' +
data.shortener_url +
'/' +
shortener.code}
target="_blank"
class="hover:underline">
{data.shortener_url + '/' + shortener.code}
</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 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>
</Card.Content>
</Card.Root>
{/each}
</div>
</Card.Content>
</Card.Root>
{/each}
</div>
</ScrollArea>
{:else}
<div>No Data</div>
{/if}

Loading…
Cancel
Save