Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V.2 - Drizzle, app router, clerk, shadcn #8

Merged
merged 27 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
51d48c5
v2 init: drizzle, app router, clerk setup
andrewsolonets Sep 28, 2024
d3ec48f
home page setup, assets added, single product page init
andrewsolonets Sep 29, 2024
d4c5184
single product page, reviews, server action test
andrewsolonets Sep 29, 2024
03d23ec
ReviewForm working with api route (testing)
andrewsolonets Sep 30, 2024
1b6284d
feat: shadcn form styles, category pages, started using sonner for to…
andrewsolonets Oct 2, 2024
ebe6bfe
feat: cart trpc queries, header component added
andrewsolonets Oct 2, 2024
bd81650
feat: cart working with trpc setup, stripe init, hooks moved from v1
andrewsolonets Oct 3, 2024
7cb30e8
feat: drizzle products infinite query, product page, cart menu upd
andrewsolonets Oct 4, 2024
ea893f5
feat: order creation w clerk, images upd, shadcn table
andrewsolonets Oct 5, 2024
f57bd49
feat: breadcrumb in single product, navbar refactor
andrewsolonets Oct 6, 2024
7f71a3b
fix: pnpm removed
andrewsolonets Oct 6, 2024
f3bac68
fix: checkoutsessions type fix
andrewsolonets Oct 6, 2024
747fe54
fix: checkout sessions type fix
andrewsolonets Oct 6, 2024
3538c8f
fix: type fix, payment status fix webhook
andrewsolonets Oct 6, 2024
d33deaf
fix: review form upd
andrewsolonets Oct 6, 2024
cf7469d
fix(QuantitywCart): quantity null fix
andrewsolonets Oct 6, 2024
c4c637a
fix(ProductCard): quantity fix type
andrewsolonets Oct 6, 2024
2248086
fix(ProductReviews): type fixes
andrewsolonets Oct 6, 2024
da80c65
fix: seed type errors
andrewsolonets Oct 6, 2024
88eb49c
fix: type fixes
andrewsolonets Oct 6, 2024
5102b68
fix: clerk env vars added to envjs file
andrewsolonets Oct 6, 2024
80ea234
fix(CartContext): cart provider covering the entire app to get guest …
andrewsolonets Oct 6, 2024
de24134
chore: readme todo list created
andrewsolonets Oct 6, 2024
812b224
feat: algolia search implemented
andrewsolonets Oct 7, 2024
7565bcc
fix: schema cartitem fix, removed console logs from checkout route
andrewsolonets Oct 8, 2024
e304397
chore: seed files renamed, comments cleaned up, readme updated
andrewsolonets Oct 8, 2024
c6e8a56
chore: app version in package json updated
andrewsolonets Oct 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: breadcrumb in single product, navbar refactor
  • Loading branch information
andrewsolonets committed Oct 6, 2024
commit f57bd4958135b0629cab067a0d34f7aa80d95813
16 changes: 4 additions & 12 deletions src/app/categories/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
import { ProductCard } from "~/components/ui/ProductCard";
import { db } from "~/server/db";
import { getCategory } from "~/server/queries";

export default async function SingleCategory({
params: { id: id },
}: {
params: { id: string };
}) {
const category = await db.query.categories.findFirst({
where: (categories, { eq }) => eq(categories.id, Number(id)),
with: {
products: {
with: {
reviews: true,
},
},
},
});
const category = await getCategory(Number(id));
console.log(category?.products);
return (
<>
<section className="mt-32 flex h-fit flex-col gap-24 px-4 py-4 md:px-8">
<section className="mt-12 flex h-fit flex-col gap-6 px-4 py-4 md:px-8">
<h2 className="mb-8 text-3xl font-bold">{category?.name}</h2>
<div className="grid grid-cols-[repeat(auto-fit,_minmax(200px,_1fr))] gap-4">
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
{category?.products?.map((el) => (
<ProductCard product={el} key={el.id} />
))}
Expand Down
2 changes: 1 addition & 1 deletion src/app/categories/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import CategoryList from "~/components/CategoryList";

export default async function Categories() {
return (
<section className="mt-32 h-fit px-8 py-4">
<section className="mt-12 h-fit px-8 py-4">
<h2 className="mb-8 text-3xl font-bold">All Categories</h2>
<CategoryList />
</section>
Expand Down
6 changes: 3 additions & 3 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ export default function RootLayout({
<TRPCReactProvider>
<CartProvider>
<Header />
<main>{children}</main>
<Footer />
<Toaster />
</CartProvider>
<main>{children}</main>
<Footer />
<Toaster />
</TRPCReactProvider>
</body>
</html>
Expand Down
10 changes: 7 additions & 3 deletions src/app/products/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ import PlusIcon from "public/img/PlusIcon";
import { useState } from "react";
import { toast } from "react-toastify";
import { FeaturedList } from "~/app/_components/FeaturedList";
import ProductBreadcrumb from "~/components/ProductBreadcrumb";
import { QuantitywCart } from "~/components/QuantitywCart";
import { BigButton } from "~/components/ui/Buttons";
import { ProductReviews } from "~/components/ui/ProductReviews";
import { getFeaturedProducts, getProduct } from "~/server/queries";

// TODO: Make breadcrumb links

export default async function SingleProductPage({
params: { id: id },
}: {
Expand All @@ -21,7 +24,7 @@ export default async function SingleProductPage({

const item = await getProduct(Number(id));
if (!item) return;
const { image, title, price, quantity } = item;
const { image, title, price, quantity, categoryId } = item;

// return (
// <>
Expand All @@ -32,9 +35,10 @@ export default async function SingleProductPage({
// </>
// );
return (
<section className="mt-32 flex h-fit flex-col gap-24 px-4 py-4 md:px-8">
<section className="flex h-fit flex-col gap-12 px-4 py-4 md:px-8">
<ProductBreadcrumb product={item} />
<div className="flex w-full flex-col items-center justify-between gap-20 md:flex-row md:items-start">
<div className="b- border- relative h-72 w-72 rounded-lg border-8 border-amber-400 object-cover">
<div className="relative h-72 w-72 rounded-lg border-8 border-amber-400 object-cover">
<Image
// changed image to static for data saving
// src={image}
Expand Down
6 changes: 3 additions & 3 deletions src/app/products/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ export default function AllProducts() {

useEffect(() => {
if (inView && hasNextPage) {
fetchNextPage();
void fetchNextPage();
}
}, [inView]);

// data will be split in pages
return (
<>
<section className="mt-32 h-fit px-4 py-4 md:px-8">
<div className="relative flex w-full flex-col items-center justify-center">
<section className="mt-12 h-fit px-4 py-4 md:px-8">
<div className="relative flex w-full flex-col">
<h2 className="mb-8 text-3xl font-bold">All Products</h2>
<div className="grid auto-cols-max grid-cols-1 gap-6 md:grid-cols-3 lg:grid-cols-4">
{data?.pages.map((page) => (
Expand Down
2 changes: 1 addition & 1 deletion src/components/CartItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { type CartItemPlus } from "../utils/helpers";
import CrossIcon from "public/img/CrossIcon";
import PlusIcon from "public/img/PlusIcon";
import MinusIcon from "public/img/MinusIcon";
import { CartItemGuest } from "~/types/cart";
import { CartItem, CartItemGuest } from "~/types/cart";

type Props = {
item: CartItemPlus | CartItemGuest;
Expand Down
11 changes: 9 additions & 2 deletions src/components/CartMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { CartItemCard } from "./CartItem";
import { useCart } from "../context/CartContext";
import { api } from "~/trpc/react";
import { ArrowBtn, OutlineBtn } from "./ui/Buttons";
import { CartItemGuest } from "~/types/cart";
import { CartItemPlus } from "~/utils/helpers";

export const CartMenu = ({ isOpen }: { isOpen: boolean }) => {
const { clearCart, createCheckOutSession } = useCartActions();
Expand Down Expand Up @@ -38,7 +40,9 @@ export const CartMenu = ({ isOpen }: { isOpen: boolean }) => {
<div className="flex h-fit w-full flex-col gap-4 overflow-y-auto md:w-[600px]">
{cartItems
? cartItems?.map((el) => {
return <CartItemCard key={el.id} item={el} />;
return (
<CartItemCard key={el.id} item={el as CartItemGuest} />
);
})
: guestItems
? guestItems?.map((el) => {
Expand All @@ -54,7 +58,10 @@ export const CartMenu = ({ isOpen }: { isOpen: boolean }) => {
</div>
<ArrowBtn
onClick={() =>
createCheckOutSession(cartItems ? cartItems : guestItems)
createCheckOutSession(
//@ts-expect-error cart items type error
cartItems ? (cartItems as CartItemPlus) : guestItems,
)
}
>
Checkout
Expand Down
72 changes: 32 additions & 40 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,59 +12,51 @@ import { usePathname } from "next/navigation";
import CartIcon from "public/img/CartIcon";
import ProfileIcon from "public/img/ProfileIcon";
import { useCart } from "~/context/CartContext";
import { cn } from "~/lib/utils";
import { api } from "~/trpc/react";

// TODO: refactor navigation - use client component only when needed, disable links when on that page, use shadcn
// TODO: Make breadcrumb links
// TODO: Make header glass effect
// TODO: use client component only when needed - move client side parts to separate comps.

const NavMain = () => {
const pathname = usePathname();
const LINKS: { text: string; href: string }[] = [
{ text: "Home", href: "/" },
{ text: "Categories", href: "/categories" },
{ text: "All products", href: "/products" },
];

return (
<ul className="hidden items-center gap-10 sm:flex">
<li>
<Link
href="/"
className={`transition-all duration-300 hover:text-violet-300 active:text-amber-300 ${
pathname == "/" ? "font-semibold text-amber-400" : "text-slate-50"
}`}
>
Home
</Link>
</li>
<li>
<Link
href="/categories"
className={`transition-all duration-300 hover:text-violet-300 active:text-amber-300 ${
pathname == "/categories"
? "font-semibold text-amber-400"
: "text-slate-50"
}`}
>
Categories
</Link>
</li>
<li className="w-max">
<Link
href="/products"
className={`transition-all duration-300 hover:text-violet-300 active:text-amber-300 ${
pathname == "/products"
? "font-semibold text-amber-400"
: "text-white"
}`}
>
All Products
</Link>
</li>
{LINKS.map((link) => (
<li key={link.href}>
<Link
href={link.href}
aria-disabled={pathname === link.href}
tabIndex={pathname === link.href ? -1 : undefined}
className={cn(
"transition-all duration-300 hover:text-violet-300 active:text-amber-300",
pathname === link.href
? "pointer-events-none font-semibold text-amber-400"
: "",
)}
>
{link.text}
</Link>
</li>
))}
</ul>
);
};

export const Header = () => {
// const { data: sessionData } = useSession();
const { userId } = useAuth();
const { toggleCart, getCartQuantity } = useCart();

// const userId = sessionData?.user?.id;
const { data: cartItems } = api.cart.getCartItems.useQuery();
const { data: cartItems } = api.cart.getCartItems.useQuery(undefined, {
staleTime: 60 * 1000,
enabled: !!userId,
});

let totalQuantity = 0;

if (cartItems) {
Expand Down
39 changes: 39 additions & 0 deletions src/components/ProductBreadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "~/components/ui/breadcrumb";
import type { ProductWithRelations } from "~/server/db/schema";

export default function ProductBreadcrumb({
product,
}: {
product: ProductWithRelations;
}) {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/products">All products</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href={`/categories/${product.categoryId}`}>
{product.category?.name}
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>{product.title}</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
);
}
2 changes: 1 addition & 1 deletion src/components/UserOrders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default function UserOrders({ orders }: { orders: OrderModel[] }) {
{/* <TableCaption>A list of your recent invoices.</TableCaption> */}
<TableHeader>
<TableRow>
<TableHead className="w-[300px]">Date</TableHead>
<TableHead className="w-[150px]">Date</TableHead>
<TableHead>Status</TableHead>

<TableHead className="text-right">Total Amount</TableHead>
Expand Down
Loading