Skip to content

Commit

Permalink
default -> new-york
Browse files Browse the repository at this point in the history
  • Loading branch information
sadmann7 committed Aug 20, 2023
1 parent 9373327 commit 8e5a44f
Show file tree
Hide file tree
Showing 39 changed files with 236 additions and 282 deletions.
2 changes: 1 addition & 1 deletion components.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"style": "new-york",
"rsc": true,
"tailwind": {
"config": "tailwind.config.js",
Expand Down
34 changes: 14 additions & 20 deletions src/app/(dashboard)/dashboard/billing/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card"
import { ManageStoreSubscriptionForm } from "@/components/forms/manage-store-subscription-form"
import { ManageSubscriptionForm } from "@/components/forms/manage-subscription-form"
import { Icons } from "@/components/icons"
import { PageHeader } from "@/components/page-header"
import { Shell } from "@/components/shells/shell"
Expand All @@ -34,10 +34,6 @@ export default async function BillingPage() {
redirect("/signin")
}

const email =
user.emailAddresses?.find((e) => e.id === user.primaryEmailAddressId)
?.emailAddress ?? ""

const subscriptionPlan = await getUserSubscriptionPlan(user.id)

return (
Expand Down Expand Up @@ -84,7 +80,8 @@ export default async function BillingPage() {
className={cn(
"flex flex-col",
i === storeSubscriptionPlans.length - 1 &&
"lg:col-span-2 xl:col-span-1"
"lg:col-span-2 xl:col-span-1",
i === 1 && "border-primary shadow-md"
)}
>
<CardHeader>
Expand All @@ -111,22 +108,19 @@ export default async function BillingPage() {
</CardContent>
<CardFooter className="pt-4">
{plan.id === "basic" ? (
<Link href="/dashboard/stores" className="w-full">
<div
className={cn(
buttonVariants({
className: "w-full",
})
)}
>
Manage Stores
<span className="sr-only">Manage Stores</span>
</div>
<Link
href="/dashboard/stores"
className={cn(
buttonVariants({
className: "w-full",
})
)}
>
Get started
<span className="sr-only">Get started</span>
</Link>
) : (
<ManageStoreSubscriptionForm
userId={user.id}
email={email}
<ManageSubscriptionForm
stripePriceId={plan.stripePriceId}
stripeCustomerId={subscriptionPlan?.stripeCustomerId}
stripeSubscriptionId={
Expand Down
2 changes: 1 addition & 1 deletion src/app/(dashboard)/dashboard/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default async function DashboardLayout({
<div className="container flex-1 items-start md:grid md:grid-cols-[220px_minmax(0,1fr)] md:gap-6 lg:grid-cols-[240px_minmax(0,1fr)] lg:gap-10">
<aside className="fixed top-14 z-30 -ml-2 hidden h-[calc(100vh-3.5rem)] w-full shrink-0 overflow-y-auto border-r md:sticky md:block">
<ScrollArea className="py-6 pr-6 lg:py-8">
<SidebarNav items={dashboardConfig.sidebarNav} />
<SidebarNav items={dashboardConfig.sidebarNav} className="p-1" />
</ScrollArea>
</aside>
<main className="flex w-full flex-col overflow-hidden">{children}</main>
Expand Down
19 changes: 8 additions & 11 deletions src/app/(dashboard)/dashboard/stores/[storeId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,16 +170,13 @@ export default async function UpdateStorePage({
href="https://dashboard.stripe.com/"
target="_blank"
rel="noopener noreferrer"
className={cn(
buttonVariants({
className: "text-center",
})
)}
>
<div
className={cn(
buttonVariants({
className: "text-center",
})
)}
>
Manage Stripe account
</div>
Manage Stripe account
</Link>
</CardFooter>
</Card>
Expand Down Expand Up @@ -246,15 +243,15 @@ export default async function UpdateStorePage({
</fieldset>
<div className="flex flex-col gap-2 xs:flex-row">
<LoadingButton>
Update Store
Update store
<span className="sr-only">Update store</span>
</LoadingButton>
<LoadingButton
// eslint-disable-next-line @typescript-eslint/no-misused-promises
formAction={deleteStore}
variant="destructive"
>
Delete Store
Delete store
<span className="sr-only">Delete store</span>
</LoadingButton>
</div>
Expand Down
26 changes: 9 additions & 17 deletions src/app/(dashboard)/dashboard/stores/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ import { db } from "@/db"
import { products, stores } from "@/db/schema"
import { env } from "@/env.mjs"
import { currentUser } from "@clerk/nextjs"
import { RocketIcon } from "@radix-ui/react-icons"
import { desc, eq, sql } from "drizzle-orm"

import {
getDashboardRedirectPath,
getFeaturedStoreAndProductCounts,
getPlanFeatures,
getUserSubscriptionPlan,
} from "@/lib/subscription"
import { formatDate } from "@/lib/utils"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { Icons } from "@/components/icons"
import { PageHeader } from "@/components/page-header"
import { Shell } from "@/components/shells/shell"
import { StoreCard } from "@/components/store-card"
Expand Down Expand Up @@ -47,30 +46,23 @@ export default async function StoresPage() {

const subscriptionPlan = await getUserSubscriptionPlan(user.id)

const { featuredStoreCount, featuredProductCount } =
getFeaturedStoreAndProductCounts(subscriptionPlan?.id)
const { maxStoreCount, maxProductCount } = getPlanFeatures(
subscriptionPlan?.id
)

return (
<Shell variant="sidebar">
<PageHeader title="Stores" description="Manage your stores" size="sm" />
<Alert>
<Icons.terminal className="h-4 w-4" aria-hidden="true" />
<RocketIcon className="h-4 w-4" aria-hidden="true" />
<AlertTitle>Heads up!</AlertTitle>
<AlertDescription>
You are currently on the{" "}
<span className="font-semibold">{subscriptionPlan?.name}</span> plan.{" "}
{!subscriptionPlan?.isSubscribed
? "Upgrade to create more stores and products."
: subscriptionPlan.isCanceled
? "Your plan will be canceled on "
: "Your plan renews on "}
{subscriptionPlan?.stripeCurrentPeriodEnd
? `${formatDate(subscriptionPlan.stripeCurrentPeriodEnd)}.`
: null}{" "}
You can create up to{" "}
<span className="font-semibold">{featuredStoreCount}</span> stores and{" "}
<span className="font-semibold">{featuredProductCount}</span> products
on this plan.
<span className="font-semibold">{maxStoreCount}</span> stores and{" "}
<span className="font-semibold">{maxProductCount}</span> products on
this plan.
</AlertDescription>
</Alert>
<div className="grid gap-4 sm:grid-cols-2 md:grid-cols-3">
Expand Down
20 changes: 6 additions & 14 deletions src/app/(lobby)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Link from "next/link"
import { db } from "@/db"
import { products, stores } from "@/db/schema"
import { desc, eq, sql } from "drizzle-orm"
import Balance from "react-wrap-balancer"
import { Balancer } from "react-wrap-balancer"

import { productCategories } from "@/config/products"
import { siteConfig } from "@/config/site"
Expand Down Expand Up @@ -87,27 +87,19 @@ export default async function IndexPage() {
<h1 className="text-3xl font-bold leading-tight tracking-tighter md:text-5xl lg:text-6xl lg:leading-[1.1]">
An e-commerce skateshop built with everything new in Next.js 13
</h1>
<Balance className="max-w-[46rem] text-lg text-muted-foreground sm:text-xl">
<Balancer className="max-w-[46rem] text-lg text-muted-foreground sm:text-xl">
Buy and sell skateboarding products from independent brands and stores
around the world
</Balance>
</Balancer>
<div className="flex flex-wrap items-center justify-center gap-4">
<Link
href="/products"
className={cn(
buttonVariants({
size: "lg",
})
)}
>
<Link href="/products" className={cn(buttonVariants())}>
Buy Now
</Link>
<Link
href="/dashboard/stores"
className={cn(
buttonVariants({
variant: "outline",
size: "lg",
})
)}
>
Expand All @@ -124,9 +116,9 @@ export default async function IndexPage() {
<h2 className="text-3xl font-bold leading-[1.1] sm:text-3xl md:text-5xl">
Categories
</h2>
<Balance className="max-w-[46rem] leading-normal text-muted-foreground sm:text-lg sm:leading-7">
<Balancer className="max-w-[46rem] leading-normal text-muted-foreground sm:text-lg sm:leading-7">
Explore our categories and find the best products for you
</Balance>
</Balancer>
</div>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
{productCategories.map((category) => (
Expand Down
12 changes: 8 additions & 4 deletions src/app/_actions/stripe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { db } from "@/db"
import { payments, stores } from "@/db/schema"
import { clerkClient } from "@clerk/nextjs"
import { currentUser } from "@clerk/nextjs"
import { eq } from "drizzle-orm"
import { type z } from "zod"

Expand All @@ -19,12 +19,16 @@ export async function manageSubscriptionAction(
) {
const billingUrl = absoluteUrl("/dashboard/billing")

const user = await clerkClient.users.getUser(input.userId)
const user = await currentUser()

if (!user) {
throw new Error("User not found.")
}

const email =
user.emailAddresses?.find((e) => e.id === user.primaryEmailAddressId)
?.emailAddress ?? ""

// If the user is already subscribed to a plan, we redirect them to the Stripe billing portal
if (input.isSubscribed && input.stripeCustomerId && input.isCurrentPlan) {
const stripeSession = await stripe.billingPortal.sessions.create({
Expand All @@ -44,15 +48,15 @@ export async function manageSubscriptionAction(
payment_method_types: ["card"],
mode: "subscription",
billing_address_collection: "auto",
customer_email: input.email,
customer_email: email,
line_items: [
{
price: input.stripePriceId,
quantity: 1,
},
],
metadata: {
userId: input.userId,
userId: user.id,
},
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,15 @@ import { Button } from "@/components/ui/button"
import { Icons } from "@/components/icons"
import { manageSubscriptionAction } from "@/app/_actions/stripe"

type ManageStoreSubscriptionFormProps = z.infer<
typeof manageSubscriptionSchema
> & {
isCurrentPlan: boolean
}
type ManageSubscriptionFormProps = z.infer<typeof manageSubscriptionSchema>

export function ManageStoreSubscriptionForm({
userId,
email,
export function ManageSubscriptionForm({
isCurrentPlan,
isSubscribed,
stripeCustomerId,
stripeSubscriptionId,
stripePriceId,
}: ManageStoreSubscriptionFormProps) {
}: ManageSubscriptionFormProps) {
const [isPending, startTransition] = React.useTransition()

function onSubmit(e: React.FormEvent<HTMLFormElement>) {
Expand All @@ -32,8 +26,6 @@ export function ManageStoreSubscriptionForm({
startTransition(async () => {
try {
const session = await manageSubscriptionAction({
email,
userId,
isSubscribed,
isCurrentPlan,
stripeCustomerId,
Expand All @@ -58,7 +50,7 @@ export function ManageStoreSubscriptionForm({
aria-hidden="true"
/>
)}
{isCurrentPlan ? "Manage Subscription" : "Subscribe"}
{isCurrentPlan ? "Manage" : "Subscribe"}
</Button>
</form>
)
Expand Down
7 changes: 4 additions & 3 deletions src/components/layouts/sidebar-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,23 @@ import type { SidebarNavItem } from "@/types"
import { cn } from "@/lib/utils"
import { Icons } from "@/components/icons"

export interface SidebarNavProps {
export interface SidebarNavProps extends React.HTMLAttributes<HTMLDivElement> {
items: SidebarNavItem[]
}

export function SidebarNav({ items }: SidebarNavProps) {
export function SidebarNav({ items, className, ...props }: SidebarNavProps) {
const pathname = usePathname()

if (!items?.length) return null

return (
<div className="flex w-full flex-col gap-2">
<div className={cn("flex w-full flex-col gap-2", className)} {...props}>
{items.map((item, index) => {
const Icon = Icons[item.icon ?? "chevronLeft"]

return item.href ? (
<Link
aria-label={item.title}
key={index}
href={item.href}
target={item.external ? "_blank" : ""}
Expand Down
19 changes: 8 additions & 11 deletions src/components/layouts/site-footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,15 @@ export function SiteFooter() {
href={siteConfig.links.github}
target="_blank"
rel="noreferrer"
className={cn(
buttonVariants({
size: "icon",
variant: "ghost",
})
)}
>
<div
className={cn(
buttonVariants({
size: "icon",
variant: "ghost",
})
)}
>
<Icons.gitHub className="h-4 w-4" aria-hidden="true" />
<span className="sr-only">GitHub</span>
</div>
<Icons.gitHub className="h-4 w-4" aria-hidden="true" />
<span className="sr-only">GitHub</span>
</Link>
<ThemeToggle />
</div>
Expand Down
17 changes: 8 additions & 9 deletions src/components/layouts/site-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,14 @@ export function SiteHeader({ user }: SiteHeaderProps) {
</DropdownMenuContent>
</DropdownMenu>
) : (
<Link href="/signin">
<div
className={buttonVariants({
size: "sm",
})}
>
Sign In
<span className="sr-only">Sign In</span>
</div>
<Link
href="/signin"
className={buttonVariants({
size: "sm",
})}
>
Sign In
<span className="sr-only">Sign In</span>
</Link>
)}
</nav>
Expand Down
Loading

0 comments on commit 8e5a44f

Please sign in to comment.