Skip to content

Commit

Permalink
changes made thorughout work
Browse files Browse the repository at this point in the history
  • Loading branch information
JD-n0v committed Nov 29, 2023
1 parent 9a23c64 commit 6b6a4ea
Show file tree
Hide file tree
Showing 14 changed files with 238 additions and 135 deletions.
1 change: 1 addition & 0 deletions apps/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@trpc/next": "^10.1.0",
"@trpc/react-query": "^10.1.0",
"@trpc/server": "^10.1.0",
"jotai": "^2.5.1",
"next": "^13.1.6",
"react": "18.2.0",
"react-dom": "18.2.0",
Expand Down
66 changes: 66 additions & 0 deletions apps/nextjs/src/atoms/cart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { atom } from "jotai";
import { atomFamily, atomWithStorage, createJSONStorage } from "jotai/utils";
import { productsAtom, singleProductAtomFamily } from "./products";

export const cartAtom = atomWithStorage<Record<number, number>>(
"cart",
{},
createJSONStorage(() => localStorage),
);

export const cartItemQuantityAtomFamily = atomFamily((id: number) =>
atom(
(get) => {
return get(cartAtom)[id] ?? 0;
},
(get, set, newValue: number) => {
const currentCart = get(cartAtom);
set(cartAtom, { ...currentCart, [id]: newValue });
},
),
);

export const cartTotalAtom = atom((get) => {
const currentCart = get(cartAtom);
const products = get(productsAtom);

const ids = Object.keys(currentCart);
let total = 0;

for (const pr of products) {
if (ids.includes(pr.id.toString())) {
total += (currentCart[pr.id] ?? 0) * pr.price.toNumber();
}
}

return total;
});

export const addItemToCartAtom = atomFamily(
({ id, quantity }: { id: number; quantity: number }) =>
atom(null, async (get, set) => {
const currentCart = get(cartAtom);
const currentQuantity = currentCart[id];
const currentItemStock =
get(singleProductAtomFamily(id))?.stock.toNumber() ?? 0;

const q = currentQuantity ? currentQuantity + quantity : quantity;

if (q < 1) {
set(cartAtom, { ...currentCart, [id]: 1 });
} else if (q <= currentItemStock) {
set(cartAtom, { ...currentCart, [id]: q });
} else {
set(cartAtom, { ...currentCart, [id]: currentItemStock });
}
}),
);

export const deleteItemFromCartAtom = atomFamily(({ id }: { id: number }) =>
atom(null, async (_, set) => {
set(cartAtom, async (prev) => {
const { [id]: toDelete, ...rest } = await prev;
return { ...rest };
});
}),
);
16 changes: 16 additions & 0 deletions apps/nextjs/src/atoms/products.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { AppRouter } from "@acme/api";
import { inferProcedureOutput } from "@trpc/server";
import { atom } from "jotai";
import { atomFamily } from "jotai/utils";

export const productsAtom = atom<
inferProcedureOutput<AppRouter["item"]["all"]>
>([]);

export const singleProductAtomFamily = atomFamily((id: number) =>
atom((get) => {
const product = get(productsAtom).filter((product) => product.id === id)[0];
if (!product) return null;
return product;
}),
);
5 changes: 5 additions & 0 deletions apps/nextjs/src/atoms/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { createStore } from "jotai";

const jotaiStore = createStore();

export default jotaiStore;
6 changes: 3 additions & 3 deletions apps/nextjs/src/components/ItemHeader/ItemHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ function ItemHeader() {
</span>
<span className={styles.listSpan}>
<ul>
<li onClick={() => router.back()}>Home</li>
<li>Shop</li>
<li>About</li>
<li onClick={() => router.push(`/`)}>Home</li>
<li onClick={() => router.push(`/shoppingCart`)}>Cart</li>
<li onClick={() => router.push(`/login`)}>Login</li>
<li>Contact</li>
</ul>
</span>
Expand Down
70 changes: 54 additions & 16 deletions apps/nextjs/src/components/content/Content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,83 @@ import Aside from "../aside/Aside";
import styles from "./Content.module.css";
import { trpc } from "../../utils/trpc";
import { useRouter } from "next/router";
import { useSetAtom } from "jotai";
import { productsAtom } from "../../atoms/products";
import { useEffect } from "react";
import { inferProcedureOutput } from "@trpc/server";
import { AppRouter } from "@acme/api";
import { addItemToCartAtom, deleteItemFromCartAtom } from "../../atoms/cart";

interface ContentProps {
filterValue: string;
}

function Content({ filterValue }: ContentProps) {
const { data } = trpc.item.all.useQuery();
const router = useRouter();
const setItemsAtom = useSetAtom(productsAtom);

const filteredData =
data?.filter((item) =>
item.name.toLowerCase().includes(filterValue.toLowerCase()),
) ?? [];

useEffect(() => {
setItemsAtom(data ?? []);
}, [data, setItemsAtom]);

return (
<>
<div className={styles.container}>
<Aside></Aside>
<main>
{filteredData.map((item) => (
<span
className={styles.card}
key={item.id}
onClick={() => router.push(`/item/${item.id}`)}
>
<picture>
<img
src={item.image_url != null ? item.image_url : ""}
alt="product"
/>
</picture>
<h3>{item.name}</h3>
<p>${item.price.toFixed(2)}</p>
<button type="button">Add to cart</button>
</span>
<ItemCard item={item} key={item.id} />
))}
</main>
</div>
</>
);
}

function ItemCard({
item,
}: {
item: inferProcedureOutput<AppRouter["item"]["all"]>[number];
}) {
const router = useRouter();
const addToCart = useSetAtom(addItemToCartAtom({ id: item.id, quantity: 1 }));
const deleteFromCart = useSetAtom(deleteItemFromCartAtom({ id: item.id }));

return (
<div
className={styles.card}
onClick={() => router.push(`/item/${item.id}`)}
>
<picture>
{" "}
<img src={item.image_url ? item.image_url : ""} alt={item.name} />
</picture>
<h3>{item.name}</h3>
<p>${item.price.toFixed(2)}</p>
<button
type="button"
onClick={(e) => {
e.stopPropagation();
addToCart();
}}
>
Add to cart
</button>
<button
type="button"
onClick={(e) => {
e.stopPropagation();
deleteFromCart();
}}
>
Delete
</button>
</div>
);
}
export default Content;
1 change: 0 additions & 1 deletion apps/nextjs/src/components/loginContent/LoginContent.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import styles from "./LoginContent.module.css";
import RegisterForm from "../RegisterForm/RegisterForm";
import { useRouter } from "next/router";
function LoginContent() {
const router = useRouter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,22 @@
}
.image {
height: 100px;
width: 100px;
border: 1px solid gray;
display: flex;
justify-content: center;
}
.details h3 {
font-size: large;
width: 250px;
}
.quantityBox {
height: 30px;
border: 1px solid black;
}
.quantityInput {
height: 100%;
width: 80px;
padding-left: 10px;
text-align: center;
}
Expand Down
Loading

0 comments on commit 6b6a4ea

Please sign in to comment.