-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
47c0410
commit 18451b8
Showing
7 changed files
with
690 additions
and
1 deletion.
There are no files selected for viewing
196 changes: 196 additions & 0 deletions
196
apps/gifting-concierge/src/app/dashboard/gifting-concierge/[giftId]/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
import { createClient } from "~/supabase/server"; | ||
|
||
import { | ||
Card, | ||
CardHeader, | ||
CardTitle, | ||
CardDescription, | ||
CardContent, | ||
} from "@theliaison/ui/card"; | ||
import { Button } from "@theliaison/ui/button"; | ||
import Image from "next/image"; | ||
|
||
export default async function GiftingConciergeByIdPage({ | ||
params: { giftId }, | ||
}: { | ||
params: { giftId: string }; | ||
}) { | ||
const supabase = createClient(); | ||
const { data, error } = await supabase | ||
.from("gifts") | ||
.select(` | ||
sender_name, | ||
recipient_name, | ||
total_price, | ||
gifts_products(id, quantity, products(name, image, prices(unit_amount))) | ||
`) | ||
.eq("id", giftId) | ||
.single(); | ||
|
||
if (error) { | ||
console.log(error); | ||
return <div>Error</div>; | ||
} | ||
|
||
return ( | ||
<div className="mx-auto lg:mt-20"> | ||
<Card className="w-full max-w-4xl"> | ||
<CardHeader className="flex items-center gap-4 border-b pb-4"> | ||
<div className="flex-1"> | ||
<CardTitle>Gifting Concierge</CardTitle> | ||
<CardDescription>Gift Data</CardDescription> | ||
</div> | ||
<Button variant="outline" size="icon"> | ||
<BellIcon className="h-5 w-5" /> | ||
<span className="sr-only">Notifications</span> | ||
</Button> | ||
</CardHeader> | ||
<CardContent className="grid gap-6 py-6"> | ||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> | ||
<div> | ||
<h3 className="font-semibold text-lg mb-4">Gift Items</h3> | ||
<div className="grid gap-4"> | ||
{data.gifts_products.map((giftItem) => ( | ||
<div key={giftItem.id}> | ||
<div className="flex items-center gap-4"> | ||
<Image | ||
src={giftItem.products?.image ?? "/placeholder.svg"} | ||
alt={giftItem.products?.name ?? "Gift Item"} | ||
width={80} | ||
height={80} | ||
className="rounded-md" | ||
/> | ||
<div className="flex-1"> | ||
<p className="font-medium">{giftItem.products?.name}</p> | ||
<p className="text-sm text-gray-500 dark:text-gray-400"> | ||
Quantity: {giftItem.quantity} | ||
</p> | ||
<p className="text-sm font-medium"> | ||
{Intl.NumberFormat("en-US", { | ||
style: "currency", | ||
currency: "USD", | ||
}).format( | ||
(giftItem.products?.prices[0]?.unit_amount ?? 0) / | ||
100 ?? 0, | ||
)}{" "} | ||
x {giftItem.quantity} ={" "} | ||
{Intl.NumberFormat("en-US", { | ||
style: "currency", | ||
currency: "USD", | ||
}).format( | ||
((giftItem.products?.prices[0]?.unit_amount ?? 0) / | ||
100) * | ||
giftItem.quantity ?? 0, | ||
)} | ||
</p> | ||
</div> | ||
</div> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
<div> | ||
<h3 className="font-semibold text-lg mb-4">Gift Status</h3> | ||
<div className="grid gap-4"> | ||
<div className="flex items-center gap-4"> | ||
<TruckIcon className="h-8 w-8 text-gray-500 dark:text-gray-400" /> | ||
<div className="flex-1"> | ||
<p className="font-medium">Pending Confirmation</p> | ||
<p className="text-sm text-gray-500 dark:text-gray-400"> | ||
Your gift is awaiting approval. | ||
</p> | ||
</div> | ||
</div> | ||
<div className="flex items-center gap-4"> | ||
<TruckIcon className="h-8 w-8 text-yellow-500" /> | ||
<div className="flex-1"> | ||
<p className="font-medium">Pending Payment</p> | ||
<p className="text-sm text-gray-500 dark:text-gray-400"> | ||
Please complete your payment. | ||
</p> | ||
</div> | ||
</div> | ||
<div className="flex items-center gap-4"> | ||
<TruckIcon className="h-8 w-8 text-green-500" /> | ||
<div className="flex-1"> | ||
<p className="font-medium">In Shipping</p> | ||
<p className="text-sm text-gray-500 dark:text-gray-400"> | ||
Your gift is on its way. | ||
</p> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div> | ||
<h3 className="font-semibold text-lg mb-4">Sender & Recipient</h3> | ||
<div className="flex items-center gap-4"> | ||
<div className="flex-1"> | ||
<p className="font-medium">Sender: {data.sender_name}</p> | ||
<p className="text-sm text-gray-500 dark:text-gray-400"> | ||
Recipient: {data.recipient_name} | ||
</p> | ||
</div> | ||
<div className="text-right"> | ||
<p className="font-medium text-lg"> | ||
{Intl.NumberFormat("en-US", { | ||
style: "currency", | ||
currency: "USD", | ||
}).format(data.total_price ?? 0)} | ||
</p> | ||
<p className="text-sm text-gray-500 dark:text-gray-400"> | ||
Total | ||
</p> | ||
</div> | ||
</div> | ||
</div> | ||
</CardContent> | ||
</Card> | ||
</div> | ||
); | ||
} | ||
|
||
function BellIcon(props: React.SVGProps<SVGSVGElement>) { | ||
return ( | ||
<svg | ||
{...props} | ||
aria-hidden="true" | ||
xmlns="http://www.w3.org/2000/svg" | ||
width="24" | ||
height="24" | ||
viewBox="0 0 24 24" | ||
fill="none" | ||
stroke="currentColor" | ||
strokeWidth="2" | ||
strokeLinecap="round" | ||
strokeLinejoin="round" | ||
> | ||
<path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9" /> | ||
<path d="M10.3 21a1.94 1.94 0 0 0 3.4 0" /> | ||
</svg> | ||
); | ||
} | ||
|
||
function TruckIcon(props: React.SVGProps<SVGSVGElement>) { | ||
return ( | ||
<svg | ||
aria-hidden="true" | ||
{...props} | ||
xmlns="http://www.w3.org/2000/svg" | ||
width="24" | ||
height="24" | ||
viewBox="0 0 24 24" | ||
fill="none" | ||
stroke="currentColor" | ||
strokeWidth="2" | ||
strokeLinecap="round" | ||
strokeLinejoin="round" | ||
> | ||
<path d="M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2" /> | ||
<path d="M15 18H9" /> | ||
<path d="M19 18h2a1 1 0 0 0 1-1v-3.65a1 1 0 0 0-.22-.624l-3.48-4.35A1 1 0 0 0 17.52 8H14" /> | ||
<circle cx="17" cy="18" r="2" /> | ||
<circle cx="7" cy="18" r="2" /> | ||
</svg> | ||
); | ||
} |
9 changes: 9 additions & 0 deletions
9
apps/gifting-concierge/src/app/dashboard/gifting-concierge/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { GiftsData } from "../_components/gifts-data"; | ||
|
||
export default function GiftingConciergePage() { | ||
return ( | ||
<div> | ||
<GiftsData /> | ||
</div> | ||
); | ||
} |
124 changes: 124 additions & 0 deletions
124
apps/gifting-concierge/src/app/dashboard/gifts/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import Image from "next/image"; | ||
import { MoreHorizontal } from "lucide-react"; | ||
import { Button } from "@theliaison/ui/button"; | ||
import { | ||
Card, | ||
CardContent, | ||
CardDescription, | ||
CardFooter, | ||
CardHeader, | ||
CardTitle, | ||
} from "@theliaison/ui/card"; | ||
import { | ||
DropdownMenu, | ||
DropdownMenuContent, | ||
DropdownMenuItem, | ||
DropdownMenuLabel, | ||
DropdownMenuTrigger, | ||
} from "@theliaison/ui/dropdown-menu"; | ||
import { | ||
Table, | ||
TableBody, | ||
TableCell, | ||
TableHead, | ||
TableHeader, | ||
TableRow, | ||
} from "@theliaison/ui/table"; | ||
import { createClient } from "~/supabase/server"; | ||
|
||
export default async function GiftsPage() { | ||
const supabase = createClient(); | ||
const { data, error } = await supabase | ||
.from("products") | ||
.select(` | ||
id, | ||
name, | ||
image, | ||
type, | ||
active, | ||
prices(id, unit_amount) | ||
`) | ||
.eq("type", "gift") | ||
.eq("active", true); | ||
|
||
if (error) { | ||
console.log(error); | ||
return <div>Error</div>; | ||
} | ||
|
||
return ( | ||
<div className="flex flex-col gap-6"> | ||
<Card> | ||
<CardHeader> | ||
<CardTitle>Products</CardTitle> | ||
<CardDescription> | ||
Manage your gift products and view their sales performance. | ||
</CardDescription> | ||
</CardHeader> | ||
<CardContent> | ||
<Table> | ||
<TableHeader> | ||
<TableRow> | ||
<TableHead className="hidden w-[100px] sm:table-cell"> | ||
<span className="sr-only">Image</span> | ||
</TableHead> | ||
<TableHead>Name</TableHead> | ||
<TableHead className="hidden md:table-cell">Price</TableHead> | ||
<TableHead> | ||
<span className="sr-only">Actions</span> | ||
</TableHead> | ||
</TableRow> | ||
</TableHeader> | ||
<TableBody> | ||
{data?.map((product, index) => ( | ||
<TableRow key={product.id}> | ||
<TableCell className="hidden sm:table-cell"> | ||
<Image | ||
alt="Product image" | ||
className="aspect-square rounded-md object-cover" | ||
height="64" | ||
src={product.image ?? "/placeholder.svg"} | ||
width="64" | ||
/> | ||
</TableCell> | ||
<TableCell className="font-medium">{product.name}</TableCell> | ||
<TableCell className="hidden md:table-cell"> | ||
{Intl.NumberFormat("en-US", { | ||
style: "currency", | ||
currency: "USD", | ||
}).format((product.prices[0]?.unit_amount ?? 0) / 100)} | ||
</TableCell> | ||
<TableCell> | ||
<DropdownMenu> | ||
<DropdownMenuTrigger asChild> | ||
<Button | ||
aria-haspopup="true" | ||
size="icon" | ||
variant="ghost" | ||
> | ||
<MoreHorizontal className="h-4 w-4" /> | ||
<span className="sr-only">Toggle menu</span> | ||
</Button> | ||
</DropdownMenuTrigger> | ||
<DropdownMenuContent align="end"> | ||
<DropdownMenuLabel>Actions</DropdownMenuLabel> | ||
<DropdownMenuItem>Edit</DropdownMenuItem> | ||
<DropdownMenuItem>Delete</DropdownMenuItem> | ||
</DropdownMenuContent> | ||
</DropdownMenu> | ||
</TableCell> | ||
</TableRow> | ||
))} | ||
</TableBody> | ||
</Table> | ||
</CardContent> | ||
<CardFooter> | ||
<div className="text-xs text-muted-foreground"> | ||
Showing <strong>1 - {data.length}</strong> of{" "} | ||
<strong>{data?.length}</strong> products | ||
</div> | ||
</CardFooter> | ||
</Card> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { DashboardSidebar } from "~/components/sidebar"; | ||
|
||
export default function DashboardLayout({ | ||
children, | ||
}: Readonly<{ | ||
children: React.ReactNode; | ||
}>) { | ||
return <DashboardSidebar>{children}</DashboardSidebar>; | ||
} |
Oops, something went wrong.