Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d3c84ba
Add id and stock_level in VariantTransformer
noelreissig Jul 5, 2023
936faf6
Set chosenVariant in productStore to get the stock of the selected va…
noelreissig Jul 7, 2023
5be2f6f
Add info to chosenVariant and improve code explanation
noelreissig Jul 7, 2023
b903899
Control input buttons (arrow) as per stock and availability
noelreissig Jul 7, 2023
9fd8378
Control add to cart quantity vs. stock
noelreissig Jul 8, 2023
85a611f
Modify `Coming Soon` with `Out of stock`
noelreissig Jul 8, 2023
a818c79
Reviews functionality (#173)
FelipeCabreraB Jul 10, 2023
68950d4
Update ProductProp for matching options with variants by id
noelreissig Jul 10, 2023
8c87845
Temp - Working stock logic
JoaquinEtchegaray Jul 14, 2023
de55056
Fix TS issues
JoaquinEtchegaray Jul 19, 2023
fa42c98
Set the button as disable when Out of Stock
noelreissig Jul 19, 2023
3361086
Add id and stock_level in VariantTransformer
noelreissig Jul 5, 2023
81d7783
Set chosenVariant in productStore to get the stock of the selected va…
noelreissig Jul 7, 2023
631e72a
Add info to chosenVariant and improve code explanation
noelreissig Jul 7, 2023
d104ae6
Control input buttons (arrow) as per stock and availability
noelreissig Jul 7, 2023
4202615
Control add to cart quantity vs. stock
noelreissig Jul 8, 2023
c7ad5c1
Modify `Coming Soon` with `Out of stock`
noelreissig Jul 8, 2023
c6bb375
Update ProductProp for matching options with variants by id
noelreissig Jul 10, 2023
fdb035f
Temp - Working stock logic
JoaquinEtchegaray Jul 14, 2023
5520548
Fix TS issues
JoaquinEtchegaray Jul 19, 2023
8cb2c6f
Set the button as disable when Out of Stock
noelreissig Jul 19, 2023
2611d47
Merge branch 'variants-and-stock-refactor' of https://github.com/Comm…
JoaquinEtchegaray Jul 20, 2023
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
2 changes: 1 addition & 1 deletion app/_components/Globals/Cart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const Cart = ({ isCartOpen, setIsCartOpen }: Props) => {
</div>
{/* products sections */}
<div className="overflow-y-auto px-7 mb-auto">
{cart?.items.length === 0 || cart === null ? (
{cart?.items?.length === 0 || cart === null ? (
<p>There are no items in your cart yet!</p>
) : (
<>
Expand Down
2 changes: 1 addition & 1 deletion app/_components/Globals/Spinner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const Spinner = ({ position = 'center', size = 10, className }: SpinnerPr
<div className={`text-${position} ${className ? className : ''}`}>
<div role="status">
<svg
className={`inline mr-2 w-${size} h-${size} text-gray-medium animate-spin dark:text-gray-dark fill-gray`}
className={`inline w-${size} h-${size} text-gray-medium animate-spin dark:text-gray-dark fill-gray`}
viewBox="0 0 100 101"
fill="none"
xmlns="http://www.w3.org/2000/svg"
Expand Down
20 changes: 17 additions & 3 deletions app/_hooks/useStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,25 @@ export function useGlobalState() {
****************************************************************************/
type StateProduct = {
chosenOptions: { [key: string]: string };
chosenOptionsId: string[];
chosenVariant: {
variantLabel: string | undefined;
variantId: string | undefined;
variantActive: boolean | undefined;
variantStock: number | undefined;
};
};

const stateProduct = atom({
chosenOptions: {}
const stateProduct = atom<StateProduct>({
chosenOptions: {},
chosenOptionsId: [],
chosenVariant: { variantId: '', variantActive: true, variantLabel: '', variantStock: 0 }
});

export function useProductState(): {
productState: StateProduct;
updateProductProp: (property: string, value: unknown) => void;
updateProductState: (newState: StateProduct) => void;
} {
const [productState, setProductState] = useAtom(stateProduct);

Expand All @@ -36,7 +46,11 @@ export function useProductState(): {
});
};

return { productState, updateProductProp };
const updateProductState = (newState: StateProduct) => {
setProductState(newState);
};

return { productState, updateProductProp, updateProductState };
}

/*****************************************************************************
Expand Down
62 changes: 59 additions & 3 deletions app/_lib/Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ class Store {
sku: product.sku || null,
images: this.transformImages(product),
categories: product.category_index?.id,
stock: product.stock_level
stock: product.stock_level,
reviewRating: product.review_rating
};
}

Expand All @@ -127,7 +128,7 @@ class Store {
* Convert Swell product options to generic format
****************************************************************************/
transformProductOptions(product: SwellProduct) {
return product.options.map((option) => ({
return product.options?.map((option) => ({
label: option.name,
active: option.active,
values: option.values
Expand All @@ -139,9 +140,11 @@ class Store {
****************************************************************************/
transformProductVariants(product: SwellProduct) {
return product.variants?.results?.map((variant) => ({
id: variant.id,
name: variant.name,
active: variant.active,
value_ids: variant.option_value_ids
value_ids: variant.option_value_ids,
stock_variant: variant.stock_level
}));
}

Expand Down Expand Up @@ -177,6 +180,59 @@ class Store {
limit
};
}

async getReviews(reviewInfo: { productId: string; limit?: number; page?: number }) {
const { productId, limit = 10, page } = reviewInfo;
const reviews = await swell.get('/products:reviews', {
parent_id: productId,
limit,
page
});
return reviews;
}

async postReview(reviewInfo: {
userId: string;
comments: string;
productId: string;
rating: number;
title: string;
}) {
const { userId, comments, productId, rating, title } = reviewInfo;

const reviews = await swell.post('/products:reviews', {
account_id: userId,
comments: comments,
parent_id: productId,
rating: rating,
title: title,
approved: true
});
return reviews;
}

async deleteReview(reviewId: string) {
const review = await swell.delete(`/products:reviews/${reviewId}`);
return review;
}

async editReview(
reviewId: string,
reviewInfo: {
comments: string;
rating: number;
title: string;
}
) {
const { comments, rating, title } = reviewInfo;

const review = await swell.put(`/products:reviews/${reviewId}`, {
comments: comments,
rating: rating,
title: title
});
return review;
}
}

export default new Store();
5 changes: 3 additions & 2 deletions app/_lib/SwellAPI.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';
import 'server-only';

import Store from './Store';
Expand Down Expand Up @@ -104,6 +103,7 @@ export const getLoggedUser = async (): Promise<SwellAPI_Customer | null> => {
name
}
product {
id
name
images {
file {
Expand Down Expand Up @@ -157,7 +157,7 @@ export const getUserInfo = async () => {
const user = await getLoggedUser();

if (!user?.session.accountId) {
return redirect('/account/login');
return { authenticated: false, user: null, userId: null, orders: [], addresses: [], cards: [] };
}

const addresses = await getAddresses();
Expand All @@ -166,6 +166,7 @@ export const getUserInfo = async () => {
return {
authenticated: true,
user: user.account,
userId: user.session.accountId,
orders: user.orders.results || [],
addresses: addresses || [],
cards: cards || []
Expand Down
2 changes: 1 addition & 1 deletion app/_types/Generic/Generic.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
interface Pagination {
total: number;
total?: number;
pages: number[];
current: number;
limit: number;
Expand Down
6 changes: 5 additions & 1 deletion app/_types/Generic/Products.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface Product {
sku?: string | null;
categories?: string[];
stock?: number;
reviewRating?: number;
}

interface ProductImage {
Expand All @@ -29,9 +30,12 @@ interface ProductOption {
}

interface Variant {
id: string;
name: string;
active: boolean;
value_ids: string[];
value_ids: Record<string, string> | string[];
stock_variant: number;
variantActive: boolean;
}

interface GenericProductsList {
Expand Down
21 changes: 21 additions & 0 deletions app/_types/Generic/Reviews.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
type Reviews = {
count: number;
page_count: number;
page: number;
results: Review[];
pages: {
[key: string]: { start: number; end: number };
};
};

interface Review {
account_id: string;
comments: string;
parent_id: string;
rating: number;
title: string;
name: string;
date_created: string;
approved: boolean;
id: string;
}
2 changes: 2 additions & 0 deletions app/_types/Swell/Product.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ interface SwellProduct {
sale_price?: number | null;
sku?: string;
category_index: CategoryIndex;
review_rating: number;
id: string;
}

Expand Down Expand Up @@ -103,4 +104,5 @@ interface SwellVariant {
date_updated: string;
sku?: string;
id: string;
stock_level: number;
}
1 change: 1 addition & 0 deletions app/_types/Swell/SwellAPI.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ interface SwellAPI_Order {
name: string;
};
product: {
id: string;
name: string;
price: number;
images: {
Expand Down
2 changes: 2 additions & 0 deletions app/_types/Swell/swell-js_index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ declare module 'swell-js' {
variant: { name: string; id: string };
taxTotal: number;
product: Product;
variant_id: string;
}

export interface CartItemSnakeCase {
Expand All @@ -120,6 +121,7 @@ declare module 'swell-js' {
variant: { name: string; id: string };
tax_total: number;
product: Product;
variant_id: string;
}

export type CartItem = CartItemCamelCase | CartItemSnakeCase;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client';

import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { useRouter, useSearchParams } from 'next/navigation';
import { useSearchParams } from 'next/navigation';
import { useRef, useState } from 'react';
import { SubmitHandler, useForm } from 'react-hook-form';
import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai';
Expand Down
5 changes: 2 additions & 3 deletions app/account/(user)/addresses/_components/AddressCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,20 @@ const AddressCard = ({ address }: Props) => {
</div>
<div className="flex flex-col justify-between">
<button className="flex justify-center items-center pt-1" onClick={() => setOpen(true)}>
<EditIcon />
<EditIcon strokeColor="black" />
</button>
<DeleteAddressModal
addressId={address.id}
openModal={openModal}
setOpenModal={setOpenModal}
/>
<button
className="hover:stroke-red-500"
data-delete="address"
onClick={() => {
void setOpenModal(true);
}}
>
<TrashIcon />
<TrashIcon strokeColor="red" />
</button>
<EditAddressModal open={open} setOpen={setOpen} address={address} />
</div>
Expand Down
7 changes: 7 additions & 0 deletions app/account/(user)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { redirect } from 'next/navigation';

import EditProfileModal from './_components/EditProfileModal';
import AccountLink from './_components/Link';
import LogOutModal from './_components/LogOutModal';
Expand All @@ -9,6 +11,11 @@ import { getUserInfo } from '~/_lib/SwellAPI';
export default async function Layout({ children }: { children: React.ReactNode }) {
const { user: account } = await getUserInfo();

// Prevent access to account pages if user is not logged in
if (!account) {
return redirect('/account/login');
}

return (
<Container className="mb-10">
<div className="grid gap-10 lg:gap-0 lg:grid-cols-12 pt-10 font-quicksand space-x-10">
Expand Down
2 changes: 1 addition & 1 deletion app/account/(user)/payments/_components/PaymentsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const PaymentCard = ({ card, defaultCard }: PaymentCardProps) => {
<div className={`flex flex-col ${defaultCard ? 'justify-between items-end' : 'justify-end'}`}>
{defaultCard && <p className="bg-gray shadow p-1 px-2 text-xs">Default</p>}
<button onClick={() => setOpenConfModal(true)}>
<TrashIcon />
<TrashIcon strokeColor="red" />
</button>
</div>
<DeleteCardModal
Expand Down
Loading