first init

This commit is contained in:
ISMAIL MASSERAN
2026-06-08 11:37:14 +08:00
commit 94ecbe5887
1058 changed files with 87732 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+235
View File
@@ -0,0 +1,235 @@
<script lang="ts" setup>
import _ from 'lodash'
import fakers from '@/utils/faker'
import { AvatarRoot, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Box } from '@/components/ui/box'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Lucide } from '@/components/ui/lucide'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import {
TooltipRoot,
TooltipTrigger,
TooltipPositioner,
TooltipContent,
} from '@/components/ui/tooltip'
</script>
<template>
<div class="flex flex-col items-center sm:flex-row">
<h2 class="mr-auto text-lg font-medium">Blog Layout</h2>
<div class="mt-4 flex w-full sm:mt-0 sm:w-auto">
<Button look="outline" class="mr-2 shadow-sm" variant="primary"> Add New Post </Button>
<MenuRoot class="w-auto ml-auto sm:ml-0">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="share">
<Lucide class="mr-2 size-4" icon="Share" /> Share Post
</MenuItem>
<MenuItem value="download">
<Lucide class="mr-2 size-4" icon="Download" /> Download Post
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
</div>
<div class="mt-5 grid grid-cols-12 gap-x-6 gap-y-8">
<!-- BEGIN: Blog Layout -->
<template v-for="(faker, fakerKey) in _.take(fakers, 9)" :key="fakerKey">
<Box class="col-span-12 p-0 md:col-span-6 xl:col-span-4">
<div class="flex items-center border-b border-foreground/15 px-5 py-4">
<AvatarRoot class="size-10 rounded-full">
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="faker.photos[0]" alt="avatar" />
</AvatarRoot>
<div class="ml-3 mr-auto">
<a class="font-medium" href="">
{{ faker.users[0]?.name }}
</a>
<div class="mt-0.5 flex truncate text-xs opacity-70">
<a class="text-primary inline-block truncate" href="">
{{ faker.products[0]?.category }}
</a>
<span class="mx-1"></span> {{ faker.formattedTimes[0] }}
</div>
</div>
<MenuRoot class="w-auto ml-3">
<MenuTrigger as-child>
<a href="#">
<Lucide class="size-5 opacity-70" icon="MoreVertical" />
</a>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="edit">
<Lucide class="mr-2 size-4" icon="Edit" /> Edit Post
</MenuItem>
<MenuItem value="delete">
<Lucide class="mr-2 size-4" icon="Trash" /> Delete Post
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
<div class="p-5">
<div class="image-fit h-40 2xl:h-56">
<img
class="rounded-md"
:src="faker.images[0]"
alt="Midone - Tailwind Admin Dashboard Template"
/>
</div>
<a class="mt-5 block text-base font-medium" href="">
{{ faker.news[0]?.title }}
</a>
<div class="mt-2 text-foreground/70">
{{ faker.news[0]?.shortContent }}
</div>
</div>
<div class="flex items-center border-t border-foreground/15 px-5 py-3">
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="bg-foreground/5 mr-2 flex size-8 items-center justify-center rounded-full border border-foreground/15"
href=""
>
<Lucide class="size-3" icon="Bookmark" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Bookmark</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
<div class="mr-2 flex">
<AvatarRoot
class="bg-background size-8 rounded-full"
:title="`Uploaded at ${faker.dates[0]}`"
>
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="faker.images[0]" alt="avatar" />
</AvatarRoot>
<AvatarRoot
class="bg-background -ml-4 size-8 rounded-full"
:title="`Uploaded at ${faker.dates[1]}`"
>
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="faker.images[1]" alt="avatar" />
</AvatarRoot>
<AvatarRoot
class="bg-background -ml-4 size-8 rounded-full"
:title="`Uploaded at ${faker.dates[2]}`"
>
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="faker.images[2]" alt="avatar" />
</AvatarRoot>
</div>
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="bg-primary/10 border-primary/20 text-primary ml-auto flex size-8 items-center justify-center rounded-full border"
href=""
>
<Lucide class="size-3" icon="Share" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Share</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="bg-primary ml-2 flex size-8 items-center justify-center rounded-full text-white"
href=""
>
<Lucide class="size-3" icon="Share" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Download PDF</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
</div>
<div class="border-t border-foreground/15 px-5 pb-5 pt-3">
<div class="flex w-full text-xs opacity-70 sm:text-sm">
<div class="mr-2">
Comments:
<span class="font-medium">{{ faker.totals[0] }}</span>
</div>
<div class="mr-2">
Views: <span class="font-medium">{{ faker.totals[1] }}k</span>
</div>
<div class="ml-auto">
Likes: <span class="font-medium">{{ faker.totals[2] }}k</span>
</div>
</div>
<div class="mt-3 flex w-full items-center">
<AvatarRoot class="mr-3 size-10 rounded-full">
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="faker.photos[0]" alt="avatar" />
</AvatarRoot>
<div class="relative flex-1">
<Input class="rounded-full" type="text" placeholder="Post a comment..." />
<Lucide
class="absolute inset-y-0 right-0 my-auto mr-3 size-4 opacity-70"
icon="Smile"
/>
</div>
</div>
</div>
</Box>
</template>
<!-- END: Blog Layout -->
<!-- BEGIN: Pagination -->
<div class="col-span-12 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="5000"
:pageSize="10"
:siblingCount="2"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>
<Lucide class="size-4" icon="ChevronLeft" />
</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>
<Lucide class="size-4" icon="ChevronRight" />
</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="box mt-3 w-20 sm:mt-0">
<NativeSelectOption>10</NativeSelectOption>
<NativeSelectOption>25</NativeSelectOption>
<NativeSelectOption>35</NativeSelectOption>
<NativeSelectOption>50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
</template>
+239
View File
@@ -0,0 +1,239 @@
<script lang="ts" setup>
import _ from 'lodash'
import fakers from '@/utils/faker'
import { AvatarRoot, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Box } from '@/components/ui/box'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Lucide } from '@/components/ui/lucide'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import {
TooltipRoot,
TooltipTrigger,
TooltipPositioner,
TooltipContent,
} from '@/components/ui/tooltip'
</script>
<template>
<div class="flex flex-col items-center sm:flex-row">
<h2 class="mr-auto text-lg font-medium">Blog Layout</h2>
<div class="mt-4 flex w-full sm:mt-0 sm:w-auto">
<Button look="outline" class="mr-2 shadow-sm" variant="primary"> Add New Post </Button>
<MenuRoot class="w-auto ml-auto sm:ml-0">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="share">
<Lucide class="mr-2 size-4" icon="Share" /> Share Post
</MenuItem>
<MenuItem value="download">
<Lucide class="mr-2 size-4" icon="Download" /> Download Post
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
</div>
<div class="mt-5 grid grid-cols-12 gap-6">
<!-- BEGIN: Blog Layout -->
<template v-for="(faker, fakerKey) in _.take(fakers, 6)" :key="fakerKey">
<Box class="col-span-12 p-0 md:col-span-6">
<div
class="image-fit h-[320px] before:absolute before:left-0 before:top-0 before:z-10 before:block before:h-full before:w-full before:rounded-t-xl before:bg-gradient-to-t before:from-black/90 before:to-black/10"
>
<img
class="rounded-t-xl"
:src="faker.images[0]"
alt="Midone - Tailwind Admin Dashboard Template"
/>
<div class="absolute z-10 flex w-full items-center px-5 pt-6">
<AvatarRoot class="size-10 rounded-full border-2 border-white">
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="faker.photos[0]" alt="avatar" />
</AvatarRoot>
<div class="ml-3 mr-auto text-white">
<a class="font-medium" href="">
{{ faker.users[0]?.name }}
</a>
<div class="mt-0.5 text-xs">
{{ faker.formattedTimes[0] }}
</div>
</div>
<MenuRoot class="w-auto ml-3">
<MenuTrigger as-child>
<a
class="flex size-8 items-center justify-center rounded-full bg-white/20"
href="#"
>
<Lucide class="size-4 text-white" icon="MoreVertical" />
</a>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="edit">
<Lucide class="mr-2 size-4" icon="Edit" /> Edit Post
</MenuItem>
<MenuItem value="delete">
<Lucide class="mr-2 size-4" icon="Trash" /> Delete Post
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
<div class="absolute bottom-0 z-10 px-5 pb-6 text-white">
<span class="rounded-lg bg-white/20 px-2 py-1">
{{ faker.products[0]?.category }}
</span>
<a class="mt-3 block text-xl font-medium" href="">
{{ faker.news[0]?.title }}
</a>
</div>
</div>
<div class="p-5 opacity-70">
{{ faker.news[0]?.shortContent }}
</div>
<div class="flex items-center border-t border-foreground/15 px-5 py-3">
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="bg-foreground/5 mr-2 flex size-8 items-center justify-center rounded-full border border-foreground/15"
href=""
>
<Lucide class="size-3" icon="Bookmark" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Bookmark</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
<div class="mr-2 flex">
<AvatarRoot
class="bg-background size-8 rounded-full"
:title="`Uploaded at ${faker.dates[0]}`"
>
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="faker.images[0]" alt="avatar" />
</AvatarRoot>
<AvatarRoot
class="bg-background -ml-4 size-8 rounded-full"
:title="`Uploaded at ${faker.dates[1]}`"
>
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="faker.images[1]" alt="avatar" />
</AvatarRoot>
<AvatarRoot
class="bg-background -ml-4 size-8 rounded-full"
:title="`Uploaded at ${faker.dates[2]}`"
>
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="faker.images[2]" alt="avatar" />
</AvatarRoot>
</div>
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="bg-primary/10 border-primary/20 text-primary ml-auto flex size-8 items-center justify-center rounded-full border"
href=""
>
<Lucide class="size-3" icon="Share" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Share</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="bg-primary ml-2 flex size-8 items-center justify-center rounded-full text-white"
href=""
>
<Lucide class="size-3" icon="Share" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Download PDF</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
</div>
<div class="border-t border-foreground/15 px-5 pb-5 pt-3">
<div class="flex w-full text-xs opacity-70 sm:text-sm">
<div class="mr-2">
Comments:
<span class="font-medium">{{ faker.totals[0] }}</span>
</div>
<div class="mr-2">
Views: <span class="font-medium">{{ faker.totals[1] }}k</span>
</div>
<div class="ml-auto">
Likes: <span class="font-medium">{{ faker.totals[2] }}k</span>
</div>
</div>
<div class="mt-3 flex w-full items-center">
<AvatarRoot class="mr-3 size-10 rounded-full">
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="faker.photos[0]" alt="avatar" />
</AvatarRoot>
<div class="relative flex-1">
<Input class="rounded-full" type="text" placeholder="Post a comment..." />
<Lucide
class="absolute inset-y-0 right-0 my-auto mr-3 size-4 opacity-70"
icon="Smile"
/>
</div>
</div>
</div>
</Box>
</template>
<!-- END: Blog Layout -->
<!-- BEGIN: Pagination -->
<div class="col-span-12 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="5000"
:pageSize="10"
:siblingCount="2"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>
<Lucide class="size-4" icon="ChevronLeft" />
</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>
<Lucide class="size-4" icon="ChevronRight" />
</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="box mt-3 w-20 sm:mt-0">
<NativeSelectOption>10</NativeSelectOption>
<NativeSelectOption>25</NativeSelectOption>
<NativeSelectOption>35</NativeSelectOption>
<NativeSelectOption>50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
</template>
+236
View File
@@ -0,0 +1,236 @@
<script lang="ts" setup>
import fakers from '@/utils/faker'
import { AvatarRoot, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Box } from '@/components/ui/box'
import { Lucide } from '@/components/ui/lucide'
import { Textarea } from '@/components/ui/textarea'
import {
TooltipRoot,
TooltipTrigger,
TooltipPositioner,
TooltipContent,
} from '@/components/ui/tooltip'
</script>
<template>
<Box class="p-5 xl:w-3/5">
<!-- BEGIN: Blog Layout -->
<h2 class="text-xl font-medium sm:text-2xl">
{{ fakers[0]?.news[0]?.title }}
</h2>
<div class="mt-2 text-xs opacity-70 sm:text-sm">
{{ fakers[0]?.dates[0] }} <span class="mx-1"></span>
<a class="text-primary" href="">
{{ fakers[0]?.products[0]?.category }}
</a>
<span class="mx-1"></span> 7 Min read
</div>
<div class="mt-6">
<div class="image-fit h-[250px]">
<img
class="rounded-xl"
:src="fakers[0]?.images[0]"
alt="Midone - Tailwind Admin Dashboard Template"
/>
</div>
</div>
<div class="relative flex items-center gap-3 pb-6 pt-16 sm:pt-6">
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="bg-foreground/5 flex size-8 flex-none items-center justify-center rounded-full border border-foreground/15 sm:size-10"
href=""
>
<Lucide class="size-3" icon="Bookmark" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Bookmark</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
<div class="flex">
<AvatarRoot
class="bg-background size-8 sm:size-10 rounded-full"
:title="`Uploaded at ${fakers[0]?.dates[0]}`"
>
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="fakers[0]?.photos[0]" alt="avatar" />
</AvatarRoot>
<AvatarRoot
class="bg-background -ml-4 size-8 sm:size-10 rounded-full"
:title="`Uploaded at ${fakers[0]?.dates[1]}`"
>
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="fakers[0]?.photos[1]" alt="avatar" />
</AvatarRoot>
<AvatarRoot
class="bg-background -ml-4 size-8 sm:size-10 rounded-full"
:title="`Uploaded at ${fakers[0]?.dates[2]}`"
>
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="fakers[0]?.photos[2]" alt="avatar" />
</AvatarRoot>
</div>
<div
class="absolute -mt-12 flex w-full gap-3 text-xs opacity-70 sm:relative sm:mt-0 sm:text-sm"
>
<div class="mr-1">
Comments:
<span class="font-medium">{{ fakers[0]?.totals[0] }}</span>
</div>
<div class="mr-1">
Views:
<span class="font-medium">{{ fakers[0]?.totals[1] }}k</span>
</div>
<div class="ml-auto">
Likes:
<span class="font-medium">{{ fakers[0]?.totals[2] }}k</span>
</div>
</div>
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="bg-primary/10 border-primary/20 text-primary ml-auto flex size-8 flex-none items-center justify-center rounded-full border sm:size-10"
href=""
>
<Lucide class="size-3" icon="Share" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Share</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="bg-primary -ml-1 flex size-8 flex-none items-center justify-center rounded-full text-white sm:size-10"
href=""
>
<Lucide class="size-3" icon="Download" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Download PDF</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
</div>
<div class="text-justify indent-8">
<p class="mb-5">{{ fakers[1]?.news[0]?.content }}</p>
<p class="mb-5">{{ fakers[2]?.news[0]?.content }}</p>
<p>{{ fakers[3]?.news[0]?.content }}</p>
</div>
<div
class="mt-5 flex flex-col items-center border-t border-foreground/10 pt-5 text-xs sm:flex-row sm:text-sm"
>
<div class="flex items-center">
<AvatarRoot class="size-12 rounded-full">
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="fakers[0]?.photos[0]" alt="avatar" />
</AvatarRoot>
<div class="ml-3.5 mr-auto">
<a class="font-medium" href="">
{{ fakers[0]?.users[0]?.name }}
</a>
<div class="mt-0.5 text-xs opacity-70">Senior Frontend Engineer</div>
</div>
</div>
<div class="mt-5 flex items-center gap-2 sm:ml-auto sm:mt-0">
<div class="mr-1">Share this post:</div>
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="flex size-8 items-center justify-center rounded-full border border-foreground/15 sm:size-10"
href=""
>
<Lucide class="size-3 fill-current opacity-70" icon="Facebook" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Facebook</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="flex size-8 items-center justify-center rounded-full border border-foreground/15 sm:size-10"
href=""
>
<Lucide class="size-3 fill-current opacity-70" icon="Twitter" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Twitter</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="flex size-8 items-center justify-center rounded-full border border-foreground/15 sm:size-10"
href=""
>
<Lucide class="size-3 fill-current opacity-70" icon="Linkedin" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Linked In</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
</div>
</div>
<!-- END: Blog Layout -->
<!-- BEGIN: Comments -->
<div class="mt-5 border-t border-foreground/10 pt-5">
<div class="text-base font-medium">2 Responses</div>
<div class="h-18 relative mt-5">
<Lucide
class="absolute inset-y-0 left-0 my-auto ml-6 size-5 opacity-50 z-10"
icon="MessageCircle"
/>
<Textarea class="min-h-24 pl-16 pt-6" placeholder="Post a comment..."></Textarea>
</div>
</div>
<div class="mt-5 pb-8">
<div class="pt-5">
<div class="flex">
<AvatarRoot class="size-10 sm:size-12 rounded-full">
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="fakers[0]?.photos[1]" alt="avatar" />
</AvatarRoot>
<div class="ml-3.5 flex-1">
<div class="flex items-center">
<a class="font-medium" href="">
{{ fakers[0]?.users[1]?.name }}
</a>
<a class="ml-auto text-xs opacity-70" href=""> Reply </a>
</div>
<div class="mt-0.5 text-xs opacity-70">
{{ fakers[0]?.formattedTimes[1] }}
</div>
<div class="mt-2">{{ fakers[0]?.news[1]?.shortContent }}</div>
</div>
</div>
</div>
<div class="mt-5 border-t border-foreground/10 pt-5">
<div class="flex">
<AvatarRoot class="size-10 sm:size-12 rounded-full">
<AvatarFallback>PA</AvatarFallback>
<AvatarImage :src="fakers[0]?.photos[2]" alt="avatar" />
</AvatarRoot>
<div class="ml-3.5 flex-1">
<div class="flex items-center">
<a class="font-medium" href="">
{{ fakers[0]?.users[2]?.name }}
</a>
<a class="ml-auto text-xs opacity-70" href=""> Reply </a>
</div>
<div class="mt-0.5 text-xs opacity-70">
{{ fakers[0]?.formattedTimes[2] }}
</div>
<div class="mt-2">{{ fakers[0]?.news[2]?.shortContent }}</div>
</div>
</div>
</div>
</div>
<!-- END: Comments -->
</Box>
</template>
+203
View File
@@ -0,0 +1,203 @@
<script lang="ts" setup>
import { ref } from 'vue'
import fakers from '@/utils/faker'
import { AvatarRoot, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Box } from '@/components/ui/box'
import { Button } from '@/components/ui/button'
import { DialogRoot, DialogContent, DialogCloseTrigger } from '@/components/ui/dialog'
import { Input } from '@/components/ui/input'
import { Lucide } from '@/components/ui/lucide'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import {
Table,
TableHeader,
TableBody,
TableHead,
TableRow,
TableCell,
} from '@/components/ui/table'
const deleteConfirmationOpen = ref(false)
</script>
<template>
<div>
<h2 class="text-lg font-medium">Categories</h2>
<div class="mt-5 grid grid-cols-12 gap-6">
<div class="col-span-12 mt-2 flex flex-wrap items-center sm:flex-nowrap">
<Button class="mr-2" look="outline" variant="primary"> Add New Category </Button>
<MenuRoot class="w-auto">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="print">
<Lucide class="mr-2 h-4 w-4" icon="Printer" /> Print
</MenuItem>
<MenuItem value="excel">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to Excel
</MenuItem>
<MenuItem value="pdf">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to PDF
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
<div class="mx-auto hidden opacity-70 md:block">Showing 1 to 10 of 150 entries</div>
<div class="mt-3 w-full sm:ml-auto sm:mt-0 sm:w-auto md:ml-0">
<div class="relative w-56">
<Input class="w-56 pr-10" type="text" placeholder="Search..." />
<Lucide class="absolute inset-y-0 right-0 my-auto mr-3 h-4 w-4" icon="Search" />
</div>
</div>
</div>
<!-- BEGIN: Data List -->
<div class="col-span-12 overflow-auto lg:overflow-visible">
<Table class="-mt-2" variant="boxed">
<TableHeader>
<TableRow>
<TableHead> IMAGES </TableHead>
<TableHead> CATEGORY NAME </TableHead>
<TableHead> SLUG </TableHead>
<TableHead class="text-center"> STATUS </TableHead>
<TableHead class="text-center"> ACTIONS </TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow v-for="(faker, index) in fakers.slice(0, 9)" :key="index">
<TableCell>
<div class="flex">
<AvatarRoot class="size-11 bg-background rounded-full">
<AvatarFallback>IM</AvatarFallback>
<AvatarImage
:src="faker['images'][0]"
:alt="'Uploaded at ' + faker['dates'][0]"
/>
</AvatarRoot>
<AvatarRoot class="size-11 bg-background rounded-full -ms-5">
<AvatarFallback>IM</AvatarFallback>
<AvatarImage
:src="faker['images'][1]"
:alt="'Uploaded at ' + faker['dates'][1]"
/>
</AvatarRoot>
<AvatarRoot class="size-11 bg-background rounded-full -ms-5">
<AvatarFallback>IM</AvatarFallback>
<AvatarImage
:src="faker['images'][2]"
:alt="'Uploaded at ' + faker['dates'][2]"
/>
</AvatarRoot>
</div>
</TableCell>
<TableCell>
<a class="whitespace-nowrap font-medium" href="">
{{ faker['categories'][0]!['name'] }}
</a>
<div class="mt-0.5 whitespace-nowrap text-xs opacity-70">
Tags: {{ faker['categories'][0]!['tags'] }}
</div>
</TableCell>
<TableCell>
<a class="mr-3 flex items-center opacity-70" href="#">
<Lucide class="mr-2 h-4 w-4" icon="ExternalLink" />
/categories/{{ faker['categories'][0]!['slug'] }}
</a>
</TableCell>
<TableCell>
<div
class="flex items-center justify-center"
:class="faker['trueFalse'][0] ? 'text-success' : 'text-danger'"
>
<Lucide class="mr-2 h-4 w-4" icon="CheckSquare" />
{{ faker['trueFalse'][0] ? 'Active' : 'Inactive' }}
</div>
</TableCell>
<TableCell>
<div class="flex items-center justify-center">
<a class="mr-3 flex items-center" href="">
<Lucide class="mr-1 h-4 w-4" icon="CheckSquare" />
Edit
</a>
<a
class="text-danger flex items-center"
href="#"
@click.prevent="deleteConfirmationOpen = true"
>
<Lucide class="mr-1 h-4 w-4" icon="Trash" />
Delete
</a>
</div>
</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
<!-- END: Data List -->
<!-- BEGIN: Pagination -->
<div class="col-span-12 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="150"
:pageSize="10"
:siblingCount="1"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>Previous</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>Next</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="mt-3 w-20 sm:mt-0">
<NativeSelectOption value="10">10</NativeSelectOption>
<NativeSelectOption value="25">25</NativeSelectOption>
<NativeSelectOption value="35">35</NativeSelectOption>
<NativeSelectOption value="50">50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
<!-- BEGIN: Delete Confirmation Modal -->
<DialogRoot
:open="deleteConfirmationOpen"
@openChange="(details) => (deleteConfirmationOpen = details.open)"
>
<DialogContent>
<div class="p-5 text-center">
<Lucide class="text-danger mx-auto mt-3 size-16 stroke-1" icon="CircleX" />
<div class="mt-5 text-2xl font-medium">Are you sure?</div>
<div class="mt-2 opacity-70">
Do you really want to delete these records? <br />
This process cannot be undone.
</div>
</div>
<div class="px-5 pb-8 text-center">
<DialogCloseTrigger class="mr-2 w-24"> Cancel </DialogCloseTrigger>
<Button class="w-24" type="button" variant="danger" look="outline"> Delete </Button>
</div>
</DialogContent>
</DialogRoot>
<!-- END: Delete Confirmation Modal -->
</div>
</template>
File diff suppressed because it is too large Load Diff
+200
View File
@@ -0,0 +1,200 @@
<script lang="ts" setup>
import { ref } from 'vue'
import fakers from '@/utils/faker'
import { AvatarRoot, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Box } from '@/components/ui/box'
import { Button } from '@/components/ui/button'
import { DialogRoot, DialogContent, DialogCloseTrigger } from '@/components/ui/dialog'
import { Input } from '@/components/ui/input'
import { Lucide } from '@/components/ui/lucide'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import {
Table,
TableHeader,
TableBody,
TableHead,
TableRow,
TableCell,
} from '@/components/ui/table'
const deleteConfirmationOpen = ref(false)
</script>
<template>
<div>
<h2 class="text-lg font-medium">Data List Layout</h2>
<div class="mt-5 grid grid-cols-12 gap-6">
<div class="col-span-12 mt-2 flex flex-wrap items-center sm:flex-nowrap">
<Button class="mr-2" look="outline" variant="primary"> Add New Product </Button>
<MenuRoot class="w-auto">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="print">
<Lucide class="mr-2 h-4 w-4" icon="Printer" /> Print
</MenuItem>
<MenuItem value="excel">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to Excel
</MenuItem>
<MenuItem value="pdf">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to PDF
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
<div class="mx-auto hidden opacity-70 md:block">Showing 1 to 10 of 150 entries</div>
<div class="mt-3 w-full sm:ml-auto sm:mt-0 sm:w-auto md:ml-0">
<div class="relative w-56">
<Input class="w-56 pr-10" type="text" placeholder="Search..." />
<Lucide class="absolute inset-y-0 right-0 my-auto mr-3 h-4 w-4" icon="Search" />
</div>
</div>
</div>
<!-- BEGIN: Data List -->
<div class="col-span-12 overflow-auto lg:overflow-visible">
<Table class="-mt-2" variant="boxed">
<TableHeader>
<TableRow>
<TableHead> IMAGES </TableHead>
<TableHead> PRODUCT NAME </TableHead>
<TableHead class="text-center"> STOCK </TableHead>
<TableHead class="text-center"> STATUS </TableHead>
<TableHead class="text-center"> ACTIONS </TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow v-for="(faker, index) in fakers.slice(0, 9)" :key="index">
<TableCell>
<div class="flex">
<AvatarRoot class="size-11 bg-background rounded-full">
<AvatarFallback>IM</AvatarFallback>
<AvatarImage
:src="faker['images'][0]"
:alt="'Uploaded at ' + faker['dates'][0]"
/>
</AvatarRoot>
<AvatarRoot class="size-11 bg-background rounded-full -ms-5">
<AvatarFallback>IM</AvatarFallback>
<AvatarImage
:src="faker['images'][1]"
:alt="'Uploaded at ' + faker['dates'][1]"
/>
</AvatarRoot>
<AvatarRoot class="size-11 bg-background rounded-full -ms-5">
<AvatarFallback>IM</AvatarFallback>
<AvatarImage
:src="faker['images'][2]"
:alt="'Uploaded at ' + faker['dates'][2]"
/>
</AvatarRoot>
</div>
</TableCell>
<TableCell>
<a class="whitespace-nowrap font-medium" href="">
{{ faker['products'][0]!['name'] }}
</a>
<div class="mt-0.5 whitespace-nowrap text-xs opacity-70">
{{ faker['products'][0]!['category'] }}
</div>
</TableCell>
<TableCell class="text-center">
{{ faker['stocks'][0] }}
</TableCell>
<TableCell>
<div
class="flex items-center justify-center"
:class="faker['trueFalse'][0] ? 'text-success' : 'text-danger'"
>
<Lucide class="mr-2 h-4 w-4" icon="CheckSquare" />
{{ faker['trueFalse'][0] ? 'Active' : 'Inactive' }}
</div>
</TableCell>
<TableCell>
<div class="flex items-center justify-center">
<a class="mr-3 flex items-center" href="">
<Lucide class="mr-1 h-4 w-4" icon="CheckSquare" />
Edit
</a>
<a
class="text-danger flex items-center"
href="#"
@click.prevent="deleteConfirmationOpen = true"
>
<Lucide class="mr-1 h-4 w-4" icon="Trash" />
Delete
</a>
</div>
</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
<!-- END: Data List -->
<!-- BEGIN: Pagination -->
<div class="col-span-12 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="150"
:pageSize="10"
:siblingCount="1"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>Previous</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>Next</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="mt-3 w-20 sm:mt-0">
<NativeSelectOption value="10">10</NativeSelectOption>
<NativeSelectOption value="25">25</NativeSelectOption>
<NativeSelectOption value="35">35</NativeSelectOption>
<NativeSelectOption value="50">50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
<!-- BEGIN: Delete Confirmation Modal -->
<DialogRoot
:open="deleteConfirmationOpen"
@openChange="(details) => (deleteConfirmationOpen = details.open)"
>
<DialogContent>
<div class="p-5 text-center">
<Lucide class="text-danger mx-auto mt-3 size-16 stroke-1" icon="CircleX" />
<div class="mt-5 text-2xl font-medium">Are you sure?</div>
<div class="mt-2 opacity-70">
Do you really want to delete these records? <br />
This process cannot be undone.
</div>
</div>
<div class="px-5 pb-8 text-center">
<DialogCloseTrigger class="mr-2 w-24"> Cancel </DialogCloseTrigger>
<Button class="w-24" type="button" variant="danger" look="outline"> Delete </Button>
</div>
</DialogContent>
</DialogRoot>
<!-- END: Delete Confirmation Modal -->
</div>
</template>
+141
View File
@@ -0,0 +1,141 @@
<script lang="ts" setup>
import { ref, computed } from 'vue'
import * as combobox from '@zag-js/combobox'
import { Box } from '@/components/ui/box'
import { Button } from '@/components/ui/button'
import {
ComboboxRoot,
ComboboxControl,
ComboboxTrigger,
ComboboxContent,
ComboboxInput,
ComboboxItemGroup,
ComboboxItemGroupLabel,
ComboboxItem,
ComboboxItemText,
} from '@/components/ui/combobox'
import { Field, FieldLabel } from '@/components/ui/field'
import { Input } from '@/components/ui/input'
import { SwitchRoot, SwitchControl } from '@/components/ui/switch'
import { Textarea } from '@/components/ui/textarea'
const categoryData = [
{ label: 'Sport & Outdoor', code: 'sport' },
{ label: 'PC & Laptop', code: 'pc' },
{ label: 'Smartphone & Tablet', code: 'smartphone' },
{ label: 'Photography', code: 'photography' },
]
const categoryValue = ref(['Sport & Outdoor', 'Smartphone & Tablet'])
const categoryOptions = ref(categoryData)
const categoryCollection = computed(() =>
combobox.collection({
items: categoryOptions.value,
itemToValue: (item) => item.label,
}),
)
</script>
<template>
<div class="flex items-center">
<h2 class="mr-auto text-lg font-medium">Form Layout</h2>
</div>
<div class="mt-5 grid grid-cols-12 gap-6">
<div class="col-span-12 lg:col-span-6">
<!-- BEGIN: Form Layout -->
<Box>
<Field>
<FieldLabel for="crud-form-1">Product Name</FieldLabel>
<Input class="w-full" id="crud-form-1" type="text" placeholder="Product name" />
</Field>
<Field class="mt-3">
<FieldLabel>Category</FieldLabel>
<ComboboxRoot :collection="categoryCollection" :value="categoryValue"
@value-change="(details) => (categoryValue = details.value)" @input-value-change="
({ inputValue }) => {
const filtered = categoryData.filter((item) =>
item.label.toLowerCase().includes(inputValue.toLowerCase()),
)
categoryOptions = filtered.length > 0 ? filtered : categoryData
}
" class="w-full" multiple>
<ComboboxControl>
<ComboboxTrigger />
</ComboboxControl>
<ComboboxContent>
<ComboboxInput placeholder="Search category..." />
<ComboboxItemGroup>
<ComboboxItemGroupLabel>Categories</ComboboxItemGroupLabel>
<ComboboxItem v-for="item in categoryCollection.items" :key="item.code" :item="item">
<ComboboxItemText>{{ item.label }}</ComboboxItemText>
</ComboboxItem>
</ComboboxItemGroup>
</ComboboxContent>
</ComboboxRoot>
</Field>
<Field class="mt-3">
<FieldLabel for="crud-form-3">Quantity</FieldLabel>
<div class="flex">
<Input class="rounded-e-none border-e-0" type="text" placeholder="Quantity" />
<div
class="bg-(--color)/3 border-(--color)/8 text-(--color)/70 flex w-16 items-center justify-center rounded-e-lg border [--color:var(--color-foreground)]">
pcs
</div>
</div>
</Field>
<Field class="mt-3">
<FieldLabel for="crud-form-4">Weight</FieldLabel>
<div class="flex">
<Input class="rounded-e-none border-e-0" type="text" placeholder="Weight" />
<div
class="bg-(--color)/3 border-(--color)/8 text-(--color)/70 flex w-16 items-center justify-center rounded-e-lg border [--color:var(--color-foreground)]">
grams
</div>
</div>
</Field>
<Field class="mt-3">
<FieldLabel>Price</FieldLabel>
<div class="grid-cols-3 gap-2 sm:grid">
<div class="flex">
<div
class="bg-(--color)/3 border-(--color)/8 text-(--color)/70 flex items-center justify-center rounded-s-lg border px-3 [--color:var(--color-foreground)]">
Unit
</div>
<Input class="rounded-s-none border-s-0" type="text" placeholder="Unit" />
</div>
<div class="mt-2 flex sm:mt-0">
<div
class="bg-(--color)/3 border-(--color)/8 text-(--color)/70 flex items-center justify-center rounded-s-lg border px-3 [--color:var(--color-foreground)]">
Wholesale
</div>
<Input class="rounded-s-none border-s-0" type="text" placeholder="Wholesale" />
</div>
<div class="mt-2 flex sm:mt-0">
<div
class="bg-(--color)/3 border-(--color)/8 text-(--color)/70 flex items-center justify-center rounded-s-lg border px-3 [--color:var(--color-foreground)]">
Bulk
</div>
<Input class="rounded-s-none border-s-0" type="text" placeholder="Bulk" />
</div>
</div>
</Field>
<Field class="mt-3">
<FieldLabel>Active Status</FieldLabel>
<SwitchRoot>
<SwitchControl />
</SwitchRoot>
</Field>
<Field class="mt-3">
<FieldLabel for="crud-form-5">Description</FieldLabel>
<Textarea id="crud-form-5" placeholder="Product description">Content of the editor.</Textarea>
</Field>
<div class="mt-5 text-right">
<Button class="mr-1 w-24" type="button" look="outline"> Cancel </Button>
<Button class="w-24" type="button" variant="primary"> Save </Button>
</div>
</Box>
<!-- END: Form Layout -->
</div>
</div>
</template>
+591
View File
@@ -0,0 +1,591 @@
<script lang="ts" setup>
import { ref } from 'vue'
import { today, getLocalTimeZone } from '@internationalized/date'
import phoneIllustration from '@/assets/images/phone-illustration.svg'
import womanIllustration from '@/assets/images/woman-illustration.svg'
import { Badge } from '@/components/ui/badge'
import { Box } from '@/components/ui/box'
import {
CarouselRoot,
CarouselPrevTrigger,
CarouselNextTrigger,
CarouselItemGroup,
CarouselItem,
} from '@/components/ui/carousel'
import {
DatePickerRoot,
DatePickerControl,
DatePickerInput,
DatePickerTrigger,
DatePickerPositioner,
DatePickerContent,
DatePickerYearSelect,
DatePickerMonthSelect,
DatePickerView,
DatePickerViewControl,
DatePickerPrevTrigger,
DatePickerNextTrigger,
DatePickerRangeText,
DatePickerTable,
DatePickerTableHead,
DatePickerTableRow,
DatePickerTableHeader,
DatePickerTableBody,
DatePickerTableCell,
DatePickerTableCellTrigger,
DatePickerContext,
} from '@/components/ui/datepicker'
import { DialogRoot, DialogContent, DialogCloseTrigger } from '@/components/ui/dialog'
import { Field, FieldLabel, FieldGroup } from '@/components/ui/field'
import { Input } from '@/components/ui/input'
import { Lucide } from '@/components/ui/lucide'
import {
MenuRoot,
MenuTrigger,
MenuPositioner,
MenuContent,
MenuCheckboxItem,
} from '@/components/ui/menu'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import { Line1, Line2, Pie1, Donut1, Donut2 } from '@/components/chart-presets'
import { Transactions } from '@/components/transactions'
import { RecentActivities } from '@/components/recent-activities'
import { DailyNotes } from '@/components/daily-notes'
import { Schedules } from '@/components/schedules'
import { OfficialStores } from '@/components/official-stores'
import { WeeklyBestSellers } from '@/components/weekly-best-sellers'
import { WeeklyTopProducts } from '@/components/weekly-top-products'
const pc = ref(false)
const electronic = ref(false)
const smartphone = ref(false)
const photography = ref(false)
const sport = ref(false)
const onboardingDialog = ref(true)
const salesReportDate = ref<any[]>([
today(getLocalTimeZone()).subtract({ days: 7 }),
today(getLocalTimeZone()),
])
</script>
<template>
<div>
<div class="grid grid-cols-12 gap-6">
<div class="col-span-12 2xl:col-span-9">
<div class="grid grid-cols-12 gap-6">
<!-- BEGIN: General Report -->
<div class="col-span-12">
<div class="flex h-10 items-center">
<h2 class="me-5 truncate text-lg font-medium">General Report</h2>
<a class="text-primary ms-auto flex items-center gap-3" href="">
<Lucide icon="RefreshCcw" /> Refresh
</a>
</div>
<div class="mt-5 grid grid-cols-12 gap-6">
<div class="col-span-12 sm:col-span-6 xl:col-span-3">
<Box raised="single">
<div class="flex">
<Lucide
class="h-7 w-7 stroke-1 drop-shadow [--color:var(--color-primary)]"
icon="CircleGauge"
/>
<div class="ms-auto">
<Badge variant="success" look="outline" content="12% Higher than last month">
12%
<Lucide class="ms-0.5" icon="ChevronUp" />
</Badge>
</div>
</div>
<div class="mt-6 text-2xl font-medium leading-8">$724,091.47</div>
<div class="mt-1.5 text-xs uppercase opacity-70">Item Sales</div>
</Box>
</div>
<div class="col-span-12 sm:col-span-6 xl:col-span-3">
<Box raised="single">
<div class="flex">
<Lucide
class="h-7 w-7 stroke-1 [--color:var(--color-pending)]"
icon="PanelBottomClose"
/>
<div class="ms-auto">
<Badge variant="success" look="outline" content="9% Higher than last month">
9%
<Lucide class="ms-0.5" icon="ChevronUp" />
</Badge>
</div>
</div>
<div class="mt-6 text-2xl font-medium leading-8">21,546</div>
<div class="mt-1.5 text-xs uppercase opacity-70">New Orders</div>
</Box>
</div>
<div class="col-span-12 sm:col-span-6 xl:col-span-3">
<Box raised="single">
<div class="flex">
<Lucide class="h-7 w-7 stroke-1 [--color:var(--color-warning)]" icon="Disc3" />
<div class="ms-auto">
<Badge variant="danger" look="outline" content="7% Lower than last month">
7%
<Lucide class="ms-0.5" icon="ChevronDown" />
</Badge>
</div>
</div>
<div class="mt-6 text-2xl font-medium leading-8">1,524,091</div>
<div class="mt-1.5 text-xs uppercase opacity-70">Total Products</div>
</Box>
</div>
<div class="col-span-12 sm:col-span-6 xl:col-span-3">
<Box raised="single">
<div class="flex">
<Lucide class="h-7 w-7 stroke-1 [--color:var(--color-danger)]" icon="Album" />
<div class="ms-auto">
<Badge variant="success" look="outline" content="41% Higher than last month">
41%
<Lucide class="ms-0.5" icon="ChevronUp" />
</Badge>
</div>
</div>
<div class="mt-6 text-2xl font-medium leading-8">42,924,091</div>
<div class="mt-1.5 text-xs uppercase opacity-70">Unique Visitors</div>
</Box>
</div>
</div>
</div>
<!-- END: General Report -->
<!-- BEGIN: Sales Report -->
<div class="col-span-12 mt-5 lg:col-span-6">
<div class="block h-10 items-center sm:flex">
<h2 class="me-5 truncate text-lg font-medium">Sales Report</h2>
<div class="relative mt-3 sm:ms-auto sm:mt-0">
<DatePickerRoot
selection-mode="range"
:num-of-months="2"
:value="salesReportDate"
@value-change="(details) => (salesReportDate = details.value)"
>
<DatePickerControl>
<DatePickerInput :index="0" />
<DatePickerTrigger />
</DatePickerControl>
<DatePickerPositioner>
<DatePickerContent>
<DatePickerYearSelect />
<DatePickerMonthSelect />
<DatePickerViewControl>
<DatePickerPrevTrigger />
<DatePickerRangeText />
<DatePickerNextTrigger />
</DatePickerViewControl>
<DatePickerView view="day" class="flex-row">
<DatePickerContext v-slot="{ datePicker }">
<DatePickerTable>
<DatePickerTableHead>
<DatePickerTableRow>
<DatePickerTableHeader
v-for="(weekDay, id) in datePicker?.weekDays"
:key="id"
>
{{ weekDay.short }}
</DatePickerTableHeader>
</DatePickerTableRow>
</DatePickerTableHead>
<DatePickerTableBody>
<DatePickerTableRow v-for="(week, id) in datePicker?.weeks" :key="id">
<DatePickerTableCell
v-for="(day, id) in week"
:key="id"
:value="day"
>
<DatePickerTableCellTrigger>
{{ day.day }}
</DatePickerTableCellTrigger>
</DatePickerTableCell>
</DatePickerTableRow>
</DatePickerTableBody>
</DatePickerTable>
</DatePickerContext>
<DatePickerContext v-slot="{ datePicker }">
<DatePickerTable>
<DatePickerTableHead>
<DatePickerTableRow>
<DatePickerTableHeader
v-for="(weekDay, id) in datePicker?.weekDays"
:key="id"
>
{{ weekDay.short }}
</DatePickerTableHeader>
</DatePickerTableRow>
</DatePickerTableHead>
<DatePickerTableBody>
<DatePickerTableRow
v-for="(week, id) in datePicker?.getOffset({
months: 1,
}).weeks"
:key="id"
>
<DatePickerTableCell
v-for="(day, id) in week"
:key="id"
:value="day"
:visible-range="datePicker?.getOffset({ months: 1 }).visibleRange"
>
<DatePickerTableCellTrigger>
{{ day.day }}
</DatePickerTableCellTrigger>
</DatePickerTableCell>
</DatePickerTableRow>
</DatePickerTableBody>
</DatePickerTable>
</DatePickerContext>
</DatePickerView>
</DatePickerContent>
</DatePickerPositioner>
</DatePickerRoot>
</div>
</div>
<Box class="mt-12 p-5 sm:mt-5">
<div class="flex flex-col md:flex-row md:items-center">
<div class="flex">
<div>
<div class="text-lg font-medium">$24,100,21</div>
<div class="mt-1.5 text-xs uppercase opacity-70">This Month</div>
</div>
<div
class="border-foreground/20 mx-4 h-12 w-px border border-r border-dotted xl:mx-6"
></div>
<div class="text-foreground/80">
<div class="text-lg font-medium">$21,023,01</div>
<div class="mt-1.5 text-xs uppercase opacity-70">Last Month</div>
</div>
</div>
<MenuRoot class="w-auto mt-5 md:ms-auto md:mt-0">
<MenuTrigger>Filter by Category</MenuTrigger>
<MenuPositioner>
<MenuContent>
<MenuCheckboxItem
:checked="pc"
:onCheckedChange="(checked) => (pc = checked)"
value="checked"
>
PC & Laptop
</MenuCheckboxItem>
<MenuCheckboxItem
:checked="smartphone"
:onCheckedChange="(checked) => (smartphone = checked)"
value="checked"
>
Smartphone
</MenuCheckboxItem>
<MenuCheckboxItem
:checked="electronic"
:onCheckedChange="(checked) => (electronic = checked)"
value="checked"
>
Electronic
</MenuCheckboxItem>
<MenuCheckboxItem
:checked="photography"
:onCheckedChange="(checked) => (photography = checked)"
value="checked"
>
Photography
</MenuCheckboxItem>
<MenuCheckboxItem
:checked="sport"
:onCheckedChange="(checked) => (sport = checked)"
value="checked"
>
Sport
</MenuCheckboxItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
<Line1 class="mt-6 h-[275px]" />
</Box>
</div>
<!-- END: Sales Report -->
<!-- BEGIN: Weekly Top Seller -->
<div class="col-span-12 mt-5 sm:col-span-6 lg:col-span-3">
<div class="flex h-10 items-center">
<h2 class="me-5 truncate text-lg font-medium">Weekly Top Seller</h2>
<a class="text-primary ms-auto truncate" href=""> Show More </a>
</div>
<Box class="mt-5 p-5">
<div class="mt-3">
<Pie1 class="h-[213px]" />
</div>
<div class="mx-auto mt-8 w-52 sm:w-auto">
<div class="flex items-center">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 size-2 rounded-full border [--color:var(--color-primary)]"
></div>
<span class="truncate">17 - 30 Years old</span>
<span class="ms-auto">62%</span>
</div>
<div class="mt-4 flex items-center">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 size-2 rounded-full border [--color:var(--color-pending)]"
></div>
<span class="truncate">31 - 50 Years old</span>
<span class="ms-auto">33%</span>
</div>
<div class="mt-4 flex items-center">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 size-2 rounded-full border [--color:var(--color-warning)]"
></div>
<span class="truncate">&gt;= 50 Years old</span>
<span class="ms-auto">10%</span>
</div>
</div>
</Box>
</div>
<!-- END: Weekly Top Seller -->
<!-- BEGIN: Sales Report -->
<div class="col-span-12 mt-5 sm:col-span-6 lg:col-span-3">
<div class="flex h-10 items-center">
<h2 class="me-5 truncate text-lg font-medium">Sales Report</h2>
<a class="text-primary ms-auto truncate" href=""> Show More </a>
</div>
<Box class="mt-5 p-5">
<div class="mt-3">
<Donut1 class="h-[213px]" />
</div>
<div class="mx-auto mt-8 w-52 sm:w-auto">
<div class="flex items-center">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 size-2 rounded-full border [--color:var(--color-primary)]"
></div>
<span class="truncate">17 - 30 Years old</span>
<span class="ms-auto">62%</span>
</div>
<div class="mt-4 flex items-center">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 size-2 rounded-full border [--color:var(--color-pending)]"
></div>
<span class="truncate">31 - 50 Years old</span>
<span class="ms-auto">33%</span>
</div>
<div class="mt-4 flex items-center">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 size-2 rounded-full border [--color:var(--color-warning)]"
></div>
<span class="truncate">&gt;= 50 Years old</span>
<span class="ms-auto">10%</span>
</div>
</div>
</Box>
</div>
<!-- END: Sales Report -->
<!-- BEGIN: Official Store -->
<div class="col-span-12 mt-6 xl:col-span-8">
<OfficialStores />
</div>
<!-- END: Official Store -->
<!-- BEGIN: Weekly Best Sellers -->
<div class="col-span-12 mt-6 xl:col-span-4">
<WeeklyBestSellers />
</div>
<!-- END: Weekly Best Sellers -->
<!-- BEGIN: General Report -->
<div class="col-span-12 mt-8 grid grid-cols-12 gap-6">
<div class="col-span-12 sm:col-span-6 2xl:col-span-3">
<Box class="p-5">
<div class="flex items-center">
<div class="w-2/4 flex-none">
<div class="truncate text-lg font-medium">Target Sales</div>
<div class="mt-1 opacity-70">300 Sales</div>
</div>
<div class="relative ms-auto flex-none">
<Donut2 class="w-[90px] h-[90px]" />
<div
class="absolute start-0 top-0 flex h-full w-full items-center justify-center font-medium"
>
20%
</div>
</div>
</div>
</Box>
</div>
<div class="col-span-12 sm:col-span-6 2xl:col-span-3">
<Box class="p-5">
<div class="flex items-center">
<div class="me-3 truncate text-lg font-medium">Social Media</div>
<Badge variant="secondary" look="outline" class="ms-auto whitespace-nowrap"
>137 Sales</Badge
>
</div>
<div class="mt-1">
<Line2 class="-ms-1 h-[58px]" />
</div>
</Box>
</div>
<div class="col-span-12 sm:col-span-6 2xl:col-span-3">
<Box class="p-5">
<div class="flex items-center">
<div class="w-2/4 flex-none">
<div class="truncate text-lg font-medium">New Products</div>
<div class="mt-1 opacity-70">1450 Products</div>
</div>
<div class="relative ms-auto flex-none">
<Donut2 class="w-[90px] h-[90px]" />
<div
class="absolute start-0 top-0 flex h-full w-full items-center justify-center font-medium"
>
45%
</div>
</div>
</div>
</Box>
</div>
<div class="col-span-12 sm:col-span-6 2xl:col-span-3">
<Box class="p-5">
<div class="flex items-center">
<div class="me-3 truncate text-lg font-medium">Posted Ads</div>
<Badge variant="secondary" look="outline" class="ms-auto whitespace-nowrap"
>180 Campaign</Badge
>
</div>
<div class="mt-1">
<Line2 class="-ms-1 h-[58px]" />
</div>
</Box>
</div>
</div>
<!-- END: General Report -->
<!-- BEGIN: Weekly Top Products -->
<div class="col-span-12 mt-6">
<WeeklyTopProducts />
</div>
<!-- END: Weekly Top Products -->
</div>
</div>
<div class="col-span-12 2xl:col-span-3">
<div class="-mb-10 h-full pb-10 2xl:border-l border-foreground/15">
<div class="grid grid-cols-12 gap-x-6 gap-y-6 2xl:gap-x-0 2xl:pl-6">
<!-- BEGIN: Transactions -->
<div class="col-span-12 md:col-span-6 xl:col-span-4 2xl:col-span-12">
<Transactions />
</div>
<!-- END: Transactions -->
<!-- BEGIN: Recent Activities -->
<div class="col-span-12 mt-3 md:col-span-6 xl:col-span-4 2xl:col-span-12">
<RecentActivities />
</div>
<!-- END: Recent Activities -->
<!-- BEGIN: Daily Notes -->
<div
class="col-span-12 mt-3 md:col-span-6 xl:col-span-12 xl:col-start-1 xl:row-start-1 2xl:col-start-auto 2xl:row-start-auto"
>
<DailyNotes />
</div>
<!-- END: Daily Notes -->
<!-- BEGIN: Schedules -->
<div
class="col-span-12 mt-3 md:col-span-6 xl:col-span-4 xl:col-start-1 xl:row-start-2 2xl:col-span-12 2xl:col-start-auto 2xl:row-start-auto"
>
<Schedules />
</div>
<!-- END: Schedules -->
</div>
</div>
</div>
</div>
<!-- BEGIN: Onboarding Dialog -->
<DialogRoot
:open="onboardingDialog"
@openChange="(details) => (onboardingDialog = details.open)"
>
<DialogContent class="sm:max-w-xl">
<DialogCloseTrigger />
<div class="overflow-hidden">
<div class="-my-5 -mx-10">
<CarouselRoot :default-page="0" :slide-count="2" class="border-0">
<CarouselItemGroup>
<CarouselItem class="border-transparent bg-none bg-transparent" :index="0">
<div class="relative mx-3 flex flex-col items-center gap-1 px-3.5 pb-20">
<div
class="w-full bg-primary/[.05] mb-7 border-primary/10 shadow-lg shadow-black/10 relative rounded-3xl border h-52 overflow-hidden before:bg-noise before:absolute before:inset-0 before:opacity-30 after:bg-accent after:absolute after:inset-0 after:opacity-30 after:blur-2xl"
>
<img
class="absolute inset-0 mx-auto mt-10 w-2/5 scale-125"
:src="phoneIllustration"
alt="Midone - Tailwind Admin Dashboard Template"
/>
</div>
<div class="px-8">
<div class="text-center text-xl font-medium">Welcome to Midone Admin!</div>
<div class="mt-3 text-center text-base leading-relaxed opacity-70">
Premium admin dashboard template for all kinds <br />
of projects. With a unique and modern design, Midone offers the perfect
foundation to build professional applications with ease.
</div>
</div>
<div class="absolute inset-x-0 bottom-0 flex place-content-between px-5">
<a
class="text-danger flex items-center gap-3 font-medium cursor-pointer"
@click.prevent="onboardingDialog = false"
>
Skip Intro
</a>
<CarouselNextTrigger
class="text-primary flex items-center gap-3 font-medium me-0 px-5"
>
Next <Lucide icon="MoveRight" />
</CarouselNextTrigger>
</div>
</div>
</CarouselItem>
<CarouselItem class="border-transparent bg-none bg-transparent" :index="1">
<div class="relative mx-3 flex flex-col items-center gap-1 px-3.5 pb-20">
<div
class="w-full bg-primary/[.05] mb-7 border-primary/10 shadow-lg shadow-black/10 relative rounded-3xl border h-52 overflow-hidden before:bg-noise before:absolute before:inset-0 before:opacity-30 after:bg-accent after:absolute after:inset-0 after:opacity-30 after:blur-2xl"
>
<img
class="absolute inset-0 mx-auto mt-10 w-2/5 scale-125"
:src="womanIllustration"
alt="Midone - Tailwind Admin Dashboard Template"
/>
</div>
<div class="w-full">
<div class="text-center text-xl font-medium">Example Request Information</div>
<div class="mt-3 text-center text-base leading-relaxed opacity-70">
Your premium admin dashboard template.
</div>
<div class="mt-8">
<FieldGroup class="px-5">
<div class="grid grid-cols-2 gap-5">
<Field>
<FieldLabel>Full Name</FieldLabel>
<Input type="text" placeholder="John Doe" />
</Field>
<Field>
<FieldLabel>Event</FieldLabel>
<NativeSelect>
<NativeSelectOption>Corporate Event</NativeSelectOption>
<NativeSelectOption>Wedding</NativeSelectOption>
<NativeSelectOption>Birthday</NativeSelectOption>
<NativeSelectOption>Other</NativeSelectOption>
</NativeSelect>
</Field>
</div>
</FieldGroup>
</div>
</div>
<div class="absolute inset-x-0 bottom-0 flex place-content-between px-5">
<CarouselPrevTrigger
class="text-primary flex items-center gap-3 font-medium ms-0 px-5"
>
<Lucide icon="MoveLeft" /> Previous
</CarouselPrevTrigger>
</div>
</div>
</CarouselItem>
</CarouselItemGroup>
</CarouselRoot>
</div>
</div>
</DialogContent>
</DialogRoot>
<!-- END: Onboarding Dialog -->
</div>
</template>
+43
View File
@@ -0,0 +1,43 @@
<script lang="ts" setup>
import errorIllustrationUrl from '@/assets/images/error-illustration.svg'
import { Button } from '@/components/ui/button'
</script>
<template>
<div
:class="[
'relative py-2',
'before:bg-primary dark:before:bg-foreground/[.01] before:fixed before:inset-0 before:bg-noise',
'after:bg-accent after:bg-contain after:fixed after:inset-0 after:blur-xl dark:after:opacity-20',
]"
>
<div class="container relative z-10 mx-auto">
<!-- BEGIN: Error Page -->
<div
class="flex h-screen flex-col items-center justify-center text-center lg:flex-row lg:text-left"
>
<div class="lg:mr-20">
<img
class="h-48 w-[450px] lg:h-auto"
:src="errorIllustrationUrl"
alt="Midone - Tailwind Admin Dashboard Template"
/>
</div>
<div class="mt-10 text-white lg:mt-0">
<div class="text-9xl [text-shadow:_7px_7px_--alpha(var(--color-white)_/_20%)]">404</div>
<div class="mt-8 text-xl font-medium lg:text-2xl">Oops. This page has gone missing.</div>
<div class="mt-3 text-base opacity-70">
You may have mistyped the address or the page may have moved.
</div>
<Button
class="box mt-10 border border-white bg-transparent px-7 py-6 text-white"
variant="ghost"
>
Back to Home
</Button>
</div>
</div>
<!-- END: Error Page -->
</div>
</div>
</template>
+271
View File
@@ -0,0 +1,271 @@
<script lang="ts" setup>
import { Box } from '@/components/ui/box'
import {
AccordionRoot,
AccordionItem,
AccordionTrigger,
AccordionContent,
} from '@/components/ui/accordion'
import { Lucide } from '@/components/ui/lucide'
</script>
<template>
<div class="flex items-center">
<h2 class="mr-auto text-lg font-medium">FAQ Layout</h2>
</div>
<div class="mt-5 grid grid-cols-12 gap-x-6 gap-y-8">
<!-- BEGIN: FAQ Menu -->
<Box
class="active [&.active]:before:bg-(--color)/5 [&.active]:before:border-(--color)/20 [&.active]:after:bg-(--color)/5 [&.active]:after:border-(--color)/20 col-span-12 py-10 [--color:var(--color-primary)] lg:col-span-4"
href=""
as="a"
>
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="Shield" />
<div class="mt-3 text-center text-base font-medium">Single Application</div>
<div class="mx-auto mt-2 w-3/4 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing
</div>
</Box>
<Box
class="[&.active]:before:bg-(--color)/5 [&.active]:before:border-(--color)/20 [&.active]:after:bg-(--color)/5 [&.active]:after:border-(--color)/20 col-span-12 py-10 [--color:var(--color-primary)] lg:col-span-4"
href=""
as="a"
>
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="Send" />
<div class="mt-3 text-center text-base font-medium">Multi Application</div>
<div class="mx-auto mt-2 w-3/4 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing
</div>
</Box>
<Box
class="[&.active]:before:bg-(--color)/5 [&.active]:before:border-(--color)/20 [&.active]:after:bg-(--color)/5 [&.active]:after:border-(--color)/20 col-span-12 py-10 [--color:var(--color-primary)] lg:col-span-4"
href=""
as="a"
>
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="TrendingUp" />
<div class="mt-3 text-center text-base font-medium">Custom License</div>
<div class="mx-auto mt-2 w-3/4 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing
</div>
</Box>
<!-- END: FAQ Menu -->
<!-- BEGIN: FAQ Content -->
<div class="col-span-12 lg:col-span-6">
<Box class="p-0">
<div class="flex items-center border-b border-foreground/15 p-5">
<h2 class="mr-auto text-base font-medium">Working with Dropplets</h2>
</div>
<div class="p-5">
<AccordionRoot class="border-none" :default-value="['faq-1-1']">
<AccordionItem value="faq-1-1">
<AccordionTrigger>
OpenSSL Essentials: Working with SSL Certificates, Private Keys
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-1-2">
<AccordionTrigger>
Understanding IP Addresses, Subnets, and CIDR Notation
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-1-3">
<AccordionTrigger>How To Troubleshoot Common HTTP Error Codes</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-1-4">
<AccordionTrigger>An Introduction to Securing your Linux VPS</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
</AccordionRoot>
</div>
</Box>
<Box class="mt-8 p-0">
<div class="flex items-center border-b border-foreground/15 p-5">
<h2 class="mr-auto text-base font-medium">Working with Dropplets</h2>
</div>
<div class="p-5">
<AccordionRoot class="border-none">
<AccordionItem value="faq-2-1">
<AccordionTrigger>
OpenSSL Essentials: Working with SSL Certificates, Private Keys
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-2-2">
<AccordionTrigger>
Understanding IP Addresses, Subnets, and CIDR Notation
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-2-3">
<AccordionTrigger>How To Troubleshoot Common HTTP Error Codes</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-2-4">
<AccordionTrigger>An Introduction to Securing your Linux VPS</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
</AccordionRoot>
</div>
</Box>
</div>
<div class="col-span-12 lg:col-span-6">
<Box class="p-0">
<div class="flex items-center border-b border-foreground/15 p-5">
<h2 class="mr-auto text-base font-medium">Working with Dropplets</h2>
</div>
<div class="p-5">
<AccordionRoot class="border-none">
<AccordionItem value="faq-3-1">
<AccordionTrigger>
OpenSSL Essentials: Working with SSL Certificates, Private Keys
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-3-2">
<AccordionTrigger>
Understanding IP Addresses, Subnets, and CIDR Notation
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-3-3">
<AccordionTrigger>How To Troubleshoot Common HTTP Error Codes</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-3-4">
<AccordionTrigger>An Introduction to Securing your Linux VPS</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
</AccordionRoot>
</div>
</Box>
<Box class="mt-8 p-0">
<div class="flex items-center border-b border-foreground/15 p-5">
<h2 class="mr-auto text-base font-medium">Working with Dropplets</h2>
</div>
<div class="p-5">
<AccordionRoot class="border-none">
<AccordionItem value="faq-4-1">
<AccordionTrigger>
OpenSSL Essentials: Working with SSL Certificates, Private Keys
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-4-2">
<AccordionTrigger>
Understanding IP Addresses, Subnets, and CIDR Notation
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-4-3">
<AccordionTrigger>How To Troubleshoot Common HTTP Error Codes</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-4-4">
<AccordionTrigger>An Introduction to Securing your Linux VPS</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
</AccordionRoot>
</div>
</Box>
</div>
<!-- END: FAQ Content -->
</div>
</template>
+232
View File
@@ -0,0 +1,232 @@
<script lang="ts" setup>
import { Box } from '@/components/ui/box'
import {
AccordionRoot,
AccordionItem,
AccordionTrigger,
AccordionContent,
} from '@/components/ui/accordion'
import { Lucide } from '@/components/ui/lucide'
</script>
<template>
<div class="flex items-center">
<h2 class="mr-auto text-lg font-medium">FAQ Layout</h2>
</div>
<div class="grid grid-cols-12 gap-6">
<!-- BEGIN: FAQ Menu -->
<div class="col-span-12 lg:col-span-4 xl:col-span-3">
<Box class="mt-5 p-0">
<div class="flex flex-col gap-5 p-5">
<a
class="[&.active]:text-primary active flex items-center [&.active]:font-medium"
href=""
>
<Lucide class="mr-2 size-4" icon="Activity" /> About Our Products
</a>
<a class="[&.active]:text-primary flex items-center [&.active]:font-medium" href="">
<Lucide class="mr-2 size-4" icon="Box" /> Related License
</a>
<a class="[&.active]:text-primary flex items-center [&.active]:font-medium" href="">
<Lucide class="mr-2 size-4" icon="Lock" /> Single Application License
</a>
<a class="[&.active]:text-primary flex items-center [&.active]:font-medium" href="">
<Lucide class="mr-2 size-4" icon="Settings" /> Multi Application License
</a>
</div>
<div class="flex flex-col gap-5 border-t border-foreground/15 p-5">
<a class="[&.active]:text-primary flex items-center [&.active]:font-medium" href="">
<Lucide class="mr-2 size-4" icon="Activity" /> Term of Use
</a>
<a class="[&.active]:text-primary flex items-center [&.active]:font-medium" href="">
<Lucide class="mr-2 size-4" icon="Box" /> Author Fees
</a>
<a class="[&.active]:text-primary flex items-center [&.active]:font-medium" href="">
<Lucide class="mr-2 size-4" icon="Lock" /> Product Review
</a>
<a class="[&.active]:text-primary flex items-center [&.active]:font-medium" href="">
<Lucide class="mr-2 size-4" icon="Settings" /> Privacy Policy
</a>
</div>
<div class="flex flex-col gap-5 border-t border-foreground/15 p-5">
<a class="[&.active]:text-primary flex items-center [&.active]:font-medium" href="">
<Lucide class="mr-2 size-4" icon="Activity" /> About Our Products
</a>
<a class="[&.active]:text-primary flex items-center [&.active]:font-medium" href="">
<Lucide class="mr-2 size-4" icon="Box" /> Related License
</a>
<a class="[&.active]:text-primary flex items-center [&.active]:font-medium" href="">
<Lucide class="mr-2 size-4" icon="Lock" /> Single Application License
</a>
<a class="[&.active]:text-primary flex items-center [&.active]:font-medium" href="">
<Lucide class="mr-2 size-4" icon="Settings" /> Multi Application License
</a>
</div>
</Box>
</div>
<!-- END: FAQ Menu -->
<!-- BEGIN: FAQ Content -->
<div class="col-span-12 lg:col-span-8 xl:col-span-9">
<Box class="p-0 lg:mt-5">
<div class="flex items-center border-b border-foreground/15 p-5">
<h2 class="mr-auto text-base font-medium">About Our Products</h2>
</div>
<div class="p-5">
<AccordionRoot class="border-none" :default-value="['faq-1-1']">
<AccordionItem value="faq-1-1">
<AccordionTrigger>
OpenSSL Essentials: Working with SSL Certificates, Private Keys
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-1-2">
<AccordionTrigger>
Understanding IP Addresses, Subnets, and CIDR Notation
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-1-3">
<AccordionTrigger>How To Troubleshoot Common HTTP Error Codes</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-1-4">
<AccordionTrigger>An Introduction to Securing your Linux VPS</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
</AccordionRoot>
</div>
</Box>
<Box class="mt-8 p-0">
<div class="flex items-center border-b border-foreground/15 p-5">
<h2 class="mr-auto text-base font-medium">Related License</h2>
</div>
<div class="p-5">
<AccordionRoot class="border-none">
<AccordionItem value="faq-2-1">
<AccordionTrigger>
OpenSSL Essentials: Working with SSL Certificates, Private Keys
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-2-2">
<AccordionTrigger>
Understanding IP Addresses, Subnets, and CIDR Notation
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-2-3">
<AccordionTrigger>How To Troubleshoot Common HTTP Error Codes</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-2-4">
<AccordionTrigger>An Introduction to Securing your Linux VPS</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
</AccordionRoot>
</div>
</Box>
<Box class="mt-8 p-0">
<div class="flex items-center border-b border-foreground/15 p-5">
<h2 class="mr-auto text-base font-medium">Single Application License</h2>
</div>
<div class="p-5">
<AccordionRoot class="border-none">
<AccordionItem value="faq-3-1">
<AccordionTrigger>
OpenSSL Essentials: Working with SSL Certificates, Private Keys
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-3-2">
<AccordionTrigger>
Understanding IP Addresses, Subnets, and CIDR Notation
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-3-3">
<AccordionTrigger>How To Troubleshoot Common HTTP Error Codes</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-3-4">
<AccordionTrigger>An Introduction to Securing your Linux VPS</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
</AccordionRoot>
</div>
</Box>
</div>
<!-- END: FAQ Content -->
</div>
</template>
+271
View File
@@ -0,0 +1,271 @@
<script lang="ts" setup>
import { Box } from '@/components/ui/box'
import {
AccordionRoot,
AccordionItem,
AccordionTrigger,
AccordionContent,
} from '@/components/ui/accordion'
import { Lucide } from '@/components/ui/lucide'
</script>
<template>
<div class="flex items-center">
<h2 class="mr-auto text-lg font-medium">FAQ Layout</h2>
</div>
<div class="grid grid-cols-12 gap-6">
<!-- BEGIN: FAQ Menu -->
<div class="col-span-12 lg:col-span-4 xl:col-span-3">
<Box class="mt-5 p-0">
<div class="flex flex-col gap-1 px-4 pb-3 pt-5">
<a
class="[&.active]:bg-primary/5 active [&.active]:border-primary/10 [&.active]:text-primary flex items-center rounded-lg border border-transparent px-4 py-2 [&.active]:font-medium"
href=""
>
<Lucide class="mr-2 size-4" icon="Activity" />
<div class="flex-1 truncate">About Our Products</div>
</a>
<a
class="[&.active]:bg-primary/5 [&.active]:border-primary/10 [&.active]:text-primary flex items-center rounded-lg border border-transparent px-4 py-2 [&.active]:font-medium"
href=""
>
<Lucide class="mr-2 size-4" icon="Box" />
<div class="flex-1 truncate">Related License</div>
</a>
<a
class="[&.active]:bg-primary/5 [&.active]:border-primary/10 [&.active]:text-primary flex items-center rounded-lg border border-transparent px-4 py-2 [&.active]:font-medium"
href=""
>
<Lucide class="mr-2 size-4" icon="Lock" />
<div class="flex-1 truncate">Single Application License</div>
</a>
<a
class="[&.active]:bg-primary/5 [&.active]:border-primary/10 [&.active]:text-primary flex items-center rounded-lg border border-transparent px-4 py-2 [&.active]:font-medium"
href=""
>
<Lucide class="mr-2 size-4" icon="Settings" />
<div class="flex-1 truncate">Multi Application License</div>
</a>
</div>
<div class="flex flex-col gap-1 border-t border-foreground/15 px-4 py-3">
<a class="flex items-center px-4 py-2" href="">
<Lucide class="mr-2 size-4" icon="Activity" />
<div class="flex-1 truncate">Term of Use</div>
</a>
<a
class="[&.active]:bg-primary/5 [&.active]:border-primary/10 [&.active]:text-primary flex items-center rounded-lg border border-transparent px-4 py-2 [&.active]:font-medium"
href=""
>
<Lucide class="mr-2 size-4" icon="Box" />
<div class="flex-1 truncate">Author Fees</div>
</a>
<a
class="[&.active]:bg-primary/5 [&.active]:border-primary/10 [&.active]:text-primary flex items-center rounded-lg border border-transparent px-4 py-2 [&.active]:font-medium"
href=""
>
<Lucide class="mr-2 size-4" icon="Lock" />
<div class="flex-1 truncate">Product Review</div>
</a>
<a
class="[&.active]:bg-primary/5 [&.active]:border-primary/10 [&.active]:text-primary flex items-center rounded-lg border border-transparent px-4 py-2 [&.active]:font-medium"
href=""
>
<Lucide class="mr-2 size-4" icon="Settings" />
<div class="flex-1 truncate">Privacy Policy</div>
</a>
</div>
<div class="flex flex-col gap-1 border-t border-foreground/15 px-4 pb-5 pt-3">
<a class="flex items-center px-4 py-2" href="">
<Lucide class="mr-2 size-4" icon="Activity" />
<div class="flex-1 truncate">About Our Products</div>
</a>
<a
class="[&.active]:bg-primary/5 [&.active]:border-primary/10 [&.active]:text-primary flex items-center rounded-lg border border-transparent px-4 py-2 [&.active]:font-medium"
href=""
>
<Lucide class="mr-2 size-4" icon="Box" />
<div class="flex-1 truncate">Related License</div>
</a>
<a
class="[&.active]:bg-primary/5 [&.active]:border-primary/10 [&.active]:text-primary flex items-center rounded-lg border border-transparent px-4 py-2 [&.active]:font-medium"
href=""
>
<Lucide class="mr-2 size-4" icon="Lock" />
<div class="flex-1 truncate">Single Application License</div>
</a>
<a
class="[&.active]:bg-primary/5 [&.active]:border-primary/10 [&.active]:text-primary flex items-center rounded-lg border border-transparent px-4 py-2 [&.active]:font-medium"
href=""
>
<Lucide class="mr-2 size-4" icon="Settings" />
<div class="flex-1 truncate">Multi Application License</div>
</a>
</div>
</Box>
</div>
<!-- END: FAQ Menu -->
<!-- BEGIN: FAQ Content -->
<div class="col-span-12 lg:col-span-8 xl:col-span-9">
<Box class="p-0 lg:mt-5">
<div class="flex items-center border-b border-foreground/15 p-5">
<h2 class="mr-auto text-base font-medium">About Our Products</h2>
</div>
<div class="p-5">
<AccordionRoot :default-value="['faq-1-1']">
<AccordionItem value="faq-1-1">
<AccordionTrigger>
OpenSSL Essentials: Working with SSL Certificates, Private Keys
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-1-2">
<AccordionTrigger>
Understanding IP Addresses, Subnets, and CIDR Notation
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-1-3">
<AccordionTrigger>How To Troubleshoot Common HTTP Error Codes</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-1-4">
<AccordionTrigger>An Introduction to Securing your Linux VPS</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
</AccordionRoot>
</div>
</Box>
<Box class="mt-5 p-0">
<div class="flex items-center border-b border-foreground/15 p-5">
<h2 class="mr-auto text-base font-medium">Single Application License</h2>
</div>
<div class="p-5">
<AccordionRoot>
<AccordionItem value="faq-2-1">
<AccordionTrigger>
OpenSSL Essentials: Working with SSL Certificates, Private Keys
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-2-2">
<AccordionTrigger>
Understanding IP Addresses, Subnets, and CIDR Notation
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-2-3">
<AccordionTrigger>How To Troubleshoot Common HTTP Error Codes</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-2-4">
<AccordionTrigger>An Introduction to Securing your Linux VPS</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
</AccordionRoot>
</div>
</Box>
<Box class="mt-5 p-0">
<div class="flex items-center border-b border-foreground/15 p-5">
<h2 class="mr-auto text-base font-medium">Multi Application License</h2>
</div>
<div class="p-5">
<AccordionRoot>
<AccordionItem value="faq-3-1">
<AccordionTrigger>
OpenSSL Essentials: Working with SSL Certificates, Private Keys
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-3-2">
<AccordionTrigger>
Understanding IP Addresses, Subnets, and CIDR Notation
</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-3-3">
<AccordionTrigger>How To Troubleshoot Common HTTP Error Codes</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
<AccordionItem value="faq-3-4">
<AccordionTrigger>An Introduction to Securing your Linux VPS</AccordionTrigger>
<AccordionContent>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever since the 1500s, when an
unknown printer took a galley of type and scrambled it to make a type specimen book.
It has survived not only five centuries, but also the leap into electronic
typesetting, remaining essentially unchanged.
</AccordionContent>
</AccordionItem>
</AccordionRoot>
</div>
</Box>
</div>
<!-- END: FAQ Content -->
</div>
</template>
+265
View File
@@ -0,0 +1,265 @@
<script lang="ts" setup>
import fakers from '@/utils/faker'
import { Badge } from '@/components/ui/badge'
import { Box } from '@/components/ui/box'
import { Button } from '@/components/ui/button'
import { CheckboxRoot, CheckboxControl } from '@/components/ui/checkbox'
import { Field, FieldLabel } from '@/components/ui/field'
import { FileIcon } from '@/components/ui/file-icon'
import { Input } from '@/components/ui/input'
import { Lucide } from '@/components/ui/lucide'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import {
PopoverRoot,
PopoverTrigger,
PopoverPositioner,
PopoverContent,
} from '@/components/ui/popover'
</script>
<template>
<div class="grid grid-cols-10 gap-6">
<div class="col-span-10 lg:col-span-2">
<h2 class="mr-auto mt-2 text-lg font-medium">File Manager</h2>
<!-- BEGIN: File Manager Menu -->
<Box class="mt-6">
<div class="flex flex-col gap-2">
<a
class="[&.active]:bg-foreground/5 [&.active]:border-foreground/10 active flex items-center rounded-md border border-transparent px-3 py-2"
href=""
>
<Lucide class="mr-2 size-4" icon="Image" /> Images
<Badge variant="warning" look="outline" class="ms-auto">412</Badge>
</a>
<a
class="[&.active]:bg-foreground/5 [&.active]:border-foreground/10 flex items-center rounded-md border border-transparent px-3 py-2"
href=""
>
<Lucide class="mr-2 size-4" icon="Video" /> Videos
</a>
<a
class="[&.active]:bg-foreground/5 [&.active]:border-foreground/10 flex items-center rounded-md border border-transparent px-3 py-2"
href=""
>
<Lucide class="mr-2 size-4" icon="File" /> Documents
<Badge variant="warning" look="outline" class="ms-auto">34</Badge>
</a>
<a
class="[&.active]:bg-foreground/5 [&.active]:border-foreground/10 flex items-center rounded-md border border-transparent px-3 py-2"
href=""
>
<Lucide class="mr-2 size-4" icon="Users" /> Shared
</a>
<a
class="[&.active]:bg-foreground/5 [&.active]:border-foreground/10 flex items-center rounded-md border border-transparent px-3 py-2"
href=""
>
<Lucide class="mr-2 size-4" icon="Trash" /> Trash
</a>
</div>
<div class="mt-4 border-t border-foreground/15 pt-4">
<a class="flex items-center truncate px-3 py-2" href="">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 mr-3 h-2 w-2 rounded-full border [--color:var(--color-pending)]"
></div>
Custom Work
</a>
<a class="mt-2 flex items-center truncate rounded-md px-3 py-2" href="">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 mr-3 h-2 w-2 rounded-full border [--color:var(--color-success)]"
></div>
Important Meetings
</a>
<a class="mt-2 flex items-center truncate rounded-md px-3 py-2" href="">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 mr-3 h-2 w-2 rounded-full border [--color:var(--color-warning)]"
></div>
Work
</a>
<a class="mt-2 flex items-center truncate rounded-md px-3 py-2" href="">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 mr-3 h-2 w-2 rounded-full border [--color:var(--color-pending)]"
></div>
Design
</a>
<a class="mt-2 flex items-center truncate rounded-md px-3 py-2" href="">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 mr-3 h-2 w-2 rounded-full border [--color:var(--color-danger)]"
></div>
Next Week
</a>
<a class="mt-2 flex items-center truncate rounded-md px-3 py-2" href="">
<Lucide class="mr-2 size-4" icon="Plus" /> Add New Label
</a>
</div>
</Box>
<!-- END: File Manager Menu -->
</div>
<div class="col-span-10 lg:col-span-8">
<!-- BEGIN: File Manager Filter -->
<div class="flex flex-col-reverse items-center sm:flex-row">
<div class="relative mr-auto mt-3 w-full sm:mt-0 sm:w-auto">
<Lucide
class="absolute inset-y-0 left-0 z-10 my-auto ml-3 size-4 opacity-70"
icon="Search"
/>
<Input class="box w-full px-10 sm:w-64" type="text" placeholder="Search files" />
<PopoverRoot>
<PopoverTrigger as-child>
<a class="absolute inset-y-0 right-0 mr-3 flex items-center" href="#">
<Lucide class="size-4 cursor-pointer opacity-70" icon="ChevronDown" />
</a>
</PopoverTrigger>
<PopoverPositioner>
<PopoverContent class="ml-2 w-[30rem]">
<div class="grid grid-cols-12 gap-4 gap-y-3 p-3">
<Field class="col-span-6">
<FieldLabel class="text-xs" for="input-filter-1">File Name</FieldLabel>
<Input id="input-filter-1" type="text" placeholder="Type the file name" />
</Field>
<Field class="col-span-6">
<FieldLabel class="text-xs" for="input-filter-2">Shared With</FieldLabel>
<Input id="input-filter-2" type="text" placeholder="example@gmail.com" />
</Field>
<Field class="col-span-6">
<FieldLabel class="text-xs" for="input-filter-3">Created At</FieldLabel>
<Input id="input-filter-3" type="text" placeholder="Important Meeting" />
</Field>
<Field class="col-span-6">
<FieldLabel class="text-xs" for="input-filter-4">Size</FieldLabel>
<NativeSelect id="input-filter-4">
<NativeSelectOption>10</NativeSelectOption>
<NativeSelectOption>25</NativeSelectOption>
<NativeSelectOption>35</NativeSelectOption>
<NativeSelectOption>50</NativeSelectOption>
</NativeSelect>
</Field>
<div class="col-span-12 mt-3 flex items-center">
<Button class="ml-auto w-32" look="outline" variant="secondary">
Create Filter
</Button>
<Button class="ml-2 w-32" variant="primary"> Search </Button>
</div>
</div>
</PopoverContent>
</PopoverPositioner>
</PopoverRoot>
</div>
<div class="flex w-full sm:w-auto">
<Button class="box mr-2" look="outline" variant="primary"> Upload New Files </Button>
<MenuRoot class="w-auto">
<MenuTrigger as-child>
<Box as-child>
<Button variant="ghost" class="box flex items-center px-2">
<span class="flex size-5 items-center justify-center">
<Lucide class="size-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="share">
<Lucide class="mr-2 size-4" icon="File" /> Share Files
</MenuItem>
<MenuItem value="settings">
<Lucide class="mr-2 size-4" icon="Settings" /> Settings
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
</div>
<!-- END: File Manager Filter -->
<!-- BEGIN: Directory & Files -->
<div class="mt-5 grid grid-cols-2 gap-3 gap-y-8 sm:gap-x-5 md:grid-cols-4 lg:grid-cols-5">
<div v-for="(faker, fakerKey) in fakers" :key="fakerKey">
<Box class="relative rounded-md px-3 pb-5 pt-8 sm:px-5">
<div class="absolute left-0 top-0 ml-3 mt-3">
<CheckboxRoot :checked="faker.trueFalse[0]">
<CheckboxControl />
</CheckboxRoot>
</div>
<FileIcon
v-if="faker.files[0]!.type === 'Empty Folder'"
class="mx-auto w-3/5"
variant="empty-directory"
/>
<FileIcon
v-else-if="faker.files[0]!.type === 'Folder'"
class="mx-auto w-3/5"
variant="directory"
/>
<FileIcon
v-else-if="faker.files[0]!.type === 'Image'"
class="mx-auto w-3/5"
:src="faker.files[0]!.fileName"
variant="image"
/>
<FileIcon v-else class="mx-auto w-3/5" :type="faker.files[0]!.type" variant="file" />
<a class="mt-4 block truncate text-center font-medium" href="">
{{ faker.files[0]!.fileName.split('/').pop() }}
</a>
<div class="mt-0.5 text-center text-xs opacity-70">
{{ faker.files[0]!.size }}
</div>
<MenuRoot class="absolute right-0 top-0 ml-auto mr-2 mt-3 w-auto">
<MenuTrigger as-child>
<a class="block size-4" href="#">
<Lucide class="size-4 opacity-70" icon="MoreVertical" />
</a>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="share">
<Lucide class="mr-2 size-4" icon="Users" /> Share File
</MenuItem>
<MenuItem value="delete">
<Lucide class="mr-2 size-4" icon="Trash" /> Delete
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</Box>
</div>
</div>
<!-- END: Directory & Files -->
<!-- BEGIN: Pagination -->
<div class="mt-6 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="5000"
:pageSize="10"
:siblingCount="2"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>Previous</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>Next</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="box mt-3 w-20 sm:mt-0">
<NativeSelectOption>10</NativeSelectOption>
<NativeSelectOption>25</NativeSelectOption>
<NativeSelectOption>35</NativeSelectOption>
<NativeSelectOption>50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
</div>
</template>
+296
View File
@@ -0,0 +1,296 @@
<script lang="ts" setup>
import fakers from '@/utils/faker'
import { AvatarRoot, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Badge } from '@/components/ui/badge'
import { Box } from '@/components/ui/box'
import { Button } from '@/components/ui/button'
import { CheckboxRoot, CheckboxControl } from '@/components/ui/checkbox'
import { Field, FieldLabel } from '@/components/ui/field'
import { Input } from '@/components/ui/input'
import { Lucide } from '@/components/ui/lucide'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import {
PopoverRoot,
PopoverTrigger,
PopoverPositioner,
PopoverContent,
} from '@/components/ui/popover'
</script>
<template>
<div class="mt-8 grid grid-cols-10 gap-6">
<div class="col-span-10 lg:col-span-2">
<h2 class="mr-auto mt-2 text-lg font-medium">Inbox</h2>
<!-- BEGIN: Inbox Menu -->
<Box class="mt-6">
<Button class="w-full" type="button" variant="primary">
<Lucide class="size-4" icon="Edit" /> Compose
</Button>
<div class="mt-6 flex flex-col gap-2 border-t border-dashed border-foreground/[.08] pt-5">
<a
class="[&.active]:bg-foreground/5 [&.active]:border-foreground/10 active flex items-center rounded-md border border-transparent px-3 py-2"
href=""
>
<Lucide class="mr-2 size-4" icon="Mail" /> Inbox
<Badge class="ms-auto" look="outline" variant="warning"> 214 </Badge>
</a>
<a
class="[&.active]:bg-foreground/5 [&.active]:border-foreground/10 flex items-center rounded-md border border-transparent px-3 py-2"
href=""
>
<Lucide class="mr-2 size-4" icon="Star" /> Marked
</a>
<a
class="[&.active]:bg-foreground/5 [&.active]:border-foreground/10 flex items-center rounded-md border border-transparent px-3 py-2"
href=""
>
<Lucide class="mr-2 size-4" icon="Inbox" /> Draft
<Badge class="ms-auto" look="outline" variant="warning"> 21 </Badge>
</a>
<a
class="[&.active]:bg-foreground/5 [&.active]:border-foreground/10 flex items-center rounded-md border border-transparent px-3 py-2"
href=""
>
<Lucide class="mr-2 size-4" icon="Send" /> Sent
</a>
<a
class="[&.active]:bg-foreground/5 [&.active]:border-foreground/10 flex items-center rounded-md border border-transparent px-3 py-2"
href=""
>
<Lucide class="mr-2 size-4" icon="Trash" /> Trash
</a>
</div>
<div class="mt-4 border-t border-dashed border-foreground/[.08] pt-4">
<a class="flex items-center truncate px-3 py-2" href="">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 mr-3 h-2 w-2 rounded-full border [--color:var(--color-pending)]"
></div>
Custom Work
</a>
<a class="mt-2 flex items-center truncate rounded-md px-3 py-2" href="">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 mr-3 h-2 w-2 rounded-full border [--color:var(--color-success)]"
></div>
Important Meetings
</a>
<a class="mt-2 flex items-center truncate rounded-md px-3 py-2" href="">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 mr-3 h-2 w-2 rounded-full border [--color:var(--color-warning)]"
></div>
Work
</a>
<a class="mt-2 flex items-center truncate rounded-md px-3 py-2" href="">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 mr-3 h-2 w-2 rounded-full border [--color:var(--color-pending)]"
></div>
Design
</a>
<a class="mt-2 flex items-center truncate rounded-md px-3 py-2" href="">
<div
class="bg-(--color)/20 border-(--color)/60 me-3 mr-3 h-2 w-2 rounded-full border [--color:var(--color-danger)]"
></div>
Next Week
</a>
<a class="mt-2 flex items-center truncate rounded-md px-3 py-2" href="">
<Lucide class="mr-2 size-4" icon="Plus" /> Add New Label
</a>
</div>
</Box>
<!-- END: Inbox Menu -->
</div>
<div class="col-span-10 lg:col-span-8">
<!-- BEGIN: Inbox Filter -->
<div class="flex flex-col-reverse items-center sm:flex-row">
<div class="relative mr-auto mt-3 w-full sm:mt-0 sm:w-auto">
<Lucide
class="absolute inset-y-0 left-0 z-10 my-auto ml-3 size-4 opacity-70"
icon="Search"
/>
<Input class="w-full px-10 sm:w-64" type="text" placeholder="Search mail" />
<PopoverRoot>
<PopoverTrigger as-child>
<a class="absolute inset-y-0 right-0 mr-3 flex items-center" href="#">
<Lucide class="size-4 cursor-pointer opacity-70" icon="ChevronDown" />
</a>
</PopoverTrigger>
<PopoverPositioner>
<PopoverContent class="ml-2 w-[30rem]">
<div class="grid grid-cols-12 gap-4 gap-y-3 p-3">
<Field class="col-span-6">
<FieldLabel class="text-xs" for="input-filter-1">From</FieldLabel>
<Input id="input-filter-1" type="text" placeholder="example@gmail.com" />
</Field>
<Field class="col-span-6">
<FieldLabel class="text-xs" for="input-filter-2">To</FieldLabel>
<Input id="input-filter-2" type="text" placeholder="example@gmail.com" />
</Field>
<Field class="col-span-6">
<FieldLabel class="text-xs" for="input-filter-3">Subject</FieldLabel>
<Input id="input-filter-3" type="text" placeholder="Important Meeting" />
</Field>
<Field class="col-span-6">
<FieldLabel class="text-xs" for="input-filter-4">Has the Words</FieldLabel>
<Input id="input-filter-4" type="text" placeholder="Job, Work, Documentation" />
</Field>
<Field class="col-span-6">
<FieldLabel class="text-xs" for="input-filter-5">Doesn't Have</FieldLabel>
<Input id="input-filter-5" type="text" placeholder="Job, Work, Documentation" />
</Field>
<Field class="col-span-6">
<FieldLabel class="text-xs" for="input-filter-6">Size</FieldLabel>
<NativeSelect id="input-filter-6">
<NativeSelectOption value="10">10</NativeSelectOption>
<NativeSelectOption value="25">25</NativeSelectOption>
<NativeSelectOption value="35">35</NativeSelectOption>
<NativeSelectOption value="50">50</NativeSelectOption>
</NativeSelect>
</Field>
<div class="col-span-12 mt-3 flex items-center">
<Button look="outline" variant="secondary" class="ml-auto w-32">
Create Filter
</Button>
<Button class="ml-2 w-32" variant="primary"> Search </Button>
</div>
</div>
</PopoverContent>
</PopoverPositioner>
</PopoverRoot>
</div>
<div class="flex w-full sm:w-auto">
<Button class="mr-2" look="outline" variant="primary"> Start a Video Call </Button>
<MenuRoot class="w-auto">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex size-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="contacts">
<Lucide class="mr-2 h-4 w-4" icon="User" /> Contacts
</MenuItem>
<MenuItem value="settings">
<Lucide class="mr-2 h-4 w-4" icon="Settings" /> Settings
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
</div>
<!-- END: Inbox Filter -->
<!-- BEGIN: Inbox Content -->
<Box class="mt-5 p-0">
<div
class="flex flex-col-reverse border-b border-foreground/15 px-5 py-6 opacity-70 sm:flex-row"
>
<div
class="-mx-5 mt-3 flex items-center border-t border-foreground/15 px-5 pt-5 sm:mx-0 sm:mt-0 sm:border-0 sm:px-0 sm:pt-0"
>
<CheckboxRoot>
<CheckboxControl />
</CheckboxRoot>
<MenuRoot class="ml-1" :positioning="{ placement: 'bottom-start' }">
<MenuTrigger as-child>
<a class="block size-5" href="#">
<Lucide class="size-5" icon="ChevronDown" />
</a>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-32">
<MenuItem value="all">All</MenuItem>
<MenuItem value="none">None</MenuItem>
<MenuItem value="read">Read</MenuItem>
<MenuItem value="unread">Unread</MenuItem>
<MenuItem value="starred">Starred</MenuItem>
<MenuItem value="unstarred">Unstarred</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
<a class="ml-5 flex size-5 items-center justify-center" href="#">
<Lucide class="size-4" icon="RefreshCw" />
</a>
<a class="ml-5 flex size-5 items-center justify-center" href="#">
<Lucide class="size-4" icon="MoreHorizontal" />
</a>
</div>
<div class="flex items-center sm:ml-auto">
<div>1 - 50 of 5,238</div>
<a class="ml-5 flex size-5 items-center justify-center" href="#">
<Lucide class="size-4" icon="ChevronLeft" />
</a>
<a class="ml-5 flex size-5 items-center justify-center" href="#">
<Lucide class="size-4" icon="ChevronRight" />
</a>
<a class="ml-5 flex size-5 items-center justify-center" href="#">
<Lucide class="size-4" icon="Settings" />
</a>
</div>
</div>
<div class="overflow-x-auto sm:overflow-x-visible">
<div
v-for="(faker, index) in fakers"
:key="index"
:class="[
'transition duration-200 ease-in-out transform cursor-pointer inline-block sm:block border-b border-foreground/[.08] mx-px',
'hover:scale-[1.02] hover:relative hover:z-20 hover:shadow-md hover:border-0 hover:rounded',
!faker['trueFalse'][0] ? 'bg-foreground/5 opacity-90' : 'bg-background',
]"
>
<div class="flex px-5 py-3.5">
<div class="mr-5 flex w-72 flex-none items-center">
<CheckboxRoot>
<CheckboxControl />
</CheckboxRoot>
<a
class="ml-4 flex size-5 flex-none items-center justify-center opacity-60"
href="#"
>
<Lucide class="size-4" icon="Star" />
</a>
<a
class="ml-2 flex size-5 flex-none items-center justify-center opacity-60"
href="#"
>
<Lucide class="size-4" icon="Bookmark" />
</a>
<AvatarRoot class="ml-5 size-7 rounded-full">
<AvatarFallback>{{ faker['users'][0]!['name'].substring(0, 2) }}</AvatarFallback>
<AvatarImage :src="faker['photos'][0]" :alt="faker['users'][0]!['name']" />
</AvatarRoot>
<div :class="['ml-3 truncate', { 'font-medium': faker['trueFalse'][0] }]">
{{ faker['users'][0]!['name'] }}
</div>
</div>
<div class="w-64 truncate sm:w-auto">
<span :class="['ml-3 truncate', { 'font-medium': faker['trueFalse'][0] }]">
{{ faker['news'][0]!['superShortContent'] }}
</span>
{{ faker['news'][0]!['shortContent'] }}
</div>
<div
:class="[
'pl-10 ml-auto whitespace-nowrap',
{ 'font-medium': faker['trueFalse'][0] },
]"
>
{{ faker['times'][0] }}
</div>
</div>
</div>
</div>
<div
class="flex flex-col items-center px-5 py-6 text-center opacity-70 sm:flex-row sm:text-left"
>
<div>4.41 GB (25%) of 17 GB used Manage</div>
<div class="mt-2 sm:ml-auto sm:mt-0">Last account activity: 36 minutes ago</div>
</div>
</Box>
<!-- END: Inbox Content -->
</div>
</div>
</template>
+137
View File
@@ -0,0 +1,137 @@
<script lang="ts" setup>
import { Button } from '@/components/ui/button'
import { Box } from '@/components/ui/box'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import {
Table,
TableHeader,
TableBody,
TableHead,
TableRow,
TableCell,
} from '@/components/ui/table'
import { Lucide } from '@/components/ui/lucide'
</script>
<template>
<div class="mt-8 flex flex-col items-center sm:flex-row">
<h2 class="mr-auto text-lg font-medium">Invoice Layout</h2>
<div class="mt-4 flex w-full sm:mt-0 sm:w-auto">
<Button look="outline" class="mr-2 shadow-sm" variant="primary"> Print </Button>
<MenuRoot class="w-auto ml-auto sm:ml-0">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="word">
<Lucide class="mr-2 h-4 w-4" icon="File" /> Export Word
</MenuItem>
<MenuItem value="pdf">
<Lucide class="mr-2 h-4 w-4" icon="File" /> Export PDF
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
</div>
<!-- BEGIN: Invoice -->
<Box class="mt-5">
<div
class="bg-primary/[.01] border-primary/20 relative overflow-hidden rounded-xl border text-center sm:text-left before:bg-noise before:absolute before:inset-0 before:opacity-30 after:bg-accent after:absolute after:inset-0 after:opacity-30 after:blur-2xl"
>
<div class="px-5 py-10 sm:px-20 sm:py-20">
<div class="text-primary text-2xl font-semibold">INVOICE</div>
<div class="mt-2">
Receipt <span class="font-medium">#1923195</span>
</div>
<div class="mt-1">Jan 02, 2021</div>
</div>
<div class="flex flex-col px-5 pb-10 pt-10 sm:px-20 sm:pb-20 lg:flex-row">
<div>
<div class="text-base opacity-70">Client Details</div>
<div class="text-primary mt-2 text-lg font-medium">Arnold Schwarzenegger</div>
<div class="mt-1">arnodlschwarzenegger@gmail.com</div>
<div class="mt-1">260 W. Storm Street New York, NY 10025.</div>
</div>
<div class="mt-10 lg:ml-auto lg:mt-0 lg:text-right">
<div class="text-base opacity-70">Payment to</div>
<div class="text-primary mt-2 text-lg font-medium">Left4code</div>
<div class="mt-1">left4code@gmail.com</div>
</div>
</div>
</div>
<div class="px-5 py-10 sm:px-16 sm:py-20">
<Table>
<TableHeader>
<TableRow>
<TableHead class="whitespace-nowrap border-none pb-6">DESCRIPTION</TableHead>
<TableHead class="whitespace-nowrap border-none pb-6 text-right">QTY</TableHead>
<TableHead class="whitespace-nowrap border-none pb-6 text-right">PRICE</TableHead>
<TableHead class="whitespace-nowrap border-none pb-6 text-right">SUBTOTAL</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>
<div class="whitespace-nowrap font-medium">
Midone - Tailwind Admin Dashboard Template
</div>
<div class="mt-0.5 whitespace-nowrap text-sm opacity-70">Regular License</div>
</TableCell>
<TableCell class="text-right">2</TableCell>
<TableCell class="text-right">$25</TableCell>
<TableCell class="text-right font-medium">$50</TableCell>
</TableRow>
<TableRow>
<TableCell>
<div class="whitespace-nowrap font-medium">Vuejs Admin Template</div>
<div class="mt-0.5 whitespace-nowrap text-sm opacity-70">Regular License</div>
</TableCell>
<TableCell class="text-right">1</TableCell>
<TableCell class="text-right">$25</TableCell>
<TableCell class="text-right font-medium">$25</TableCell>
</TableRow>
<TableRow>
<TableCell>
<div class="whitespace-nowrap font-medium">React Admin Template</div>
<div class="mt-0.5 whitespace-nowrap text-sm opacity-70">Regular License</div>
</TableCell>
<TableCell class="text-right">1</TableCell>
<TableCell class="text-right">$25</TableCell>
<TableCell class="text-right font-medium">$25</TableCell>
</TableRow>
<TableRow>
<TableCell>
<div class="whitespace-nowrap font-medium">Laravel Admin Template</div>
<div class="mt-0.5 whitespace-nowrap text-sm opacity-70">Regular License</div>
</TableCell>
<TableCell class="text-right">3</TableCell>
<TableCell class="text-right">$25</TableCell>
<TableCell class="text-right font-medium">$75</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
<div class="flex flex-col-reverse px-5 pb-10 sm:flex-row sm:px-20 sm:pb-20">
<div class="mt-10 text-center sm:mt-0 sm:text-left">
<div class="text-base opacity-70">Bank Transfer</div>
<div class="text-primary mt-2 text-lg font-medium">Elon Musk</div>
<div class="mt-1 opacity-70">Bank Account : 098347234832</div>
<div class="mt-1 opacity-70">Code : LFT133243</div>
</div>
<div class="text-center sm:ml-auto sm:text-right">
<div class="text-base opacity-70">Total Amount</div>
<div class="text-primary mt-2 text-xl font-medium">$20.600.00</div>
<div class="mt-1 opacity-70">Taxes included</div>
</div>
</div>
</Box>
<!-- END: Invoice -->
</template>
+142
View File
@@ -0,0 +1,142 @@
<script lang="ts" setup>
import { Button } from '@/components/ui/button'
import { Box } from '@/components/ui/box'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import {
Table,
TableHeader,
TableBody,
TableHead,
TableRow,
TableCell,
} from '@/components/ui/table'
import { Lucide } from '@/components/ui/lucide'
</script>
<template>
<div class="mt-8 flex flex-col items-center sm:flex-row">
<h2 class="mr-auto text-lg font-medium">Invoice Layout</h2>
<div class="mt-4 flex w-full sm:mt-0 sm:w-auto">
<Button look="outline" class="mr-2 shadow-sm" variant="primary"> Print </Button>
<MenuRoot class="w-auto ml-auto sm:ml-0">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="word">
<Lucide class="mr-2 h-4 w-4" icon="File" /> Export Word
</MenuItem>
<MenuItem value="pdf">
<Lucide class="mr-2 h-4 w-4" icon="File" /> Export PDF
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
</div>
<!-- BEGIN: Invoice -->
<Box class="mt-5">
<div
class="bg-primary/[.01] border-primary/20 relative overflow-hidden rounded-xl border text-center sm:text-left before:bg-noise before:absolute before:inset-0 before:opacity-30 after:bg-accent after:absolute after:inset-0 after:opacity-30 after:blur-2xl"
>
<div
class="flex flex-col px-5 pt-10 text-center sm:px-20 sm:pt-20 sm:text-left lg:flex-row lg:pb-20"
>
<div class="text-primary text-3xl font-semibold">INVOICE</div>
<div class="mt-20 lg:ml-auto lg:mt-0 lg:text-right">
<div class="text-primary text-xl font-medium">Left4code</div>
<div class="mt-1">left4code@gmail.com</div>
<div class="mt-1">8023 Amerige Street Harriman, NY 10926.</div>
</div>
</div>
<div
class="flex flex-col px-5 pb-10 pt-10 text-center sm:px-20 sm:pb-20 sm:text-left lg:flex-row"
>
<div>
<div class="text-base opacity-70">Client Details</div>
<div class="text-primary mt-2 text-lg font-medium">Arnold Schwarzenegger</div>
<div class="mt-1">arnodlschwarzenegger@gmail.com</div>
<div class="mt-1">260 W. Storm Street New York, NY 10025.</div>
</div>
<div class="mt-10 lg:ml-auto lg:mt-0 lg:text-right">
<div class="text-base opacity-70">Receipt</div>
<div class="text-primary mt-2 text-lg font-medium">#1923195</div>
<div class="mt-1">Jan 02, 2021</div>
</div>
</div>
</div>
<div class="px-5 py-10 sm:px-16 sm:py-20">
<Table>
<TableHeader>
<TableRow>
<TableHead class="whitespace-nowrap border-none pb-6">DESCRIPTION</TableHead>
<TableHead class="whitespace-nowrap border-none pb-6 text-right">QTY</TableHead>
<TableHead class="whitespace-nowrap border-none pb-6 text-right">PRICE</TableHead>
<TableHead class="whitespace-nowrap border-none pb-6 text-right">SUBTOTAL</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>
<div class="whitespace-nowrap font-medium">
Midone - Tailwind Admin Dashboard Template
</div>
<div class="mt-0.5 whitespace-nowrap text-sm opacity-70">Regular License</div>
</TableCell>
<TableCell class="text-right">2</TableCell>
<TableCell class="text-right">$25</TableCell>
<TableCell class="text-right font-medium">$50</TableCell>
</TableRow>
<TableRow>
<TableCell>
<div class="whitespace-nowrap font-medium">Vuejs Admin Template</div>
<div class="mt-0.5 whitespace-nowrap text-sm opacity-70">Regular License</div>
</TableCell>
<TableCell class="text-right">1</TableCell>
<TableCell class="text-right">$25</TableCell>
<TableCell class="text-right font-medium">$25</TableCell>
</TableRow>
<TableRow>
<TableCell>
<div class="whitespace-nowrap font-medium">React Admin Template</div>
<div class="mt-0.5 whitespace-nowrap text-sm opacity-70">Regular License</div>
</TableCell>
<TableCell class="text-right">1</TableCell>
<TableCell class="text-right">$25</TableCell>
<TableCell class="text-right font-medium">$25</TableCell>
</TableRow>
<TableRow>
<TableCell>
<div class="whitespace-nowrap font-medium">Laravel Admin Template</div>
<div class="mt-0.5 whitespace-nowrap text-sm opacity-70">Regular License</div>
</TableCell>
<TableCell class="text-right">3</TableCell>
<TableCell class="text-right">$25</TableCell>
<TableCell class="text-right font-medium">$75</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
<div class="flex flex-col-reverse px-5 pb-10 sm:flex-row sm:px-20 sm:pb-20">
<div class="mt-10 text-center sm:mt-0 sm:text-left">
<div class="text-base opacity-70">Bank Transfer</div>
<div class="text-primary mt-2 text-lg font-medium">Elon Musk</div>
<div class="mt-1 opacity-70">Bank Account : 098347234832</div>
<div class="mt-1 opacity-70">Code : LFT133243</div>
</div>
<div class="text-center sm:ml-auto sm:text-right">
<div class="text-base opacity-70">Total Amount</div>
<div class="text-primary mt-2 text-xl font-medium">$20.600.00</div>
<div class="mt-1 opacity-70">Taxes included</div>
</div>
</div>
</Box>
<!-- END: Invoice -->
</template>
+333
View File
@@ -0,0 +1,333 @@
<script lang="ts" setup>
import { ref } from 'vue'
import fakers from '@/utils/faker'
import { Box } from '@/components/ui/box'
import { Button } from '@/components/ui/button'
import {
DialogRoot,
DialogContent,
DialogTitle,
DialogDescription,
DialogCloseTrigger,
} from '@/components/ui/dialog'
import { Field, FieldLabel } from '@/components/ui/field'
import { Input } from '@/components/ui/input'
import { Lucide } from '@/components/ui/lucide'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import { TabsRoot, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'
import { Textarea } from '@/components/ui/textarea'
const newOrderDialogOpen = ref(false)
const addItemDialogOpen = ref(false)
</script>
<template>
<div>
<div class="flex flex-col items-center sm:flex-row">
<h2 class="mr-auto text-lg font-medium">Point of Sale</h2>
<div class="mt-4 flex w-full sm:mt-0 sm:w-auto">
<Button
class="box mr-2"
href="#"
as="a"
variant="primary"
look="outline"
@click.prevent="newOrderDialogOpen = true"
>
New Order
</Button>
<MenuRoot class="ml-auto sm:ml-0">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex size-5 items-center justify-center">
<Lucide class="size-4" icon="ChevronDown" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-auto">
<MenuItem value="0">
<Lucide class="mr-2 size-4" icon="Activity" />
<span class="truncate"> INV-0206020 - {{ fakers[3]!['users'][0]!['name'] }} </span>
</MenuItem>
<MenuItem value="1">
<Lucide class="mr-2 size-4" icon="Activity" />
<span class="truncate"> INV-0206022 - {{ fakers[4]!['users'][0]!['name'] }} </span>
</MenuItem>
<MenuItem value="2">
<Lucide class="mr-2 size-4" icon="Activity" />
<span class="truncate"> INV-0206021 - {{ fakers[5]!['users'][0]!['name'] }} </span>
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
</div>
<div class="mt-5 grid grid-cols-12 gap-5">
<!-- BEGIN: Item List -->
<div class="col-span-12 lg:col-span-8">
<div class="lg:flex">
<div class="relative">
<Input
class="box w-full px-4 py-3 pr-10 lg:w-64"
type="text"
placeholder="Search item..."
/>
<Lucide
class="absolute inset-y-0 right-0 my-auto mr-3 size-4 opacity-70"
icon="Search"
/>
</div>
<NativeSelect class="box ml-auto mt-3 w-full lg:mt-0 lg:w-auto">
<NativeSelectOption>Sort By</NativeSelectOption>
<NativeSelectOption>A to Z</NativeSelectOption>
<NativeSelectOption>Z to A</NativeSelectOption>
<NativeSelectOption>Lowest Price</NativeSelectOption>
<NativeSelectOption>Highest Price</NativeSelectOption>
</NativeSelect>
</div>
<div class="mt-5 grid grid-cols-12 gap-x-5 gap-y-4">
<Box
raised="single"
class="group col-span-12 cursor-pointer sm:col-span-4 2xl:col-span-3 [&.active]:border-primary/25 [&.active]:bg-primary/10 [&.active]:text-primary"
>
<div class="text-base font-medium">Soup</div>
<div class="mt-1 text-xs opacity-70">5 Items</div>
</Box>
<Box
raised="single"
class="group col-span-12 cursor-pointer sm:col-span-4 2xl:col-span-3 active [&.active]:border-primary/25 [&.active]:bg-primary/10 [&.active]:text-primary"
>
<div class="text-base font-medium">Pancake &amp; Toast</div>
<div class="mt-1 text-xs opacity-70">8 Items</div>
</Box>
<Box
raised="single"
class="group col-span-12 cursor-pointer sm:col-span-4 2xl:col-span-3 [&.active]:border-primary/25 [&.active]:bg-primary/10 [&.active]:text-primary"
>
<div class="text-base font-medium">Pasta</div>
<div class="mt-1 text-xs opacity-70">4 Items</div>
</Box>
<Box
raised="single"
class="group col-span-12 cursor-pointer sm:col-span-4 2xl:col-span-3 [&.active]:border-primary/25 [&.active]:bg-primary/10 [&.active]:text-primary"
>
<div class="text-base font-medium">Waffle</div>
<div class="mt-1 text-xs opacity-70">3 Items</div>
</Box>
<Box
raised="single"
class="group col-span-12 cursor-pointer sm:col-span-4 2xl:col-span-3 [&.active]:border-primary/25 [&.active]:bg-primary/10 [&.active]:text-primary"
>
<div class="text-base font-medium">Snacks</div>
<div class="mt-1 text-xs opacity-70">8 Items</div>
</Box>
<Box
raised="single"
class="group col-span-12 cursor-pointer sm:col-span-4 2xl:col-span-3 [&.active]:border-primary/25 [&.active]:bg-primary/10 [&.active]:text-primary"
>
<div class="text-base font-medium">Deserts</div>
<div class="mt-1 text-xs opacity-70">8 Items</div>
</Box>
<Box
raised="single"
class="group col-span-12 cursor-pointer sm:col-span-4 2xl:col-span-3 [&.active]:border-primary/25 [&.active]:bg-primary/10 [&.active]:text-primary"
>
<div class="text-base font-medium">Beverage</div>
<div class="mt-1 text-xs opacity-70">9 Items</div>
</Box>
</div>
<div class="mt-10 grid grid-cols-12 gap-x-5 gap-y-8 border-t border-foreground/15 pt-5">
<a
v-for="(faker, index) in fakers.slice(0, 8)"
:key="index"
class="col-span-12 block sm:col-span-4 2xl:col-span-3"
href="#"
@click.prevent="addItemDialogOpen = true"
>
<Box class="relative p-3">
<div class="relative block flex-none before:block before:w-full before:pt-[100%]">
<div class="image-fit absolute left-0 top-0 h-full w-full">
<img
class="rounded-lg"
:src="faker['foods'][0]!['image']"
alt="Midone - Tailwind Admin Dashboard Template"
/>
</div>
</div>
<div class="mt-3 block truncate text-center font-medium">
{{ faker['foods'][0]!['name'] }}
</div>
</Box>
</a>
</div>
</div>
<!-- END: Item List -->
<!-- BEGIN: Ticket -->
<TabsRoot defaultValue="ticket" class="col-span-12 lg:col-span-4">
<Box class="p-4">
<TabsList class="m-0 w-full">
<TabsTrigger class="w-1/2" value="ticket">Ticket</TabsTrigger>
<TabsTrigger class="w-1/2" value="details">Details</TabsTrigger>
</TabsList>
</Box>
<TabsContent value="ticket" class="mt-2 space-y-5">
<Box class="p-2">
<a
v-for="(faker, index) in fakers.slice(0, 5)"
:key="index"
class="hover:bg-foreground/5 flex cursor-pointer items-center rounded-lg px-4 py-3 transition duration-300 ease-in-out"
href="#"
@click.prevent="addItemDialogOpen = true"
>
<div class="mr-1 max-w-[50%] truncate">
{{ faker['foods'][0]!['name'] }}
</div>
<div class="opacity-70">x 1</div>
<Lucide class="ml-2 size-4 opacity-70" icon="Edit" />
<div class="ml-auto font-medium">${{ faker['totals'][0] }}</div>
</a>
</Box>
<Box>
<div class="flex gap-2">
<Input class="bg-foreground/[.03]" type="text" placeholder="Use coupon code..." />
<Button variant="primary" look="outline"> Apply </Button>
</div>
</Box>
<Box>
<div class="flex">
<div class="mr-auto">Subtotal</div>
<div class="font-medium">$250</div>
</div>
<div class="mt-4 flex">
<div class="mr-auto">Discount</div>
<div class="text-danger font-medium">-$20</div>
</div>
<div class="mt-4 flex">
<div class="mr-auto">Tax</div>
<div class="font-medium">15%</div>
</div>
<div class="mt-4 flex border-t border-foreground/15 pt-4">
<div class="mr-auto text-base font-medium">Total Charge</div>
<div class="text-base font-medium">$220</div>
</div>
</Box>
<div>
<Button class="box ml-auto w-full" variant="primary"> Charge </Button>
<Box as-child>
<Button class="box mt-3 w-full" variant="ghost"> Clear Items </Button>
</Box>
</div>
</TabsContent>
<TabsContent value="details" class="mt-2">
<Box>
<div class="flex items-center border-b border-foreground/15 pb-5">
<div>
<div class="opacity-70">Time</div>
<div class="mt-1">02/06/20 02:10 PM</div>
</div>
<Lucide class="ml-auto size-4 opacity-70" icon="Clock" />
</div>
<div class="flex items-center border-b border-foreground/15 py-5">
<div>
<div class="opacity-70">Customer</div>
<div class="mt-1">{{ fakers[0]!['users'][0]!['name'] }}</div>
</div>
<Lucide class="ml-auto size-4 opacity-70" icon="User" />
</div>
<div class="flex items-center border-b border-foreground/15 py-5">
<div>
<div class="opacity-70">People</div>
<div class="mt-1">3</div>
</div>
<Lucide class="ml-auto size-4 opacity-70" icon="Users" />
</div>
<div class="flex items-center pt-5">
<div>
<div class="opacity-70">Table</div>
<div class="mt-1">21</div>
</div>
<Lucide class="ml-auto size-4 opacity-70" icon="Mic" />
</div>
</Box>
</TabsContent>
</TabsRoot>
<!-- END: Ticket -->
</div>
<!-- BEGIN: New Order Modal -->
<DialogRoot
:open="newOrderDialogOpen"
@openChange="(details) => (newOrderDialogOpen = details.open)"
>
<DialogContent>
<DialogTitle>New Order</DialogTitle>
<DialogDescription>
Enter the details of the new product to add it to your inventory. Ensure that all required
fields are filled correctly.
</DialogDescription>
<div class="grid grid-cols-12 gap-4 gap-y-3">
<Field class="col-span-12">
<FieldLabel for="pos-form-1">Name</FieldLabel>
<Input id="pos-form-1" type="text" placeholder="Customer name" />
</Field>
<Field class="col-span-12">
<FieldLabel for="pos-form-2">Table</FieldLabel>
<Input id="pos-form-2" type="text" placeholder="Customer table" />
</Field>
<Field class="col-span-12">
<FieldLabel for="pos-form-3">Number of People</FieldLabel>
<Input id="pos-form-3" type="text" placeholder="People" />
</Field>
</div>
<div class="flex gap-2 justify-end mt-7">
<DialogCloseTrigger> Cancel </DialogCloseTrigger>
<Button type="button" variant="primary"> Create Ticket </Button>
</div>
<DialogCloseTrigger />
</DialogContent>
</DialogRoot>
<!-- END: New Order Modal -->
<!-- BEGIN: Add Item Modal -->
<DialogRoot
:open="addItemDialogOpen"
@openChange="(details) => (addItemDialogOpen = details.open)"
>
<DialogContent>
<DialogTitle>{{ fakers[0]!['foods'][0]!['name'] }}</DialogTitle>
<DialogDescription>
Fill in the details to add a new product to your inventory. Adjust the initial stock
quantity as needed to ensure accurate tracking.
</DialogDescription>
<div class="grid grid-cols-12 gap-4 gap-y-3">
<Field class="col-span-12">
<FieldLabel for="pos-form-4">Quantity</FieldLabel>
<div class="flex flex-1 gap-1">
<Button class="w-12" type="button" look="outline"> - </Button>
<Input
class="w-24 text-center"
id="pos-form-4"
type="text"
value="2"
placeholder="Item quantity"
/>
<Button class="w-12" type="button" look="outline"> + </Button>
</div>
</Field>
<Field class="col-span-12">
<FieldLabel for="pos-form-5">Notes</FieldLabel>
<Textarea id="pos-form-5" placeholder="Item notes" />
</Field>
</div>
<div class="flex gap-2 justify-end mt-7">
<DialogCloseTrigger> Cancel </DialogCloseTrigger>
<Button type="button" variant="primary"> Add Item </Button>
</div>
<DialogCloseTrigger />
</DialogContent>
</DialogRoot>
<!-- END: Add Item Modal -->
</div>
</template>
+481
View File
@@ -0,0 +1,481 @@
<script lang="ts" setup>
import { ref, computed } from 'vue'
import * as combobox from '@zag-js/combobox'
import fakers from '@/utils/faker'
import { AvatarRoot, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Box } from '@/components/ui/box'
import { Button } from '@/components/ui/button'
import {
ComboboxRoot,
ComboboxControl,
ComboboxTrigger,
ComboboxContent,
ComboboxInput,
ComboboxItemGroup,
ComboboxItemGroupLabel,
ComboboxItem,
ComboboxItemText,
} from '@/components/ui/combobox'
import {
DatePickerRoot,
DatePickerControl,
DatePickerInput,
DatePickerTrigger,
DatePickerClearTrigger,
DatePickerPositioner,
DatePickerContent,
DatePickerYearSelect,
DatePickerMonthSelect,
DatePickerView,
DatePickerViewControl,
DatePickerPrevTrigger,
DatePickerViewTrigger,
DatePickerNextTrigger,
DatePickerRangeText,
DatePickerTable,
DatePickerTableHead,
DatePickerTableRow,
DatePickerTableHeader,
DatePickerTableBody,
DatePickerTableCell,
DatePickerTableCellTrigger,
DatePickerContext,
} from '@/components/ui/datepicker'
import { Field, FieldLabel } from '@/components/ui/field'
import { Input } from '@/components/ui/input'
import { Lucide } from '@/components/ui/lucide'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import { SwitchRoot, SwitchControl } from '@/components/ui/switch'
import { TabsRoot, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'
import { Textarea } from '@/components/ui/textarea'
import {
TooltipRoot,
TooltipTrigger,
TooltipPositioner,
TooltipContent,
} from '@/components/ui/tooltip'
// Categories combobox data
const categoryData = [
{ label: 'Horror', code: 'horror' },
{ label: 'Sci-fi', code: 'sci-fi' },
{ label: 'Action', code: 'action' },
{ label: 'Drama', code: 'drama' },
{ label: 'Comedy', code: 'comedy' },
]
const categoryValue = ref(['Horror', 'Action'])
const categoryOptions = ref(categoryData)
const categoryCollection = computed(() =>
combobox.collection({
items: categoryOptions.value,
itemToValue: (item) => item.label,
}),
)
// Tags combobox data
const tagData = [
{ label: 'Leonardo DiCaprio', code: 'leonardo' },
{ label: 'Johnny Deep', code: 'johnny' },
{ label: 'Robert Downey, Jr', code: 'robert' },
{ label: 'Samuel L. Jackson', code: 'samuel' },
{ label: 'Morgan Freeman', code: 'morgan' },
]
const tagValue = ref(['Leonardo DiCaprio', 'Robert Downey, Jr'])
const tagOptions = ref(tagData)
const tagCollection = computed(() =>
combobox.collection({
items: tagOptions.value,
itemToValue: (item) => item.label,
}),
)
</script>
<template>
<div class="flex flex-col items-center sm:flex-row">
<h2 class="mr-auto text-lg font-medium">Add New Post</h2>
<div class="mt-4 flex w-full sm:mt-0 sm:w-auto">
<MenuRoot class="mr-2">
<MenuTrigger as-child>
<Box as-child>
<Button variant="ghost" class="box flex items-center">
English
<Lucide class="ml-2 size-4" icon="ChevronDown" />
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="english">
<Lucide class="mr-2 size-4" icon="Activity" />
<span class="truncate">English</span>
</MenuItem>
<MenuItem value="indonesian">
<Lucide class="mr-2 size-4" icon="Activity" />
<span class="truncate">Indonesian</span>
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
<Box as-child>
<Button class="box ml-auto mr-2 flex items-center sm:ml-0" type="button" variant="ghost">
<Lucide class="size-4" icon="Eye" /> Preview
</Button>
</Box>
<MenuRoot class="w-auto">
<MenuTrigger as-child>
<Button class="box flex items-center" variant="primary" look="outline">
<Lucide class="size-4" icon="Save" />
Save
<Lucide class="size-4" icon="ChevronDown" />
</Button>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="new-post">
<Lucide class="mr-2 size-4" icon="FileText" /> As New Post
</MenuItem>
<MenuItem value="draft">
<Lucide class="mr-2 size-4" icon="FileText" /> As Draft
</MenuItem>
<MenuItem value="export-pdf">
<Lucide class="mr-2 size-4" icon="FileText" /> Export to PDF
</MenuItem>
<MenuItem value="export-word">
<Lucide class="mr-2 size-4" icon="FileText" /> Export to Word
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
</div>
<div class="mt-5 grid grid-cols-12 gap-8">
<!-- BEGIN: Post Content -->
<div class="col-span-12 lg:col-span-8">
<Box raised="single">
<Input type="text" placeholder="Title" />
</Box>
<Box class="mt-8">
<TabsRoot defaultValue="content">
<TabsList class="w-full">
<TabsTrigger
class="w-full sm:w-1/3 inline-flex items-center justify-center"
value="content"
>
<Lucide class="mr-2 size-4" icon="FileText" /> Content
</TabsTrigger>
<TabsTrigger
class="w-full sm:w-1/3 inline-flex items-center justify-center"
value="meta-title"
>
<Lucide class="mr-2 size-4" icon="Code" /> Meta Title
</TabsTrigger>
<TabsTrigger
class="w-full sm:w-1/3 inline-flex items-center justify-center"
value="keywords"
>
<Lucide class="mr-2 size-4" icon="AlignLeft" /> Keywords
</TabsTrigger>
</TabsList>
<TabsContent value="content" class="mt-3.5">
<div class="rounded-lg border border-foreground/15 p-5">
<div class="flex items-center border-b border-foreground/15 pb-5 font-medium">
<Lucide class="mr-2 size-4" icon="ChevronDown" /> Text Content
</div>
<div class="mt-5">
<Textarea placeholder="Write your content here...">Content of the editor.</Textarea>
</div>
</div>
<div class="mt-5 rounded-lg border border-foreground/15 p-5">
<div class="flex items-center border-b border-foreground/15 pb-5 font-medium">
<Lucide class="mr-2 size-4" icon="ChevronDown" /> Caption & Images
</div>
<div class="mt-5">
<Field>
<FieldLabel for="post-form-7">Caption</FieldLabel>
<Input id="post-form-7" type="text" placeholder="Write caption" />
</Field>
<Field class="mt-3">
<FieldLabel>Upload Image</FieldLabel>
<div class="rounded-xl border-2 border-dashed pt-4 border-foreground/15">
<div class="flex flex-wrap px-4">
<div
v-for="(faker, index) in fakers.slice(0, 4)"
:key="index"
class="image-fit relative mb-5 mr-5 h-24 w-24 cursor-pointer"
>
<img
class="rounded-xl"
:src="faker.images[0]"
alt="Midone - Tailwind Admin Dashboard Template"
/>
<TooltipRoot>
<TooltipTrigger as-child>
<div
class="bg-(--color)/80 border-(--color) text-medium absolute right-0 top-0 -mr-2 -mt-2 flex size-5 cursor-pointer items-center justify-center rounded-full text-white [--color:var(--color-danger)]"
>
<Lucide class="size-4" icon="X" />
</div>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Remove this image?</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
</div>
</div>
<div class="relative flex cursor-pointer items-center px-4 pb-4">
<Lucide class="mr-2 size-4" icon="Image" />
<span class="text-primary mr-1">Upload a file</span>
or drag and drop
<Input class="absolute left-0 top-0 h-full w-full opacity-0" type="file" />
</div>
</div>
</Field>
</div>
</div>
</TabsContent>
</TabsRoot>
</Box>
</div>
<!-- END: Post Content -->
<!-- BEGIN: Post Info -->
<div class="col-span-12 lg:col-span-4">
<Box class="box p-5">
<Field>
<FieldLabel>Written By</FieldLabel>
<MenuRoot>
<MenuTrigger as-child>
<Button variant="ghost" class="border border-foreground/15 w-full">
<AvatarRoot class="mr-1 size-6 rounded-full">
<AvatarFallback>{{
fakers[0]!['users'][0]!['name'].substring(0, 2)
}}</AvatarFallback>
<AvatarImage
:src="fakers[0]!['photos'][0]"
:alt="fakers[0]!['users'][0]!['name']"
/>
</AvatarRoot>
<div class="truncate">{{ fakers[0]!['users'][0]!['name'] }}</div>
<Lucide class="ml-auto size-4" icon="ChevronDown" />
</Button>
</MenuTrigger>
<MenuPositioner>
<MenuContent>
<MenuItem
v-for="(faker, index) in fakers.slice(0, 5)"
:key="index"
:value="'author-' + index"
class="py-2"
>
<div class="size-5 image-fit me-1">
<img
class="rounded-full size-full"
:src="faker['photos'][0]"
alt="Midone - Tailwind Admin Dashboard Template"
/>
</div>
<div>{{ faker['users'][0]!['name'] }}</div>
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</Field>
<Field class="mt-3">
<FieldLabel>Post Date</FieldLabel>
<DatePickerRoot>
<DatePickerControl>
<DatePickerInput />
<DatePickerTrigger />
<DatePickerClearTrigger>Clear</DatePickerClearTrigger>
</DatePickerControl>
<Teleport to="body">
<DatePickerPositioner>
<DatePickerContent>
<DatePickerYearSelect />
<DatePickerMonthSelect />
<DatePickerView view="day">
<DatePickerContext v-slot="{ datePicker }">
<DatePickerViewControl>
<DatePickerPrevTrigger />
<DatePickerViewTrigger>
<DatePickerRangeText />
</DatePickerViewTrigger>
<DatePickerNextTrigger />
</DatePickerViewControl>
<DatePickerTable>
<DatePickerTableHead>
<DatePickerTableRow>
<DatePickerTableHeader
v-for="(weekDay, id) in datePicker?.weekDays"
:key="id"
>
{{ weekDay.short }}
</DatePickerTableHeader>
</DatePickerTableRow>
</DatePickerTableHead>
<DatePickerTableBody>
<DatePickerTableRow v-for="(week, id) in datePicker?.weeks" :key="id">
<DatePickerTableCell v-for="(day, id) in week" :key="id" :value="day">
<DatePickerTableCellTrigger>
{{ day.day }}
</DatePickerTableCellTrigger>
</DatePickerTableCell>
</DatePickerTableRow>
</DatePickerTableBody>
</DatePickerTable>
</DatePickerContext>
</DatePickerView>
<DatePickerView view="month">
<DatePickerContext v-slot="{ datePicker }">
<DatePickerViewControl>
<DatePickerPrevTrigger />
<DatePickerViewTrigger>
<DatePickerRangeText />
</DatePickerViewTrigger>
<DatePickerNextTrigger />
</DatePickerViewControl>
<DatePickerTable>
<DatePickerTableBody>
<DatePickerTableRow
v-for="(months, id) in datePicker?.getMonthsGrid({
columns: 4,
format: 'short',
})"
:key="id"
>
<DatePickerTableCell
v-for="(month, id) in months"
:key="id"
:value="month.value"
>
<DatePickerTableCellTrigger>{{
month.label
}}</DatePickerTableCellTrigger>
</DatePickerTableCell>
</DatePickerTableRow>
</DatePickerTableBody>
</DatePickerTable>
</DatePickerContext>
</DatePickerView>
<DatePickerView view="year">
<DatePickerContext v-slot="{ datePicker }">
<DatePickerViewControl>
<DatePickerPrevTrigger />
<DatePickerViewTrigger>
<DatePickerRangeText />
</DatePickerViewTrigger>
<DatePickerNextTrigger />
</DatePickerViewControl>
<DatePickerTable>
<DatePickerTableBody>
<DatePickerTableRow
v-for="(years, id) in datePicker?.getYearsGrid({
columns: 4,
})"
:key="id"
>
<DatePickerTableCell
v-for="(year, id) in years"
:key="id"
:value="year.value"
>
<DatePickerTableCellTrigger>{{
year.label
}}</DatePickerTableCellTrigger>
</DatePickerTableCell>
</DatePickerTableRow>
</DatePickerTableBody>
</DatePickerTable>
</DatePickerContext>
</DatePickerView>
</DatePickerContent>
</DatePickerPositioner>
</Teleport>
</DatePickerRoot>
</Field>
<Field class="mt-3">
<FieldLabel>Categories</FieldLabel>
<ComboboxRoot
:collection="categoryCollection"
:value="categoryValue"
@value-change="(details) => (categoryValue = details.value)"
@input-value-change="
({ inputValue }) => {
const filtered = categoryData.filter((item) =>
item.label.toLowerCase().includes(inputValue.toLowerCase()),
)
categoryOptions = filtered.length > 0 ? filtered : categoryData
}
"
class="w-full"
multiple
>
<ComboboxControl>
<ComboboxTrigger />
</ComboboxControl>
<ComboboxContent>
<ComboboxInput placeholder="Search categories..." />
<ComboboxItemGroup>
<ComboboxItemGroupLabel>Categories</ComboboxItemGroupLabel>
<ComboboxItem
v-for="item in categoryCollection.items"
:key="item.code"
:item="item"
>
<ComboboxItemText>{{ item.label }}</ComboboxItemText>
</ComboboxItem>
</ComboboxItemGroup>
</ComboboxContent>
</ComboboxRoot>
</Field>
<Field class="mt-3">
<FieldLabel>Tags</FieldLabel>
<ComboboxRoot
:collection="tagCollection"
:value="tagValue"
@value-change="(details) => (tagValue = details.value)"
@input-value-change="
({ inputValue }) => {
const filtered = tagData.filter((item) =>
item.label.toLowerCase().includes(inputValue.toLowerCase()),
)
tagOptions = filtered.length > 0 ? filtered : tagData
}
"
class="w-full"
multiple
>
<ComboboxControl>
<ComboboxTrigger />
</ComboboxControl>
<ComboboxContent>
<ComboboxInput placeholder="Search tags..." />
<ComboboxItemGroup>
<ComboboxItemGroupLabel>Tags</ComboboxItemGroupLabel>
<ComboboxItem v-for="item in tagCollection.items" :key="item.code" :item="item">
<ComboboxItemText>{{ item.label }}</ComboboxItemText>
</ComboboxItem>
</ComboboxItemGroup>
</ComboboxContent>
</ComboboxRoot>
</Field>
<Field class="mt-3">
<FieldLabel>Published</FieldLabel>
<SwitchRoot>
<SwitchControl />
</SwitchRoot>
</Field>
<Field class="mt-3">
<FieldLabel>Show Author Name</FieldLabel>
<SwitchRoot>
<SwitchControl />
</SwitchRoot>
</Field>
</Box>
</div>
<!-- END: Post Info -->
</div>
</template>
+131
View File
@@ -0,0 +1,131 @@
<script lang="ts" setup>
import { Button } from '@/components/ui/button'
import { Box } from '@/components/ui/box'
import { Lucide } from '@/components/ui/lucide'
</script>
<template>
<div class="flex items-center">
<h2 class="mr-auto text-lg font-medium">Pricing Layout</h2>
</div>
<!-- BEGIN: Pricing Layout -->
<Box class="mt-5 flex flex-col lg:flex-row">
<div class="flex-1 px-5 py-16">
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="CreditCard" />
<div class="mt-10 text-center text-xl font-medium">Basic Plan</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1"></span> 10 Users <span class="mx-1"></span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span> 35
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</div>
<div
class="flex-1 border-b border-t px-5 py-16 lg:border-b-0 lg:border-l lg:border-r lg:border-t-0 border-foreground/15"
>
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="Briefcase" />
<div class="mt-10 text-center text-xl font-medium">Business</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1"></span> 10 Users <span class="mx-1"></span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span> 60
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</div>
<div class="flex-1 px-5 py-16">
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="ShoppingBag" />
<div class="mt-10 text-center text-xl font-medium">Enterprise</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1"></span> 10 Users <span class="mx-1"></span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span> 120
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</div>
</Box>
<!-- END: Pricing Layout -->
<!-- BEGIN: Pricing Layout -->
<Box class="mt-8 flex flex-col lg:flex-row">
<div class="flex-1 px-5 py-16">
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="Activity" />
<div class="mt-10 text-center text-xl font-medium">Basic Plan</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1"></span> 10 Users <span class="mx-1"></span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span> 35
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</div>
<div
class="flex-1 border-b border-t px-5 py-16 lg:border-b-0 lg:border-l lg:border-r lg:border-t-0 border-foreground/15"
>
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="Box" />
<div class="mt-10 text-center text-xl font-medium">Business</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1"></span> 10 Users <span class="mx-1"></span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span> 60
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</div>
<div class="flex-1 px-5 py-16">
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="Send" />
<div class="mt-10 text-center text-xl font-medium">Enterprise</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1"></span> 10 Users <span class="mx-1"></span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span> 120
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</div>
</Box>
<!-- END: Pricing Layout -->
</template>
+279
View File
@@ -0,0 +1,279 @@
<script lang="ts" setup>
import { Button } from '@/components/ui/button'
import { Box } from '@/components/ui/box'
import { TabsRoot, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'
import { Lucide } from '@/components/ui/lucide'
</script>
<template>
<h2 class="mr-auto text-center text-2xl font-medium">Best Price &amp; Services</h2>
<div class="mt-6">
<TabsRoot defaultValue="monthly">
<!-- BEGIN: Pricing Tab -->
<div class="flex justify-center">
<Box raised="single" class="mx-auto w-96 p-3">
<TabsList class="mb-0 w-full">
<TabsTrigger class="w-1/2" value="monthly">Monthly Fees</TabsTrigger>
<TabsTrigger class="w-1/2" value="annual">Annual Fees</TabsTrigger>
</TabsList>
</Box>
</div>
<!-- END: Pricing Tab -->
<!-- BEGIN: Pricing Content -->
<TabsContent value="monthly" class="mt-8">
<div class="flex flex-col gap-5 lg:flex-row">
<div
class="flex flex-1 flex-col justify-center pb-10 text-center sm:px-10 lg:px-5 lg:pb-0"
>
<div class="text-lg font-medium">Monthly Product Pricing</div>
<div class="mt-3 indent-10 opacity-70 lg:text-justify">
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever.
</p>
<p class="mt-2">
When an unknown printer took a galley of type and scrambled it to make a type
specimen book. It has survived not only five centuries, but also the leap into
electronic typesetting, remaining essentially unchanged.
</p>
</div>
</div>
<Box class="flex-1 py-16">
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="Briefcase" />
<div class="mt-10 text-center text-xl font-medium">Business</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1">•</span> 10 Users <span class="mx-1">•</span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span>
60
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</Box>
<Box class="flex-1 py-16">
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="ShoppingBag" />
<div class="mt-10 text-center text-xl font-medium">Enterprise</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1">•</span> 10 Users <span class="mx-1">•</span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span>
120
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</Box>
</div>
</TabsContent>
<TabsContent value="annual" class="mt-8">
<div class="flex flex-col lg:flex-row">
<div
class="flex flex-1 flex-col justify-center pb-10 text-center sm:px-10 lg:px-5 lg:pb-0"
>
<div class="text-lg font-medium">Annual Product Pricing</div>
<div class="mt-3 opacity-70 lg:text-justify">
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever.
</p>
<p class="mt-2">
When an unknown printer took a galley of type and scrambled it to make a type
specimen book. It has survived not only five centuries, but also the leap into
electronic typesetting, remaining essentially unchanged.
</p>
</div>
</div>
<Box class="mb-5 flex-1 py-16 lg:mb-0 lg:ml-5">
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="Briefcase" />
<div class="mt-10 text-center text-xl font-medium">Business</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1"></span> 10 Users <span class="mx-1"></span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span>
40
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</Box>
<Box class="flex-1 py-16 lg:ml-5">
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="ShoppingBag" />
<div class="mt-10 text-center text-xl font-medium">Enterprise</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1"></span> 10 Users <span class="mx-1"></span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span>
90
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</Box>
</div>
</TabsContent>
<!-- END: Pricing Content -->
</TabsRoot>
</div>
<Box class="mt-20 px-8 py-12">
<h2 class="mr-auto text-center text-2xl font-medium">Best Price &amp; Services</h2>
<TabsRoot defaultValue="monthly2">
<!-- BEGIN: Pricing Tab -->
<div class="mt-6 flex justify-center">
<div class="mx-auto w-96 rounded-2xl border border-foreground/15 p-1">
<TabsList class="mb-0 w-full">
<TabsTrigger class="w-1/2" value="monthly2">Monthly Fees</TabsTrigger>
<TabsTrigger class="w-1/2" value="annual2">Annual Fees</TabsTrigger>
</TabsList>
</div>
</div>
<!-- END: Pricing Tab -->
<!-- BEGIN: Pricing Content -->
<TabsContent value="monthly2" class="mt-10">
<div class="flex flex-col lg:flex-row">
<div
class="flex flex-1 flex-col justify-center pb-10 text-center sm:px-10 lg:px-5 lg:pb-0"
>
<div class="text-lg font-medium">Monthly Product Pricing</div>
<div class="mt-3 indent-10 opacity-70 lg:text-justify">
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever.
</p>
<p class="mt-2">
When an unknown printer took a galley of type and scrambled it to make a type
specimen book. It has survived not only five centuries, but also the leap into
electronic typesetting, remaining essentially unchanged.
</p>
</div>
</div>
<div
class="flex-1 border-b border-t py-16 lg:ml-8 lg:border-b-0 lg:border-l lg:border-r lg:border-t-0 border-foreground/15"
>
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="Briefcase" />
<div class="mt-10 text-center text-xl font-medium">Business</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1">•</span> 10 Users <span class="mx-1">•</span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span>
60
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</div>
<div class="flex-1 py-16">
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="ShoppingBag" />
<div class="mt-10 text-center text-xl font-medium">Enterprise</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1">•</span> 10 Users <span class="mx-1">•</span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span>
120
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</div>
</div>
</TabsContent>
<TabsContent value="annual2" class="mt-10">
<div class="flex flex-col lg:flex-row">
<div
class="flex flex-1 flex-col justify-center pb-10 text-center sm:px-10 lg:px-5 lg:pb-0"
>
<div class="text-lg font-medium">Monthly Product Pricing</div>
<div class="mt-3 indent-10 opacity-70 lg:text-justify">
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
Ipsum has been the industry's standard dummy text ever.
</p>
<p class="mt-2">
When an unknown printer took a galley of type and scrambled it to make a type
specimen book. It has survived not only five centuries, but also the leap into
electronic typesetting, remaining essentially unchanged.
</p>
</div>
</div>
<div
class="flex-1 border-b border-t py-16 lg:ml-8 lg:border-b-0 lg:border-l lg:border-r lg:border-t-0 border-foreground/15"
>
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="Briefcase" />
<div class="mt-10 text-center text-xl font-medium">Business</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1"></span> 10 Users <span class="mx-1"></span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span>
120
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</div>
<div class="flex-1 py-16">
<Lucide class="text-primary mx-auto block size-12 stroke-1" icon="ShoppingBag" />
<div class="mt-10 text-center text-xl font-medium">Enterprise</div>
<div class="mt-5 text-center opacity-70">
1 Domain <span class="mx-1"></span> 10 Users <span class="mx-1"></span> 20 Copies
</div>
<div class="mx-auto mt-2 px-10 text-center opacity-70">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
<div class="flex justify-center">
<div class="relative mx-auto mt-8 text-5xl font-medium">
<span class="absolute left-0 top-0 -ml-4 text-2xl">$</span>
210
</div>
</div>
<Button look="outline" class="px-10 mx-auto mt-10 block rounded-full" variant="primary">
Purchase Now
</Button>
</div>
</div>
</TabsContent>
<!-- END: Pricing Content -->
</TabsRoot>
</Box>
</template>
+180
View File
@@ -0,0 +1,180 @@
<script lang="ts" setup>
import { ref } from 'vue'
import fakers from '@/utils/faker'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Badge } from '@/components/ui/badge'
import { Box } from '@/components/ui/box'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import { DialogRoot, DialogContent, DialogCloseTrigger } from '@/components/ui/dialog'
import { Lucide } from '@/components/ui/lucide'
const deleteConfirmationOpen = ref(false)
</script>
<template>
<div>
<h2 class="text-lg font-medium">Product List</h2>
<div class="mt-5 grid grid-cols-12 gap-x-6 gap-y-8">
<div class="col-span-12 mt-2 flex flex-wrap items-center sm:flex-nowrap">
<Button class="mr-2" look="outline" variant="primary"> Add New Product </Button>
<MenuRoot class="w-auto">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="print">
<Lucide class="mr-2 h-4 w-4" icon="Printer" /> Print
</MenuItem>
<MenuItem value="excel">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to Excel
</MenuItem>
<MenuItem value="pdf">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to PDF
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
<div class="mx-auto hidden opacity-70 md:block">Showing 1 to 10 of 150 entries</div>
<div class="mt-3 w-full sm:ml-auto sm:mt-0 sm:w-auto md:ml-0">
<div class="relative w-56">
<Input class="w-56 pr-10" type="text" placeholder="Search..." />
<Lucide class="absolute inset-y-0 right-0 my-auto mr-3 h-4 w-4" icon="Search" />
</div>
</div>
</div>
<!-- BEGIN: Data List -->
<div
v-for="(faker, index) in fakers.slice(0, 12)"
:key="index"
class="col-span-12 md:col-span-6 lg:col-span-4 xl:col-span-3"
>
<Box class="p-0">
<div class="p-5">
<div
class="image-fit h-40 overflow-hidden rounded-lg before:absolute before:left-0 before:top-0 before:z-10 before:block before:h-full before:w-full before:bg-gradient-to-t before:from-black before:to-black/10 2xl:h-56"
>
<img
class="rounded-lg"
:src="faker['images'][0]"
alt="Midone - Tailwind Admin Dashboard Template"
/>
<Badge
v-if="faker['trueFalse'][0]"
class="absolute top-0 z-10 m-5"
look="outline"
variant="pending"
>
Featured
</Badge>
<div class="absolute bottom-0 z-10 px-5 pb-6 text-white">
<a class="block text-base font-medium" href="">
{{ faker['products'][0]!['name'] }}
</a>
<span class="mt-3 text-xs opacity-70">
{{ faker['products'][0]!['category'] }}
</span>
</div>
</div>
<div class="mt-5 opacity-70">
<div class="flex items-center">
<Lucide class="mr-2 h-4 w-4" icon="Link" /> Price: ${{ faker['totals'][0] }}
</div>
<div class="mt-2 flex items-center">
<Lucide class="mr-2 h-4 w-4" icon="Layers" /> Remaining Stock:
{{ faker['stocks'][0] }}
</div>
<div class="mt-2 flex items-center">
<Lucide class="mr-2 h-4 w-4" icon="CheckSquare" />
Status:
{{ faker['trueFalse'][0] ? 'Active' : 'Inactive' }}
</div>
</div>
</div>
<div
class="flex items-center justify-center border-t border-foreground/[0.08] p-5 lg:justify-end"
>
<a class="text-primary mr-auto flex items-center" href="#">
<Lucide class="mr-1 h-4 w-4" icon="Eye" /> Preview
</a>
<a class="mr-3 flex items-center" href="#">
<Lucide class="mr-1 h-4 w-4" icon="CheckSquare" /> Edit
</a>
<a
class="text-danger flex items-center"
href="#"
@click.prevent="deleteConfirmationOpen = true"
>
<Lucide class="mr-1 h-4 w-4" icon="Trash" /> Delete
</a>
</div>
</Box>
</div>
<!-- END: Data List -->
<!-- BEGIN: Pagination -->
<div class="col-span-12 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="150"
:pageSize="10"
:siblingCount="1"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>Previous</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>Next</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="mt-3 w-20 sm:mt-0">
<NativeSelectOption value="10">10</NativeSelectOption>
<NativeSelectOption value="25">25</NativeSelectOption>
<NativeSelectOption value="35">35</NativeSelectOption>
<NativeSelectOption value="50">50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
<!-- BEGIN: Delete Confirmation Modal -->
<DialogRoot
:open="deleteConfirmationOpen"
@openChange="(details) => (deleteConfirmationOpen = details.open)"
>
<DialogContent>
<div class="p-5 text-center">
<Lucide class="text-danger mx-auto mt-3 size-16 stroke-1" icon="CircleX" />
<div class="mt-5 text-2xl font-medium">Are you sure?</div>
<div class="mt-2 opacity-70">
Do you really want to delete these records? <br />
This process cannot be undone.
</div>
</div>
<div class="px-5 pb-8 text-center">
<DialogCloseTrigger class="mr-2 w-24"> Cancel </DialogCloseTrigger>
<Button class="w-24" type="button" variant="danger" look="outline"> Delete </Button>
</div>
</DialogContent>
</DialogRoot>
<!-- END: Delete Confirmation Modal -->
</div>
</template>
+202
View File
@@ -0,0 +1,202 @@
<script lang="ts" setup>
import { ref } from 'vue'
import fakers from '@/utils/faker'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Box } from '@/components/ui/box'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import {
Table,
TableHeader,
TableBody,
TableHead,
TableRow,
TableCell,
} from '@/components/ui/table'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import { AvatarRoot, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import { DialogRoot, DialogContent, DialogCloseTrigger } from '@/components/ui/dialog'
import { Lucide } from '@/components/ui/lucide'
const deleteConfirmationOpen = ref(false)
</script>
<template>
<div>
<h2 class="text-lg font-medium">Product List</h2>
<div class="mt-5 grid grid-cols-12 gap-6">
<div class="col-span-12 mt-2 flex flex-wrap items-center sm:flex-nowrap">
<Button class="mr-2" look="outline" variant="primary"> Add New Product </Button>
<MenuRoot class="w-auto">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="print">
<Lucide class="mr-2 h-4 w-4" icon="Printer" /> Print
</MenuItem>
<MenuItem value="excel">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to Excel
</MenuItem>
<MenuItem value="pdf">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to PDF
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
<div class="mx-auto hidden opacity-70 md:block">Showing 1 to 10 of 150 entries</div>
<div class="mt-3 w-full sm:ml-auto sm:mt-0 sm:w-auto md:ml-0">
<div class="relative w-56">
<Input class="w-56 pr-10" type="text" placeholder="Search..." />
<Lucide class="absolute inset-y-0 right-0 my-auto mr-3 h-4 w-4" icon="Search" />
</div>
</div>
</div>
<!-- BEGIN: Data List -->
<div class="col-span-12 overflow-auto lg:overflow-visible">
<Table class="-mt-2" variant="boxed">
<TableHeader>
<TableRow>
<TableHead> IMAGES </TableHead>
<TableHead> PRODUCT NAME </TableHead>
<TableHead class="text-center"> STOCK </TableHead>
<TableHead class="text-center"> PRICE </TableHead>
<TableHead class="text-center"> STATUS </TableHead>
<TableHead class="text-center"> ACTIONS </TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow v-for="(faker, index) in fakers.slice(0, 9)" :key="index">
<TableCell>
<div class="flex">
<AvatarRoot class="size-11 rounded-full bg-background">
<AvatarFallback>IM</AvatarFallback>
<AvatarImage
:src="faker['images'][0]"
:alt="'Uploaded at ' + faker['dates'][0]"
/>
</AvatarRoot>
<AvatarRoot class="size-11 rounded-full bg-background -ms-5">
<AvatarFallback>IM</AvatarFallback>
<AvatarImage
:src="faker['images'][1]"
:alt="'Uploaded at ' + faker['dates'][1]"
/>
</AvatarRoot>
<AvatarRoot class="size-11 rounded-full bg-background -ms-5">
<AvatarFallback>IM</AvatarFallback>
<AvatarImage
:src="faker['images'][2]"
:alt="'Uploaded at ' + faker['dates'][2]"
/>
</AvatarRoot>
</div>
</TableCell>
<TableCell>
<a class="whitespace-nowrap font-medium" href="">
{{ faker['categories'][0]!['name'] }}
</a>
<div class="mt-0.5 whitespace-nowrap text-xs opacity-70">
{{ faker['products'][0]!['category'] }}
</div>
</TableCell>
<TableCell class="text-center">
{{ faker['stocks'][0] }}
</TableCell>
<TableCell class="text-center"> ${{ faker['totals'][0] }} </TableCell>
<TableCell>
<div
class="flex items-center justify-center"
:class="faker['trueFalse'][0] ? 'text-success' : 'text-danger'"
>
<Lucide class="mr-2 h-4 w-4" icon="CheckSquare" />
{{ faker['trueFalse'][0] ? 'Active' : 'Inactive' }}
</div>
</TableCell>
<TableCell>
<div class="flex items-center justify-center">
<a class="mr-3 flex items-center" href="">
<Lucide class="mr-1 h-4 w-4" icon="CheckSquare" />
Edit
</a>
<a
class="text-danger flex items-center"
href="#"
@click.prevent="deleteConfirmationOpen = true"
>
<Lucide class="mr-1 h-4 w-4" icon="Trash" />
Delete
</a>
</div>
</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
<!-- END: Data List -->
<!-- BEGIN: Pagination -->
<div class="col-span-12 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="150"
:pageSize="10"
:siblingCount="1"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>Previous</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>Next</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="mt-3 w-20 sm:mt-0">
<NativeSelectOption value="10">10</NativeSelectOption>
<NativeSelectOption value="25">25</NativeSelectOption>
<NativeSelectOption value="35">35</NativeSelectOption>
<NativeSelectOption value="50">50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
<!-- BEGIN: Delete Confirmation Modal -->
<DialogRoot
:open="deleteConfirmationOpen"
@openChange="(details) => (deleteConfirmationOpen = details.open)"
>
<DialogContent>
<div class="p-5 text-center">
<Lucide class="text-danger mx-auto mt-3 size-16 stroke-1" icon="CircleX" />
<div class="mt-5 text-2xl font-medium">Are you sure?</div>
<div class="mt-2 opacity-70">
Do you really want to delete these records? <br />
This process cannot be undone.
</div>
</div>
<div class="px-5 pb-8 text-center">
<DialogCloseTrigger class="mr-2 w-24"> Cancel </DialogCloseTrigger>
<Button class="w-24" type="button" variant="danger" look="outline"> Delete </Button>
</div>
</DialogContent>
</DialogRoot>
<!-- END: Delete Confirmation Modal -->
</div>
</template>
+206
View File
@@ -0,0 +1,206 @@
<script lang="ts" setup>
import fakers from '@/utils/faker'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Box } from '@/components/ui/box'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import {
Table,
TableHeader,
TableBody,
TableHead,
TableRow,
TableCell,
} from '@/components/ui/table'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import { CheckboxRoot, CheckboxControl } from '@/components/ui/checkbox'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import {
TooltipRoot,
TooltipTrigger,
TooltipPositioner,
TooltipContent,
} from '@/components/ui/tooltip'
import { Lucide } from '@/components/ui/lucide'
</script>
<template>
<h2 class="text-lg font-medium">Reviews</h2>
<div class="mt-5 grid grid-cols-12 gap-6">
<div class="col-span-12 mt-2 flex flex-wrap items-center sm:flex-nowrap">
<div class="flex w-full sm:w-auto">
<div class="relative w-56">
<Input class="w-56 pr-10" type="text" placeholder="Search..." />
<Lucide class="absolute inset-y-0 right-0 my-auto mr-3 h-4 w-4" icon="Search" />
</div>
<NativeSelect class="ml-2">
<NativeSelectOption value="Status">Status</NativeSelectOption>
<NativeSelectOption value="Waiting Payment">Waiting Payment</NativeSelectOption>
<NativeSelectOption value="Confirmed">Confirmed</NativeSelectOption>
<NativeSelectOption value="Packing">Packing</NativeSelectOption>
<NativeSelectOption value="Delivered">Delivered</NativeSelectOption>
<NativeSelectOption value="Completed">Completed</NativeSelectOption>
</NativeSelect>
</div>
<div class="mx-auto hidden opacity-70 md:block">Showing 1 to 10 of 150 entries</div>
<div class="mt-3 flex w-full items-center xl:mt-0 xl:w-auto">
<Button look="outline" class="mr-2">
<Lucide class="size-4" icon="FileText" />
Export to Excel
</Button>
<Button look="outline" class="mr-2">
<Lucide class="size-4" icon="FileText" />
Export to PDF
</Button>
<MenuRoot class="w-auto">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="print">
<Lucide class="mr-2 h-4 w-4" icon="Printer" /> Print
</MenuItem>
<MenuItem value="excel">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to Excel
</MenuItem>
<MenuItem value="pdf">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to PDF
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
</div>
<!-- BEGIN: Data List -->
<div class="col-span-12 overflow-auto lg:overflow-visible">
<Table class="-mt-2" variant="boxed">
<TableHeader>
<TableRow>
<TableHead>
<CheckboxRoot>
<CheckboxControl />
</CheckboxRoot>
</TableHead>
<TableHead> PRODUCT </TableHead>
<TableHead> NAME </TableHead>
<TableHead> RATING </TableHead>
<TableHead> POSTED </TableHead>
<TableHead class="text-center"> STATUS </TableHead>
<TableHead class="text-center"> ACTIONS </TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow v-for="(faker, index) in fakers.slice(0, 9)" :key="index">
<TableCell>
<CheckboxRoot>
<CheckboxControl />
</CheckboxRoot>
</TableCell>
<TableCell>
<div class="flex items-center">
<div class="image-fit h-10 w-10">
<TooltipRoot>
<TooltipTrigger as-child>
<img
class="rounded-lg shadow-md"
:src="faker['images'][0]"
alt="Midone - Tailwind Admin Dashboard Template"
/>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>{{ 'Uploaded at ' + faker['dates'][0] }}</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
</div>
<a class="ml-4 whitespace-nowrap font-medium" href="">
{{ faker['products'][0]!['name'] }}
</a>
</div>
</TableCell>
<TableCell>
<a class="flex items-center underline decoration-dotted" href="#">
{{ faker['users'][0]!['name'] }}
</a>
</TableCell>
<TableCell>
<div class="flex items-center">
<div class="flex items-center">
<Lucide
v-for="n in 4"
:key="'filled-' + n"
class="fill-pending/30 text-pending mr-1 h-4 w-4"
icon="Star"
/>
<Lucide class="fill-foreground/20 text-foreground/70 mr-1 h-4 w-4" icon="Star" />
</div>
<div class="ml-1 text-xs opacity-70">(4.5+)</div>
</div>
</TableCell>
<TableCell>
{{ faker['formattedTimes'][0] }}
</TableCell>
<TableCell>
<div
class="flex items-center justify-center"
:class="faker['trueFalse'][0] ? 'text-success' : 'text-danger'"
>
<Lucide class="mr-2 h-4 w-4" icon="CheckSquare" />
{{ faker['trueFalse'][0] ? 'Active' : 'Inactive' }}
</div>
</TableCell>
<TableCell>
<div class="flex items-center justify-center">
<a class="text-primary mr-5 flex items-center whitespace-nowrap" href="#">
<Lucide class="mr-1 h-4 w-4" icon="CheckSquare" />
View Details
</a>
</div>
</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
<!-- END: Data List -->
<!-- BEGIN: Pagination -->
<div class="col-span-12 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="150"
:pageSize="10"
:siblingCount="1"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>Previous</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>Next</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="mt-3 w-20 sm:mt-0">
<NativeSelectOption value="10">10</NativeSelectOption>
<NativeSelectOption value="25">25</NativeSelectOption>
<NativeSelectOption value="35">35</NativeSelectOption>
<NativeSelectOption value="50">50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
</template>
+287
View File
@@ -0,0 +1,287 @@
<script lang="ts" setup>
import { ref } from 'vue'
import fakers from '@/utils/faker'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Box } from '@/components/ui/box'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import { DialogRoot, DialogContent, DialogCloseTrigger } from '@/components/ui/dialog'
import { Lucide } from '@/components/ui/lucide'
const deleteConfirmationOpen = ref(false)
</script>
<template>
<div>
<div class="flex flex-col items-center sm:flex-row">
<h2 class="mr-auto text-lg font-medium">Seller Details</h2>
<div class="mt-4 flex w-full sm:mt-0 sm:w-auto">
<Button class="mr-2" look="outline" variant="primary"> Print </Button>
<MenuRoot class="ml-auto w-auto sm:ml-0">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="size-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="print">
<Lucide class="mr-2 size-4" icon="Printer" /> Print
</MenuItem>
<MenuItem value="word">
<Lucide class="mr-2 size-4" icon="FileText" /> Export to Word
</MenuItem>
<MenuItem value="pdf">
<Lucide class="mr-2 size-4" icon="FileText" /> Export to PDF
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
</div>
<!-- BEGIN: Seller Details -->
<div class="mt-5 grid grid-cols-11 gap-5">
<div class="col-span-12 lg:col-span-4 2xl:col-span-3">
<Box>
<div class="mb-5 flex items-center border-b border-foreground/[.08] pb-5">
<div class="truncate text-base font-medium">User Details</div>
<a class="text-primary ml-auto flex items-center" href="">
<Lucide class="mr-2 h-4 w-4" icon="Edit" /> More Details
</a>
</div>
<div class="flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Clipboard" />
Unique ID:
<a class="ml-1 underline decoration-dotted" href=""> SLR-20220217-2053411933 </a>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="User" />
Name:
<a class="ml-1 underline decoration-dotted" href="">
{{ fakers[0]!['users'][0]!['name'] }}
</a>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Calendar" />
Phone Number: +71828273732
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="MapPin" />
Address: 260 W. Storm Street New York, NY 10025.
</div>
<div class="mt-5 flex items-center border-t border-foreground/[.08] pt-5 font-medium">
<Button look="outline" class="w-full px-2 py-1" type="button"> Message User </Button>
</div>
</Box>
<Box class="mt-8">
<div class="mb-5 flex items-center border-b border-foreground/[.08] pb-5">
<div class="truncate text-base font-medium">Store Details</div>
<a class="text-primary ml-auto flex items-center" href="">
<Lucide class="mr-2 h-4 w-4" icon="Edit" /> More Details
</a>
</div>
<div class="flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Clipboard" />
Unique ID:
<a class="ml-1 underline decoration-dotted" href=""> STR-2053411933-20220217 </a>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="ShoppingBag" />
Name:
<a class="ml-1 underline decoration-dotted" href=""> Themeforest </a>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Calendar" />
Phone Number: +71828273732
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="MapPin" />
Address: 260 W. Storm Street New York, NY 10025.
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Calendar" />
Status:
<Badge class="ml-2" variant="success"> Active </Badge>
</div>
<div class="mt-5 flex items-center border-t border-foreground/[.08] pt-5 font-medium">
<Button look="outline" class="w-full px-2 py-1" type="button"> Change Status </Button>
</div>
</Box>
<Box class="mt-8">
<div class="mb-5 flex items-center border-b border-foreground/[.08] pb-5">
<div class="truncate text-base font-medium">Transaction Reports</div>
<a class="text-primary ml-auto flex items-center" href="">
<Lucide class="mr-2 h-4 w-4" icon="Edit" /> More Details
</a>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Clipboard" />
Avg. Daily Transactions:
<div class="ml-auto">$1,500.00</div>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Clipboard" />
Avg. Monthly Transactions:
<div class="ml-auto">$42,500.00</div>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Clipboard" />
Avg. Annually Transactions:
<div class="ml-auto">$1,012,500.00</div>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Star" />
Average Rating:
<div class="ml-auto">4.9+</div>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Album" />
Total Products:
<div class="ml-auto">7,120</div>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Archive" />
Total Transactions:
<div class="ml-auto">1.512.001</div>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Monitor" />
Active Disputes:
<div class="ml-auto">1</div>
</div>
</Box>
</div>
<div class="col-span-12 lg:col-span-7 2xl:col-span-8">
<div class="grid grid-cols-12 gap-x-5 gap-y-8">
<div
v-for="(faker, index) in fakers.slice(0, 9)"
:key="index"
class="col-span-12 sm:col-span-6 2xl:col-span-4"
>
<Box class="p-0">
<div class="p-5">
<div
class="image-fit h-40 overflow-hidden rounded-xl before:absolute before:left-0 before:top-0 before:z-10 before:block before:h-full before:w-full before:bg-gradient-to-t before:from-black before:to-black/10 2xl:h-56"
>
<img
class="rounded-xl"
:src="faker['images'][0]"
alt="Midone - Tailwind Admin Dashboard Template"
/>
<Badge
v-if="faker['trueFalse'][0]"
class="absolute top-0 z-10 m-5 text-white"
look="filled"
variant="pending"
>
Featured
</Badge>
<div class="absolute bottom-0 z-10 px-5 pb-6 text-white">
<a class="block text-base font-medium" href="">
{{ faker['products'][0]!['name'] }}
</a>
<span class="mt-3 text-xs text-white/90">
{{ faker['products'][0]!['category'] }}
</span>
</div>
</div>
<div class="mt-5 opacity-70">
<div class="flex items-center">
<Lucide class="mr-2 h-4 w-4" icon="Link" /> Price: ${{ faker['totals'][0] }}
</div>
<div class="mt-2 flex items-center">
<Lucide class="mr-2 h-4 w-4" icon="Layers" /> Remaining Stock:
{{ faker['stocks'][0] }}
</div>
<div class="mt-2 flex items-center">
<Lucide class="mr-2 h-4 w-4" icon="CheckSquare" />
Status: {{ faker['trueFalse'][0] ? 'Active' : 'Inactive' }}
</div>
</div>
</div>
<div
class="flex items-center justify-center border-t border-foreground/[.08] p-5 lg:justify-end"
>
<a class="text-primary mr-auto flex items-center" href="#">
<Lucide class="mr-1 h-4 w-4" icon="Eye" /> Preview
</a>
<a class="mr-3 flex items-center" href="#">
<Lucide class="mr-1 h-4 w-4" icon="CheckSquare" /> Edit
</a>
<a
class="text-danger flex items-center"
href="#"
@click.prevent="deleteConfirmationOpen = true"
>
<Lucide class="mr-1 h-4 w-4" icon="Trash" /> Delete
</a>
</div>
</Box>
</div>
</div>
<!-- BEGIN: Pagination -->
<div class="col-span-11 mt-6 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="150"
:pageSize="10"
:siblingCount="1"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>Previous</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>Next</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="mt-3 w-20 sm:mt-0">
<NativeSelectOption value="10">10</NativeSelectOption>
<NativeSelectOption value="25">25</NativeSelectOption>
<NativeSelectOption value="35">35</NativeSelectOption>
<NativeSelectOption value="50">50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
</div>
<!-- END: Seller Details -->
<!-- BEGIN: Delete Confirmation Modal -->
<DialogRoot
:open="deleteConfirmationOpen"
@openChange="(details) => (deleteConfirmationOpen = details.open)"
>
<DialogContent>
<div class="p-5 text-center">
<Lucide class="text-danger mx-auto mt-3 size-16 stroke-1" icon="CircleX" />
<div class="mt-5 text-2xl font-medium">Are you sure?</div>
<div class="mt-2 opacity-70">
Do you really want to delete these records? <br />
This process cannot be undone.
</div>
</div>
<div class="px-5 pb-8 text-center">
<DialogCloseTrigger class="mr-2 w-24"> Cancel </DialogCloseTrigger>
<Button class="w-24" type="button" variant="danger" look="outline"> Delete </Button>
</div>
</DialogContent>
</DialogRoot>
<!-- END: Delete Confirmation Modal -->
</div>
</template>
+224
View File
@@ -0,0 +1,224 @@
<script lang="ts" setup>
import { ref } from 'vue'
import fakers from '@/utils/faker'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Box } from '@/components/ui/box'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import {
Table,
TableHeader,
TableBody,
TableHead,
TableRow,
TableCell,
} from '@/components/ui/table'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import { CheckboxRoot, CheckboxControl } from '@/components/ui/checkbox'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import { DialogRoot, DialogContent, DialogCloseTrigger } from '@/components/ui/dialog'
import {
TooltipRoot,
TooltipTrigger,
TooltipPositioner,
TooltipContent,
} from '@/components/ui/tooltip'
import { Lucide } from '@/components/ui/lucide'
const deleteConfirmationOpen = ref(false)
const stores = ['Themeforest', 'Codecanyon', 'Graphicriver']
</script>
<template>
<div>
<h2 class="text-lg font-medium">Seller List</h2>
<div class="mt-5 grid grid-cols-12 gap-6">
<div class="col-span-12 mt-2 flex flex-wrap items-center sm:flex-nowrap">
<div class="flex w-full sm:w-auto">
<Button class="mr-2" look="outline" variant="primary"> Add New Seller </Button>
<MenuRoot class="w-auto">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="print">
<Lucide class="mr-2 h-4 w-4" icon="Printer" /> Print
</MenuItem>
<MenuItem value="excel">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to Excel
</MenuItem>
<MenuItem value="pdf">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to PDF
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
<div class="mx-auto hidden opacity-70 md:block">Showing 1 to 10 of 150 entries</div>
<div class="mt-3 flex w-full items-center xl:mt-0 xl:w-auto">
<div class="relative w-56">
<Input class="w-56 pr-10" type="text" placeholder="Search..." />
<Lucide class="absolute inset-y-0 right-0 my-auto mr-3 h-4 w-4" icon="Search" />
</div>
<NativeSelect class="ml-2 w-56 xl:w-24">
<NativeSelectOption value="Status">Status</NativeSelectOption>
<NativeSelectOption value="Active">Active</NativeSelectOption>
<NativeSelectOption value="Inactive">Inactive</NativeSelectOption>
</NativeSelect>
</div>
</div>
<!-- BEGIN: Data List -->
<div class="col-span-12 overflow-auto lg:overflow-visible">
<Table class="-mt-2" variant="boxed">
<TableHeader>
<TableRow>
<TableHead>
<CheckboxRoot>
<CheckboxControl />
</CheckboxRoot>
</TableHead>
<TableHead> SELLER </TableHead>
<TableHead> STORE </TableHead>
<TableHead> GENDER </TableHead>
<TableHead class="text-center"> STATUS </TableHead>
<TableHead class="text-right"> TOTAL PRODUCTS </TableHead>
<TableHead class="text-center"> ACTIONS </TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow v-for="(faker, index) in fakers.slice(0, 9)" :key="index">
<TableCell>
<CheckboxRoot>
<CheckboxControl />
</CheckboxRoot>
</TableCell>
<TableCell>
<div class="flex items-center">
<div class="image-fit h-9 w-9">
<TooltipRoot>
<TooltipTrigger as-child>
<img
class="rounded-lg shadow-md"
:src="faker['images'][0]"
alt="Midone - Tailwind Admin Dashboard Template"
/>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>{{ 'Uploaded at ' + faker['dates'][0] }}</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
</div>
<div class="ml-4">
<a class="whitespace-nowrap font-medium" href="">
{{ faker['users'][0]!['name'] }}
</a>
<div class="mt-0.5 whitespace-nowrap text-xs opacity-70">
{{ faker['users'][0]!['email'] }}
</div>
</div>
</div>
</TableCell>
<TableCell>
<a class="flex items-center underline decoration-dotted" href="#">
{{ stores[index % 3] }}
</a>
</TableCell>
<TableCell>
<div class="capitalize">{{ faker['users'][0]!['gender'] }}</div>
</TableCell>
<TableCell>
<div
class="flex items-center justify-center"
:class="faker['trueFalse'][0] ? 'text-success' : 'text-danger'"
>
<Lucide class="mr-2 h-4 w-4" icon="CheckSquare" />
{{ faker['trueFalse'][0] ? 'Active' : 'Inactive' }}
</div>
</TableCell>
<TableCell class="text-right"> {{ faker['totals'][0] }} Items </TableCell>
<TableCell>
<div class="flex items-center justify-center">
<a class="mr-3 flex items-center" href="">
<Lucide class="mr-1 h-4 w-4" icon="CheckSquare" />
Edit
</a>
<a
class="text-danger flex items-center"
href="#"
@click.prevent="deleteConfirmationOpen = true"
>
<Lucide class="mr-1 h-4 w-4" icon="Trash" /> Delete
</a>
</div>
</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
<!-- END: Data List -->
<!-- BEGIN: Pagination -->
<div class="col-span-12 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="150"
:pageSize="10"
:siblingCount="1"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>Previous</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>Next</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="mt-3 w-20 sm:mt-0">
<NativeSelectOption value="10">10</NativeSelectOption>
<NativeSelectOption value="25">25</NativeSelectOption>
<NativeSelectOption value="35">35</NativeSelectOption>
<NativeSelectOption value="50">50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
<!-- BEGIN: Delete Confirmation Modal -->
<DialogRoot
:open="deleteConfirmationOpen"
@openChange="(details) => (deleteConfirmationOpen = details.open)"
>
<DialogContent>
<div class="p-5 text-center">
<Lucide class="text-danger mx-auto mt-3 size-16 stroke-1" icon="CircleX" />
<div class="mt-5 text-2xl font-medium">Are you sure?</div>
<div class="mt-2 opacity-70">
Do you really want to delete these records? <br />
This process cannot be undone.
</div>
</div>
<div class="px-5 pb-8 text-center">
<DialogCloseTrigger class="mr-2 w-24"> Cancel </DialogCloseTrigger>
<Button class="w-24" type="button" variant="danger" look="outline"> Delete </Button>
</div>
</DialogContent>
</DialogRoot>
<!-- END: Delete Confirmation Modal -->
</div>
</template>
+209
View File
@@ -0,0 +1,209 @@
<script lang="ts" setup>
import fakers from '@/utils/faker'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Box } from '@/components/ui/box'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import {
Table,
TableHeader,
TableBody,
TableHead,
TableRow,
TableCell,
} from '@/components/ui/table'
import {
TooltipRoot,
TooltipTrigger,
TooltipPositioner,
TooltipContent,
} from '@/components/ui/tooltip'
import { Lucide } from '@/components/ui/lucide'
</script>
<template>
<div class="flex flex-col items-center sm:flex-row">
<h2 class="mr-auto text-lg font-medium">Transaction Details</h2>
<div class="mt-4 flex w-full sm:mt-0 sm:w-auto">
<Button class="mr-2" look="outline" variant="primary"> Print </Button>
<MenuRoot class="ml-auto w-auto sm:ml-0">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="size-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="print"> <Lucide class="mr-2 size-4" icon="Printer" /> Print </MenuItem>
<MenuItem value="excel">
<Lucide class="mr-2 size-4" icon="FileText" /> Export to Excel
</MenuItem>
<MenuItem value="pdf">
<Lucide class="mr-2 size-4" icon="FileText" /> Export to PDF
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
</div>
<!-- BEGIN: Transaction Details -->
<div class="mt-5 grid grid-cols-11 gap-5">
<div class="col-span-12 lg:col-span-4 2xl:col-span-3">
<Box>
<div class="mb-5 flex items-center border-b border-foreground/15 pb-5">
<div class="truncate text-base font-medium">Transaction Details</div>
<a class="text-primary ml-auto flex items-center" href="">
<Lucide class="mr-2 size-4" icon="Edit" /> Change Status
</a>
</div>
<div class="flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Clipboard" />
Invoice:
<a class="ml-1 underline decoration-dotted" href=""> INV/20220217/MPL/2053411933 </a>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Calendar" />
Purchase Date: 24 March 2022
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Clock" />
Transaction Status:
<Badge class="ml-2" variant="success" look="outline"> Completed </Badge>
</div>
</Box>
<Box class="mt-8">
<div class="mb-5 flex items-center border-b border-foreground/15 pb-5">
<div class="truncate text-base font-medium">Buyer Details</div>
<a class="text-primary ml-auto flex items-center" href="">
<Lucide class="mr-2 size-4" icon="Edit" /> View Details
</a>
</div>
<div class="flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Clipboard" />
Name:
<a class="ml-1 underline decoration-dotted" href="">
{{ fakers[0]!['users'][0]!['name'] }}
</a>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Calendar" />
Phone Number: +71828273732
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="MapPin" />
Address: 260 W. Storm Street New York, NY 10025.
</div>
</Box>
<Box class="mt-8">
<div class="mb-5 flex items-center border-b border-foreground/15 pb-5">
<div class="truncate text-base font-medium">Payment Details</div>
</div>
<div class="flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Clipboard" />
Payment Method:
<div class="ml-auto">Direct bank transfer</div>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="CreditCard" />
Total Price (2 items):
<div class="ml-auto">$12,500.00</div>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="CreditCard" />
Total Shipping Cost (800 gr):
<div class="ml-auto">$1,500.00</div>
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="CreditCard" />
Shipping Insurance:
<div class="ml-auto">$600.00</div>
</div>
<div class="mt-5 flex items-center border-t border-foreground/15 pt-5 font-medium">
<Lucide class="mr-2 size-4 opacity-70" icon="CreditCard" />
Grand Total:
<div class="ml-auto">$15,000.00</div>
</div>
</Box>
<Box class="mt-8">
<div class="mb-5 flex items-center border-b border-foreground/15 pb-5">
<div class="truncate text-base font-medium">Shipping Information</div>
<a class="text-primary ml-auto flex items-center" href="">
<Lucide class="mr-2 size-4" icon="MapPin" /> Tracking Info
</a>
</div>
<div class="flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Clipboard" />
Courier: Left4code Express
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="Calendar" />
Tracking Number: 003005580322
<Lucide class="ml-2 size-4 opacity-70" icon="Copy" />
</div>
<div class="mt-3 flex items-center">
<Lucide class="mr-2 size-4 opacity-70" icon="MapPin" />
Address: 260 W. Storm Street New York, NY 10025.
</div>
</Box>
</div>
<div class="col-span-12 lg:col-span-7 2xl:col-span-8">
<Box>
<div class="mb-5 flex items-center border-b border-foreground/15 pb-5">
<div class="truncate text-base font-medium">Order Details</div>
<a class="text-primary ml-auto flex items-center" href="">
<Lucide class="mr-2 size-4" icon="Plus" /> Add Notes
</a>
</div>
<Table class="-mt-3">
<TableHeader>
<TableRow class="[&_th]:border-transparent [&_th]:py-5">
<TableHead> Product Name </TableHead>
<TableHead class="text-right"> Unit Price </TableHead>
<TableHead class="text-right"> QTY </TableHead>
<TableHead class="text-right"> Total </TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow
v-for="(faker, index) in fakers.slice(0, 8)"
:key="index"
class="[&_td]:border-transparent [&_td]:py-3"
>
<TableCell>
<div class="flex items-center">
<div
class="border-(--color)/5 border-3 ring-(--color)/25 relative block size-11 flex-none overflow-hidden rounded-xl ring-1 [--color:var(--color-primary)]"
>
<TooltipRoot>
<TooltipTrigger as-child>
<img
class="absolute top-0 size-full overflow-hidden object-cover"
:src="faker['images'][0]"
alt="Midone - Tailwind Admin Dashboard Template"
/>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>{{ 'Uploaded at ' + faker['dates'][2] }}</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
</div>
<a class="ml-4 whitespace-nowrap font-medium" href="">
{{ faker['products'][0]!['name'] }}
</a>
</div>
</TableCell>
<TableCell class="text-right"> ${{ faker['totals'][0] + ',000.00' }} </TableCell>
<TableCell class="text-right">2</TableCell>
<TableCell class="text-right"> ${{ faker['totals'][0]! * 2 + ',000.00' }} </TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</div>
</div>
<!-- END: Transaction Details -->
</template>
+220
View File
@@ -0,0 +1,220 @@
<script lang="ts" setup>
import { ref } from 'vue'
import fakers from '@/utils/faker'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Box } from '@/components/ui/box'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import {
Table,
TableHeader,
TableBody,
TableHead,
TableRow,
TableCell,
} from '@/components/ui/table'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import { CheckboxRoot, CheckboxControl } from '@/components/ui/checkbox'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import { DialogRoot, DialogContent, DialogCloseTrigger } from '@/components/ui/dialog'
import { Lucide } from '@/components/ui/lucide'
const deleteConfirmationOpen = ref(false)
</script>
<template>
<div>
<h2 class="text-lg font-medium">Transaction List</h2>
<div class="mt-5 grid grid-cols-12 gap-6">
<div class="col-span-12 mt-2 flex flex-wrap items-center sm:flex-nowrap">
<div class="flex w-full sm:w-auto">
<div class="relative w-56">
<Input class="w-56 pr-10" type="text" placeholder="Search..." />
<Lucide class="absolute inset-y-0 right-0 my-auto mr-3 h-4 w-4" icon="Search" />
</div>
<NativeSelect class="ml-2">
<NativeSelectOption value="Status">Status</NativeSelectOption>
<NativeSelectOption value="Waiting Payment">Waiting Payment</NativeSelectOption>
<NativeSelectOption value="Confirmed">Confirmed</NativeSelectOption>
<NativeSelectOption value="Packing">Packing</NativeSelectOption>
<NativeSelectOption value="Delivered">Delivered</NativeSelectOption>
<NativeSelectOption value="Completed">Completed</NativeSelectOption>
</NativeSelect>
</div>
<div class="mx-auto hidden opacity-70 md:block">Showing 1 to 10 of 150 entries</div>
<div class="mt-3 flex w-full items-center xl:mt-0 xl:w-auto">
<Box as-child>
<Button variant="ghost" class="mr-2">
<Lucide class="size-4" icon="FileText" />
Export to Excel
</Button>
</Box>
<Box as-child>
<Button variant="ghost" class="mr-2">
<Lucide class="size-4" icon="FileText" />
Export to PDF
</Button>
</Box>
<MenuRoot class="w-auto">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="print">
<Lucide class="mr-2 h-4 w-4" icon="Printer" /> Print
</MenuItem>
<MenuItem value="excel">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to Excel
</MenuItem>
<MenuItem value="pdf">
<Lucide class="mr-2 h-4 w-4" icon="FileText" /> Export to PDF
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
</div>
<!-- BEGIN: Data List -->
<div class="col-span-12 overflow-auto lg:overflow-visible">
<Table class="-mt-2" variant="boxed">
<TableHeader>
<TableRow>
<TableHead>
<CheckboxRoot>
<CheckboxControl />
</CheckboxRoot>
</TableHead>
<TableHead> INVOICE </TableHead>
<TableHead> BUYER NAME </TableHead>
<TableHead class="text-center"> STATUS </TableHead>
<TableHead> PAYMENT </TableHead>
<TableHead class="text-right"> TOTAL TRANSACTION </TableHead>
<TableHead class="text-center"> ACTIONS </TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow v-for="(faker, index) in fakers.slice(0, 9)" :key="index">
<TableCell>
<CheckboxRoot>
<CheckboxControl />
</CheckboxRoot>
</TableCell>
<TableCell>
<a class="whitespace-nowrap underline decoration-dotted" href="">
{{ '#INV-' + faker['totals'][0] + '807556' }}
</a>
</TableCell>
<TableCell>
<a class="whitespace-nowrap font-medium" href="">
{{ faker['users'][0]!['name'] }}
</a>
<div class="mt-0.5 whitespace-nowrap text-xs opacity-70">
{{ faker['trueFalse'][0] ? 'Ohio, Ohio' : 'California, LA' }}
</div>
</TableCell>
<TableCell>
<div
class="flex items-center justify-center"
:class="faker['trueFalse'][0] ? 'text-success' : 'text-danger'"
>
<Lucide class="mr-2 h-4 w-4" icon="CheckSquare" />
{{ faker['trueFalse'][0] ? 'Active' : 'Inactive' }}
</div>
</TableCell>
<TableCell>
<template v-if="faker['trueFalse'][0]">
<div class="whitespace-nowrap">Direct bank transfer</div>
<div class="mt-0.5 whitespace-nowrap text-xs opacity-70">25 March, 12:55</div>
</template>
<template v-else>
<div class="whitespace-nowrap">Checking payments</div>
<div class="mt-0.5 whitespace-nowrap text-xs opacity-70">30 March, 11:00</div>
</template>
</TableCell>
<TableCell class="text-right"> ${{ faker['totals'][0] + ',000,00' }} </TableCell>
<TableCell>
<div class="flex items-center justify-center">
<a class="text-primary mr-5 flex items-center whitespace-nowrap" href="#">
<Lucide class="mr-1 h-4 w-4" icon="CheckSquare" />
View Details
</a>
<a
class="text-primary flex items-center whitespace-nowrap"
href="#"
@click.prevent="deleteConfirmationOpen = true"
>
<Lucide class="mr-1 h-4 w-4" icon="ArrowLeftRight" />
Change Status
</a>
</div>
</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
<!-- END: Data List -->
<!-- BEGIN: Pagination -->
<div class="col-span-12 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="150"
:pageSize="10"
:siblingCount="1"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>Previous</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>Next</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="mt-3 w-20 sm:mt-0">
<NativeSelectOption value="10">10</NativeSelectOption>
<NativeSelectOption value="25">25</NativeSelectOption>
<NativeSelectOption value="35">35</NativeSelectOption>
<NativeSelectOption value="50">50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
<!-- BEGIN: Delete Confirmation Modal -->
<DialogRoot
:open="deleteConfirmationOpen"
@openChange="(details) => (deleteConfirmationOpen = details.open)"
>
<DialogContent>
<div class="p-5 text-center">
<Lucide class="text-danger mx-auto mt-3 size-16 stroke-1" icon="CircleX" />
<div class="mt-5 text-2xl font-medium">Are you sure?</div>
<div class="mt-2 opacity-70">
Do you really want to delete these records? <br />
This process cannot be undone.
</div>
</div>
<div class="px-5 pb-8 text-center">
<DialogCloseTrigger class="mr-2 w-24"> Cancel </DialogCloseTrigger>
<Button class="w-24" type="button" variant="danger" look="outline"> Delete </Button>
</div>
</DialogContent>
</DialogRoot>
<!-- END: Delete Confirmation Modal -->
</div>
</template>
+168
View File
@@ -0,0 +1,168 @@
<script lang="ts" setup>
import fakers from '@/utils/faker'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Box } from '@/components/ui/box'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import { AvatarRoot, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import {
TooltipRoot,
TooltipTrigger,
TooltipPositioner,
TooltipContent,
} from '@/components/ui/tooltip'
import { Lucide } from '@/components/ui/lucide'
</script>
<template>
<div>
<h2 class="text-lg font-medium">Users Layout</h2>
<div class="mt-5 grid grid-cols-12 gap-x-6 gap-y-8">
<div class="col-span-12 mt-2 flex flex-wrap items-center sm:flex-nowrap">
<Button class="mr-2" look="outline" variant="primary"> Add New User </Button>
<MenuRoot class="w-auto">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="group">
<Lucide class="mr-2 h-4 w-4" icon="Users" /> Add Group
</MenuItem>
<MenuItem value="message">
<Lucide class="mr-2 h-4 w-4" icon="MessageCircle" /> Send Message
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
<div class="mx-auto hidden opacity-70 md:block">Showing 1 to 10 of 150 entries</div>
<div class="mt-3 w-full sm:ml-auto sm:mt-0 sm:w-auto md:ml-0">
<div class="relative w-56">
<Input class="w-56 pr-10" type="text" placeholder="Search..." />
<Lucide class="absolute inset-y-0 right-0 my-auto mr-3 h-4 w-4" icon="Search" />
</div>
</div>
</div>
<!-- BEGIN: Users Layout -->
<div
v-for="(faker, index) in fakers.slice(0, 10)"
:key="index"
class="col-span-12 md:col-span-6"
>
<Box raised="single" class="p-0">
<div class="flex flex-col items-center border-b border-foreground/15 p-5 lg:flex-row">
<AvatarRoot class="size-24 bg-background rounded-full lg:mr-1 lg:size-12">
<AvatarFallback>IM</AvatarFallback>
<AvatarImage :src="faker['images'][2]" :alt="'Uploaded at ' + faker['dates'][2]" />
</AvatarRoot>
<div class="mt-3 text-center lg:ml-2 lg:mr-auto lg:mt-0 lg:text-left">
<a class="font-medium" href="">
{{ faker['users'][0]!['name'] }}
</a>
<div class="mt-0.5 text-xs opacity-70">
{{ faker['jobs'][0] }}
</div>
</div>
<div class="-ml-2 mt-3 flex lg:ml-0 lg:mt-0 lg:justify-end">
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="ml-2 flex h-8 w-8 items-center justify-center rounded-full border border-foreground/15"
href=""
>
<Lucide class="h-3 w-3 fill-current opacity-50" icon="Facebook" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Facebook</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="ml-2 flex h-8 w-8 items-center justify-center rounded-full border border-foreground/15"
href=""
>
<Lucide class="h-3 w-3 fill-current opacity-50" icon="Twitter" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Twitter</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
<TooltipRoot>
<TooltipTrigger as-child>
<a
class="ml-2 flex h-8 w-8 items-center justify-center rounded-full border border-foreground/15"
href=""
>
<Lucide class="h-3 w-3 fill-current opacity-50" icon="Linkedin" />
</a>
</TooltipTrigger>
<TooltipPositioner>
<TooltipContent>Linked In</TooltipContent>
</TooltipPositioner>
</TooltipRoot>
</div>
</div>
<div class="flex flex-wrap items-center justify-center p-5 lg:flex-nowrap">
<div class="mb-4 mr-auto w-full lg:mb-0 lg:w-1/2">
<div class="flex text-xs opacity-70">
<div class="mr-auto">Progress</div>
<div>20%</div>
</div>
<div class="mt-2 h-1 rounded-full bg-foreground/10">
<div class="h-full w-[20%] rounded-full bg-primary" />
</div>
</div>
<Button class="mr-2" size="sm" look="outline"> Message </Button>
<Button variant="primary" size="sm"> View Profile </Button>
</div>
</Box>
</div>
<!-- END: Users Layout -->
<!-- BEGIN: Pagination -->
<div class="col-span-12 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="150"
:pageSize="10"
:siblingCount="1"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>Previous</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>Next</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="mt-3 w-20 sm:mt-0">
<NativeSelectOption value="10">10</NativeSelectOption>
<NativeSelectOption value="25">25</NativeSelectOption>
<NativeSelectOption value="35">35</NativeSelectOption>
<NativeSelectOption value="50">50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
</div>
</template>
+108
View File
@@ -0,0 +1,108 @@
<script lang="ts" setup>
import fakers from '@/utils/faker'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Box } from '@/components/ui/box'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import { AvatarRoot, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import { Lucide } from '@/components/ui/lucide'
</script>
<template>
<div>
<h2 class="text-lg font-medium">Users Layout</h2>
<div class="mt-5 grid grid-cols-12 gap-x-6 gap-y-8">
<div class="col-span-12 mt-2 flex flex-wrap items-center sm:flex-nowrap">
<Button class="mr-2" look="outline" variant="primary"> Add New User </Button>
<MenuRoot class="w-auto">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="group">
<Lucide class="mr-2 h-4 w-4" icon="Users" /> Add Group
</MenuItem>
<MenuItem value="message">
<Lucide class="mr-2 h-4 w-4" icon="MessageCircle" /> Send Message
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
<div class="mx-auto hidden opacity-70 md:block">Showing 1 to 10 of 150 entries</div>
<div class="mt-3 w-full sm:ml-auto sm:mt-0 sm:w-auto md:ml-0">
<div class="relative w-56">
<Input class="w-56 pr-10" type="text" placeholder="Search..." />
<Lucide class="absolute inset-y-0 right-0 my-auto mr-3 h-4 w-4" icon="Search" />
</div>
</div>
</div>
<!-- BEGIN: Users Layout -->
<div v-for="(faker, index) in fakers" :key="index" class="col-span-12 md:col-span-6">
<Box raised="single">
<div class="flex flex-col items-center lg:flex-row">
<AvatarRoot class="size-24 bg-background rounded-full lg:mr-1 lg:size-12">
<AvatarFallback>IM</AvatarFallback>
<AvatarImage :src="faker['images'][2]" :alt="'Uploaded at ' + faker['dates'][2]" />
</AvatarRoot>
<div class="mt-3 text-center lg:ml-2 lg:mr-auto lg:mt-0 lg:text-left">
<a class="font-medium" href="">
{{ faker['users'][0]!['name'] }}
</a>
<div class="mt-0.5 text-xs opacity-70">
{{ faker['jobs'][0] }}
</div>
</div>
<div class="mt-4 flex lg:mt-0">
<Button class="mr-2" size="sm" look="outline"> View Profile </Button>
<Button variant="primary" size="sm"> Message </Button>
</div>
</div>
</Box>
</div>
<!-- END: Users Layout -->
<!-- BEGIN: Pagination -->
<div class="col-span-12 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="150"
:pageSize="10"
:siblingCount="1"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>Previous</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>Next</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="mt-3 w-20 sm:mt-0">
<NativeSelectOption value="10">10</NativeSelectOption>
<NativeSelectOption value="25">25</NativeSelectOption>
<NativeSelectOption value="35">35</NativeSelectOption>
<NativeSelectOption value="50">50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
</div>
</template>
+142
View File
@@ -0,0 +1,142 @@
<script lang="ts" setup>
import fakers from '@/utils/faker'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Box } from '@/components/ui/box'
import { MenuRoot, MenuTrigger, MenuPositioner, MenuContent, MenuItem } from '@/components/ui/menu'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
import { AvatarRoot, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import {
PaginationContext,
PaginationRoot,
PaginationItem,
PaginationPrevTrigger,
PaginationNextTrigger,
PaginationEllipsis,
} from '@/components/ui/pagination'
import { Lucide } from '@/components/ui/lucide'
</script>
<template>
<div>
<h2 class="text-lg font-medium">Users Layout</h2>
<div class="mt-5 grid grid-cols-12 gap-x-6 gap-y-8">
<div class="col-span-12 mt-2 flex flex-wrap items-center sm:flex-nowrap">
<Button class="mr-2" look="outline" variant="primary"> Add New User </Button>
<MenuRoot class="w-auto">
<MenuTrigger as-child>
<Box class="px-2" as-child>
<Button variant="ghost" class="box flex items-center">
<span class="flex h-5 w-5 items-center justify-center">
<Lucide class="h-4 w-4" icon="Plus" />
</span>
</Button>
</Box>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="group">
<Lucide class="mr-2 h-4 w-4" icon="Users" /> Add Group
</MenuItem>
<MenuItem value="message">
<Lucide class="mr-2 h-4 w-4" icon="MessageCircle" /> Send Message
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
<div class="mx-auto hidden opacity-70 md:block">Showing 1 to 10 of 150 entries</div>
<div class="mt-3 w-full sm:ml-auto sm:mt-0 sm:w-auto md:ml-0">
<div class="relative w-56">
<Input class="w-56 pr-10" type="text" placeholder="Search..." />
<Lucide class="absolute inset-y-0 right-0 my-auto mr-3 h-4 w-4" icon="Search" />
</div>
</div>
</div>
<!-- BEGIN: Users Layout -->
<div
v-for="(faker, index) in fakers.slice(0, 9)"
:key="index"
class="col-span-12 md:col-span-6 lg:col-span-4"
>
<Box raised="single" class="p-0">
<div class="flex items-start px-5 pt-5">
<div class="flex w-full flex-col items-center lg:flex-row">
<AvatarRoot class="size-14 bg-background rounded-full">
<AvatarFallback>IM</AvatarFallback>
<AvatarImage :src="faker['photos'][0]" :alt="faker['users'][0]!['name']" />
</AvatarRoot>
<div class="mt-3 text-center lg:ml-4 lg:mt-0 lg:text-left">
<a class="font-medium" href="">
{{ faker['users'][0]!['name'] }}
</a>
<div class="mt-0.5 text-xs opacity-70">
{{ faker['jobs'][0] }}
</div>
</div>
</div>
<MenuRoot class="w-auto absolute right-0 top-0 mr-5 mt-3">
<MenuTrigger as-child>
<a class="block size-5" href="#">
<Lucide class="size-5 opacity-70" icon="MoreHorizontal" />
</a>
</MenuTrigger>
<MenuPositioner>
<MenuContent class="w-40">
<MenuItem value="edit">
<Lucide class="mr-2 h-4 w-4" icon="Edit" /> Edit
</MenuItem>
<MenuItem value="delete">
<Lucide class="mr-2 h-4 w-4" icon="Trash" /> Delete
</MenuItem>
</MenuContent>
</MenuPositioner>
</MenuRoot>
</div>
<div class="p-5 text-center lg:text-left">
<div>{{ faker['news'][0]!['shortContent'] }}</div>
<div class="mt-5 flex items-center justify-center opacity-70 lg:justify-start">
<Lucide class="mr-2 size-3.5" icon="Mail" />
{{ faker['users'][0]!['email'] }}
</div>
<div class="mt-1 flex items-center justify-center opacity-70 lg:justify-start">
<Lucide class="mr-2 size-3.5" icon="Instagram" />
{{ faker['users'][0]!['name'] }}
</div>
</div>
<div class="border-t border-foreground/15 p-5 text-center lg:text-right">
<Button class="mr-2" size="sm" look="outline"> Message </Button>
<Button variant="primary" size="sm"> View Profile </Button>
</div>
</Box>
</div>
<!-- END: Users Layout -->
<!-- BEGIN: Pagination -->
<div class="col-span-12 flex flex-wrap items-center sm:flex-row sm:flex-nowrap">
<PaginationRoot
:count="150"
:pageSize="10"
:siblingCount="1"
class="w-full sm:mr-auto sm:w-auto"
>
<PaginationPrevTrigger>Previous</PaginationPrevTrigger>
<PaginationContext v-slot="{ pagination }">
<template v-for="(page, index) in pagination?.pages" :key="index">
<PaginationItem v-if="page.type === 'page'" v-bind="{ ...page }">
{{ page.value }}
</PaginationItem>
<PaginationEllipsis v-else :index="index" />
</template>
</PaginationContext>
<PaginationNextTrigger>Next</PaginationNextTrigger>
</PaginationRoot>
<NativeSelect class="mt-3 w-20 sm:mt-0">
<NativeSelectOption value="10">10</NativeSelectOption>
<NativeSelectOption value="25">25</NativeSelectOption>
<NativeSelectOption value="35">35</NativeSelectOption>
<NativeSelectOption value="50">50</NativeSelectOption>
</NativeSelect>
</div>
<!-- END: Pagination -->
</div>
</div>
</template>
+76
View File
@@ -0,0 +1,76 @@
<script lang="ts" setup>
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Box } from '@/components/ui/box'
import { Field, FieldLabel } from '@/components/ui/field'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
</script>
<template>
<div class="flex items-center">
<h2 class="mr-auto text-lg font-medium">Wizard Layout</h2>
</div>
<!-- BEGIN: Wizard Layout -->
<Box class="mt-5 py-10 sm:py-20">
<div class="flex justify-center">
<Button class="mx-2 size-14 rounded-full shadow-none"> 1 </Button>
<Button
variant="ghost"
class="bg-background border border-foreground/15 shadow-none mx-2 size-14 rounded-full"
>
2
</Button>
<Button
variant="ghost"
class="bg-background border border-foreground/15 shadow-none mx-2 size-14 rounded-full"
>
3
</Button>
</div>
<div class="mt-10 px-5">
<div class="text-center text-lg font-medium">Setup Your Account</div>
<div class="mt-2 text-center opacity-70">
To start off, please enter your username, email address and password.
</div>
</div>
<div class="mt-10 border-t border-foreground/10 px-5 pt-10 sm:px-20">
<div class="text-base font-medium">Profile Settings</div>
<div class="mt-5 grid grid-cols-12 gap-4 gap-y-5">
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-1">From</FieldLabel>
<Input id="input-wizard-1" type="text" placeholder="example@gmail.com" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-2">To</FieldLabel>
<Input id="input-wizard-2" type="text" placeholder="example@gmail.com" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-3">Subject</FieldLabel>
<Input id="input-wizard-3" type="text" placeholder="Important Meeting" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-4">Has the Words</FieldLabel>
<Input id="input-wizard-4" type="text" placeholder="Job, Work, Documentation" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-5">Doesn't Have</FieldLabel>
<Input id="input-wizard-5" type="text" placeholder="Job, Work, Documentation" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-6">Size</FieldLabel>
<NativeSelect id="input-wizard-6">
<NativeSelectOption>10</NativeSelectOption>
<NativeSelectOption>25</NativeSelectOption>
<NativeSelectOption>35</NativeSelectOption>
<NativeSelectOption>50</NativeSelectOption>
</NativeSelect>
</Field>
<div class="col-span-12 mt-5 flex items-center justify-center sm:justify-end">
<Button look="outline" class="w-32">Previous</Button>
<Button class="ml-2 w-32">Next</Button>
</div>
</div>
</div>
</Box>
<!-- END: Wizard Layout -->
</template>
+97
View File
@@ -0,0 +1,97 @@
<script lang="ts" setup>
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Box } from '@/components/ui/box'
import { Field, FieldLabel } from '@/components/ui/field'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
</script>
<template>
<div class="flex items-center">
<h2 class="mr-auto text-lg font-medium">Wizard Layout</h2>
</div>
<!-- BEGIN: Wizard Layout -->
<Box class="mt-5 py-10 sm:py-20">
<div class="grid gap-5 px-5 sm:px-20">
<div class="flex items-center">
<Button class="mx-2 size-12 rounded-full shadow-none"> 1 </Button>
<div class="text-primary ml-3 text-base font-medium opacity-100">Create New Account</div>
</div>
<div class="flex items-center">
<Button
variant="ghost"
class="bg-background border border-foreground/15 shadow-none mx-2 size-12 rounded-full"
>
2
</Button>
<div class="ml-3 text-base opacity-70">Setup Your Profile</div>
</div>
<div class="flex items-center">
<Button
variant="ghost"
class="bg-background border border-foreground/15 shadow-none mx-2 size-12 rounded-full"
>
3
</Button>
<div class="ml-3 text-base opacity-70">Setup Your Business Details</div>
</div>
<div class="flex items-center">
<Button
variant="ghost"
class="bg-background border border-foreground/15 shadow-none mx-2 size-12 rounded-full"
>
4
</Button>
<div class="ml-3 text-base opacity-70">Setup Billing Account</div>
</div>
<div class="flex items-center">
<Button
variant="ghost"
class="bg-background border border-foreground/15 shadow-none mx-2 size-12 rounded-full"
>
5
</Button>
<div class="ml-3 text-base opacity-70">Finalize your purchase</div>
</div>
</div>
<div class="mt-10 border-t border-foreground/10 px-5 pt-10 sm:px-20">
<div class="text-base font-medium">Profile Settings</div>
<div class="mt-5 grid grid-cols-12 gap-4 gap-y-5">
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-1">From</FieldLabel>
<Input id="input-wizard-1" type="text" placeholder="example@gmail.com" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-2">To</FieldLabel>
<Input id="input-wizard-2" type="text" placeholder="example@gmail.com" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-3">Subject</FieldLabel>
<Input id="input-wizard-3" type="text" placeholder="Important Meeting" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-4">Has the Words</FieldLabel>
<Input id="input-wizard-4" type="text" placeholder="Job, Work, Documentation" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-5">Doesn't Have</FieldLabel>
<Input id="input-wizard-5" type="text" placeholder="Job, Work, Documentation" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-6">Size</FieldLabel>
<NativeSelect id="input-wizard-6">
<NativeSelectOption>10</NativeSelectOption>
<NativeSelectOption>25</NativeSelectOption>
<NativeSelectOption>35</NativeSelectOption>
<NativeSelectOption>50</NativeSelectOption>
</NativeSelect>
</Field>
<div class="col-span-12 mt-5 flex items-center justify-center sm:justify-end">
<Button look="outline" class="w-32">Previous</Button>
<Button class="ml-2 w-32">Next</Button>
</div>
</div>
</div>
</Box>
<!-- END: Wizard Layout -->
</template>
+101
View File
@@ -0,0 +1,101 @@
<script lang="ts" setup>
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Box } from '@/components/ui/box'
import { Field, FieldLabel } from '@/components/ui/field'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
</script>
<template>
<div class="flex items-center">
<h2 class="mr-auto text-lg font-medium">Wizard Layout</h2>
</div>
<!-- BEGIN: Wizard Layout -->
<Box class="mt-5 py-10 sm:py-20">
<div
class="before:bg-foreground/10 relative flex flex-col justify-center px-5 before:absolute before:bottom-0 before:top-0 before:mt-6 before:hidden before:h-0.5 before:w-[69%] sm:px-20 lg:flex-row before:lg:block"
>
<div class="z-10 flex flex-1 items-center lg:block lg:text-center">
<Button class="mx-2 size-12 rounded-full shadow-none"> 1 </Button>
<div class="text-primary ml-3 font-medium opacity-100 lg:mx-auto lg:mt-3 lg:w-32">
Create New Account
</div>
</div>
<div class="z-10 flex flex-1 items-center lg:block lg:text-center">
<Button
variant="ghost"
class="bg-background border border-foreground/15 shadow-none mx-2 size-12 rounded-full"
>
2
</Button>
<div class="ml-3 opacity-70 lg:mx-auto lg:mt-3 lg:w-32">Setup Your Profile</div>
</div>
<div class="z-10 flex flex-1 items-center lg:block lg:text-center">
<Button
variant="ghost"
class="bg-background border border-foreground/15 shadow-none mx-2 size-12 rounded-full"
>
3
</Button>
<div class="ml-3 opacity-70 lg:mx-auto lg:mt-3 lg:w-32">Setup Your Business Details</div>
</div>
<div class="z-10 flex flex-1 items-center lg:block lg:text-center">
<Button
variant="ghost"
class="bg-background border border-foreground/15 shadow-none mx-2 size-12 rounded-full"
>
4
</Button>
<div class="ml-3 opacity-70 lg:mx-auto lg:mt-3 lg:w-32">Setup Billing Account</div>
</div>
<div class="z-10 flex flex-1 items-center lg:block lg:text-center">
<Button
variant="ghost"
class="bg-background border border-foreground/15 shadow-none mx-2 size-12 rounded-full"
>
5
</Button>
<div class="ml-3 opacity-70 lg:mx-auto lg:mt-3 lg:w-32">Finalize your purchase</div>
</div>
</div>
<div class="mt-10 border-t border-foreground/10 px-5 pt-10 sm:px-20">
<div class="text-base font-medium">Profile Settings</div>
<div class="mt-5 grid grid-cols-12 gap-4 gap-y-5">
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-1">From</FieldLabel>
<Input id="input-wizard-1" type="text" placeholder="example@gmail.com" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-2">To</FieldLabel>
<Input id="input-wizard-2" type="text" placeholder="example@gmail.com" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-3">Subject</FieldLabel>
<Input id="input-wizard-3" type="text" placeholder="Important Meeting" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-4">Has the Words</FieldLabel>
<Input id="input-wizard-4" type="text" placeholder="Job, Work, Documentation" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-5">Doesn't Have</FieldLabel>
<Input id="input-wizard-5" type="text" placeholder="Job, Work, Documentation" />
</Field>
<Field class="col-span-12 sm:col-span-6">
<FieldLabel for="input-wizard-6">Size</FieldLabel>
<NativeSelect id="input-wizard-6">
<NativeSelectOption>10</NativeSelectOption>
<NativeSelectOption>25</NativeSelectOption>
<NativeSelectOption>35</NativeSelectOption>
<NativeSelectOption>50</NativeSelectOption>
</NativeSelect>
</Field>
<div class="col-span-12 mt-5 flex items-center justify-center sm:justify-end">
<Button look="outline" class="w-32">Previous</Button>
<Button class="ml-2 w-32">Next</Button>
</div>
</div>
</div>
</Box>
<!-- END: Wizard Layout -->
</template>