this repo has no description
1import { connection } from 'next/server';
2import type { Product } from '#/types/product';
3import { Ping } from '#/components/ping';
4import { ProductEstimatedArrival } from '#/components/product-estimated-arrival';
5import { ProductLowStockWarning } from '#/components/product-low-stock-warning';
6import { ProductPrice } from '#/components/product-price';
7import { ProductSplitPayments } from '#/components/product-split-payments';
8import { ProductUsedPrice } from '#/components/product-used-price';
9import { dinero, type DineroSnapshot } from 'dinero.js';
10import { Suspense } from 'react';
11import { AddToCart } from '#/components/add-to-cart';
12import { delayShippingEstimate, withDelay } from '#/lib/delay';
13import { cookies } from 'next/headers';
14import { getProduct } from '#/lib/products';
15
16async function AddToCartFromCookies() {
17 // Tell Next.js to render dynamically at runtime instead of build-time
18 await connection();
19
20 // Get the cart count from the users cookies and pass it to the client
21 // AddToCart component
22 const cartCount = Number(cookies().get('_cart_count')?.value || '0');
23 return <AddToCart initialCartCount={cartCount} />;
24}
25
26function LoadingDots() {
27 return (
28 <div className="text-sm">
29 <span className="space-x-0.5">
30 <span className="inline-flex animate-[loading_1.4s_ease-in-out_infinite] rounded-full">
31 •
32 </span>
33 <span className="inline-flex animate-[loading_1.4s_ease-in-out_0.2s_infinite] rounded-full">
34 •
35 </span>
36 <span className="inline-flex animate-[loading_1.4s_ease-in-out_0.4s_infinite] rounded-full">
37 •
38 </span>
39 </span>
40 </div>
41 );
42}
43
44async function UserSpecificDetails({ productId }: { productId: string }) {
45 const data = await withDelay(
46 getProduct({ id: productId }),
47 delayShippingEstimate,
48 );
49
50 const product = (await data.json()) as Product;
51
52 const price = dinero(product.price as DineroSnapshot<number>);
53
54 return (
55 <>
56 <ProductSplitPayments price={price} />
57 {product.usedPrice ? (
58 <ProductUsedPrice usedPrice={product.usedPrice} />
59 ) : null}
60 <ProductEstimatedArrival leadTime={product.leadTime} hasDeliveryTime />
61 {product.stock <= 1 ? (
62 <ProductLowStockWarning stock={product.stock} />
63 ) : null}
64 </>
65 );
66}
67
68export function Pricing({ product }: { product: Product }) {
69 const price = dinero(product.price as DineroSnapshot<number>);
70
71 return (
72 <div className="space-y-4 rounded-lg bg-gray-900 p-3">
73 <ProductPrice price={price} discount={product.discount} />
74
75 <Ping />
76
77 <Suspense fallback={<LoadingDots />}>
78 <UserSpecificDetails productId={product.id} />
79 </Suspense>
80
81 <Suspense fallback={<AddToCart initialCartCount={0} />}>
82 <AddToCartFromCookies />
83 </Suspense>
84 </div>
85 );
86}