Skip to content

Commit

Permalink
feat: clean-up stores
Browse files Browse the repository at this point in the history
  • Loading branch information
sadmann7 committed Mar 10, 2024
1 parent a600d47 commit 8604e06
Show file tree
Hide file tree
Showing 28 changed files with 547 additions and 456 deletions.
2 changes: 1 addition & 1 deletion drizzle.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { type Config } from "drizzle-kit"
import { dbPrefix } from "@/lib/constants"

export default {
schema: "./src/db/schema.ts",
schema: "./src/db/schema/index.ts",
driver: "pg",
out: "./drizzle",
dbCredentials: {
Expand Down
54 changes: 30 additions & 24 deletions src/app/(dashboard)/dashboard/_components/store-switcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import { useParams, usePathname, useRouter } from "next/navigation"
import {
CaretSortIcon,
CheckIcon,
CircleIcon,
PlusCircledIcon,
ShadowIcon,
} from "@radix-ui/react-icons"

import { type getProgress } from "@/lib/actions/limit"

Check failure on line 12 in src/app/(dashboard)/dashboard/_components/store-switcher.tsx

View workflow job for this annotation

GitHub Actions / Typecheck

Cannot find module '@/lib/actions/limit' or its corresponding type declarations.
import { type getStoresByUserId } from "@/lib/actions/store"
import { type getProgress } from "@/lib/actions/user"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import {
Expand Down Expand Up @@ -85,28 +85,32 @@ export function StoreSwitcher({
<CommandList>
<CommandInput placeholder="Search store..." />
<CommandEmpty>No store found.</CommandEmpty>
{stores.map((store) => (
<CommandItem
key={store.id}
onSelect={() => {
setOpen(false)
router.push(`/dashboard/stores/${store.id}`)
}}
className="text-sm"
>
<CircleIcon className="mr-2 size-5" aria-hidden="true" />
{store.name}
<CheckIcon
className={cn(
"ml-auto size-4",
selectedStore?.id === store.id
? "opacity-100"
: "opacity-0"
)}
aria-hidden="true"
/>
</CommandItem>
))}
<CommandGroup>
{stores.map((store) => (
<CommandItem
key={store.id}
onSelect={() => {
setOpen(false)
pathname.includes(store.id)
? router.replace(pathname.replace(storeId, store.id))
: router.push(`/dashboard/stores/${store.id}`)
}}
className="text-sm"
>
<ShadowIcon className="mr-2 size-5" aria-hidden="true" />
{store.name}
<CheckIcon
className={cn(
"ml-auto size-4",
selectedStore?.id === store.id
? "opacity-100"
: "opacity-0"
)}
aria-hidden="true"
/>
</CommandItem>
))}
</CommandGroup>
</CommandList>
<CommandSeparator />
<CommandList>
Expand All @@ -116,6 +120,8 @@ export function StoreSwitcher({
setOpen(false)
setShowNewStoreDialog(true)
}}
aria-disabled={false}
disabled={false}
>
<PlusCircledIcon className="mr-2 size-5" aria-hidden="true" />
Create store
Expand Down
28 changes: 11 additions & 17 deletions src/app/(dashboard)/dashboard/billing/_components/billing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Link from "next/link"
import type { SubscriptionPlanWithPrice, UserSubscriptionPlan } from "@/types"
import { CheckIcon } from "@radix-ui/react-icons"

import { getUsageWithProgress } from "@/lib/subscription"
import { getPlanLimits } from "@/lib/subscription"
import { cn, formatDate } from "@/lib/utils"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
Expand All @@ -14,10 +14,9 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card"
import { UsageCard } from "@/components/cards/usage-card"
import { ManageSubscriptionForm } from "@/components/manage-subscription-form"

import { UsageCard } from "./usage-card"

interface BillingProps {
subscriptionPlanPromise: Promise<UserSubscriptionPlan | null>
subscriptionPlansPromise: Promise<SubscriptionPlanWithPrice[]>
Expand All @@ -38,23 +37,20 @@ export async function Billing({
usagePromise,
])

const { storeLimit, storeProgress, productLimit, productProgress } =
getUsageWithProgress({
planTitle: subscriptionPlan?.title ?? "free",
storeCount: usage.storeCount,
productCount: usage.productCount,
})
const { storeLimit, productLimit } = getPlanLimits({
planTitle: subscriptionPlan?.title,
})

return (
<>
<Card>
<CardHeader>
<CardTitle className="text-lg capitalize">Plan and Usage</CardTitle>
<CardTitle className="text-lg">Plan and Usage</CardTitle>
<div className="text-sm text-muted-foreground">
You&apos;re currently on the{" "}
<Badge
variant="secondary"
className="pointer-events-none capitalize text-foreground/90"
className="pointer-events-none text-foreground/90"
>
{subscriptionPlan?.title}
</Badge>{" "}
Expand All @@ -72,16 +68,14 @@ export async function Billing({
<CardContent className="grid gap-6 sm:grid-cols-2">
<UsageCard
title="Stores"
usage={usage.storeCount}
count={usage.storeCount}
limit={storeLimit}
progress={storeProgress}
moreInfo="The number of stores you can create on the current plan."
/>
<UsageCard
title="Products"
usage={usage.productCount}
count={usage.productCount}
limit={productLimit}
progress={productProgress}
moreInfo="The number of products you can create on the current plan."
/>
</CardContent>
Expand All @@ -95,7 +89,7 @@ export async function Billing({
})}
>
<CardHeader className="flex-1">
<CardTitle className="text-lg capitalize">{plan.title}</CardTitle>
<CardTitle className="text-lg">{plan.title}</CardTitle>
<CardDescription>{plan.description}</CardDescription>
</CardHeader>
<CardContent className="grid flex-1 place-items-start gap-6">
Expand All @@ -119,7 +113,7 @@ export async function Billing({
</div>
</CardContent>
<CardFooter className="pt-4">
{plan.title === "free" ? (
{plan.title === "Free" ? (
<Button className="w-full" asChild>
<Link href="/dashboard">
Get started
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
} from "@/components/ui/hover-card"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
import { UsageCard } from "@/components/cards/usage-card"
import { Icons } from "@/components/icons"
import { ManageSubscriptionForm } from "@/components/manage-subscription-form"

Expand Down Expand Up @@ -100,6 +101,7 @@ export function AddStoreDialog({
} finally {
setLoading(false)
setOpen(false)
onOpenChange?.(false)
form.reset()
}
}
Expand Down Expand Up @@ -269,15 +271,16 @@ function DynamicTrigger({

const {
storeLimit,
storeProgress,
storeCount,
productLimit,
productProgress,
productCount,
subscriptionPlan,
} = progress

const limtReached = storeProgress === 100 || productProgress === 100
const storeLimitReached = storeCount >= storeLimit
const productLimitReached = productCount >= productLimit

if (limtReached) {
if (storeLimitReached || productLimitReached) {
return (
<HoverCard>
<HoverCardTrigger asChild>
Expand All @@ -286,30 +289,43 @@ function DynamicTrigger({
</Button>
</HoverCardTrigger>
<HoverCardContent
className="w-80 space-y-2.5"
className="space-y-4 sm:w-80"
align="end"
sideOffset={8}
>
{storeProgress === 100 ? (
<div className="text-sm text-muted-foreground">
You can only create upto{" "}
<span className="font-bold">{storeLimit}</span> stores in your
current plan.
{storeLimitReached && (
<div className="space-y-3">
<div className="text-sm text-muted-foreground">
You&apos;ve reached the limit of{" "}
<span className="font-bold">{storeLimit}</span> stores for the{" "}
<span className="font-bold">{subscriptionPlan?.title}</span>{" "}
plan.
</div>
<UsageCard title="Stores" count={storeCount} limit={storeLimit} />
</div>
) : productProgress === 100 ? (
<div className="text-sm text-muted-foreground">
You can only create upto{" "}
<span className="font-bold">{productLimit}</span> products in your
current plan.
)}
{productLimitReached && (
<div className="space-y-3">
<div className="text-sm text-muted-foreground">
You&apos;ve reached the limit of{" "}
<span className="font-bold">{productLimit}</span> products for
the <span className="font-bold">{subscriptionPlan?.title}</span>{" "}
plan.
</div>
<UsageCard
title="Products"
count={productCount}
limit={productLimit}
/>
</div>
) : null}
{subscriptionPlan && subscriptionPlan.title !== "pro" ? (
)}
{subscriptionPlan && subscriptionPlan.title !== "Pro" ? (
<ManageSubscriptionForm
stripePriceId={subscriptionPlan.stripePriceId}
stripeCustomerId={subscriptionPlan.stripeCustomerId}
stripeSubscriptionId={subscriptionPlan.stripeSubscriptionId}
isSubscribed={subscriptionPlan.isSubscribed ?? false}
isCurrentPlan={subscriptionPlan.title === "standard"}
isCurrentPlan={subscriptionPlan.title === "Standard"}
/>
) : null}
</HoverCardContent>
Expand All @@ -319,7 +335,7 @@ function DynamicTrigger({

if (isDesktop) {
return (
<DialogTrigger>
<DialogTrigger asChild>
<Button>Create store</Button>
</DialogTrigger>
)
Expand Down
2 changes: 1 addition & 1 deletion src/app/(lobby)/_components/category-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface CategoryCardProps {

export function CategoryCard({ category }: CategoryCardProps) {
const productCountPromise = getProductCount({
categoryName: category.name,
categoryId: category.id,
})

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { QuestionMarkCircledIcon } from "@radix-ui/react-icons"

import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import {
Card,
Expand All @@ -15,23 +16,25 @@ import {
} from "@/components/ui/hover-card"
import { Progress } from "@/components/ui/progress"

interface UsageCardProps {
interface UsageCardProps extends React.ComponentPropsWithoutRef<typeof Card> {
title: string
usage: number
count: number
limit: number
progress: number
moreInfo?: string
}

export function UsageCard({
title,
count,
limit,
progress,
usage,
moreInfo,
className,
...props
}: UsageCardProps) {
const progress = Math.round((count / limit) * 100)

return (
<Card>
<Card className={cn(className)} {...props}>
<CardHeader>
<div className="flex items-center gap-2">
<CardTitle>{title}</CardTitle>
Expand All @@ -45,14 +48,14 @@ export function UsageCard({
/>
</Button>
</HoverCardTrigger>
<HoverCardContent className="w-80" sideOffset={8}>
<HoverCardContent className="sm:w-80" sideOffset={8}>
<p className="text-sm">{moreInfo}</p>
</HoverCardContent>
</HoverCard>
)}
</div>
<CardDescription>
{usage} / {limit} stores ({progress}%)
{count} / {limit} stores ({progress}%)
</CardDescription>
</CardHeader>
<CardContent>
Expand Down
14 changes: 7 additions & 7 deletions src/components/ui/alert-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,14 @@ AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName

export {
AlertDialog,
AlertDialogPortal,
AlertDialogOverlay,
AlertDialogTrigger,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogHeader,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogOverlay,
AlertDialogPortal,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogAction,
AlertDialogCancel,
AlertDialogTrigger,
}
Loading

0 comments on commit 8604e06

Please sign in to comment.