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

Implement cart page (2) #141

Merged
merged 37 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
54727a6
Implement cart page
raymosun Jan 29, 2024
12e54a0
Restore missing API function
raymosun Jan 29, 2024
fc4176f
Clean up code
raymosun Jan 29, 2024
b1c833c
Update dropped file
raymosun Jan 29, 2024
6a25eb6
Integrate with real linkedEvent
raymosun Jan 29, 2024
00607c6
Messing with supporting pickup events lacking linked event
raymosun Feb 1, 2024
5eb26a8
Clean up some code
raymosun Feb 5, 2024
56f092a
Clean up more code
raymosun Feb 5, 2024
9d184de
Refactor mock cart to debug page
raymosun Feb 5, 2024
046ac56
Fix some lil bugs
raymosun Feb 6, 2024
10cd009
Fix error message
raymosun Feb 12, 2024
edb559a
Implement warnings for sold-out/limit-reachecd items
raymosun Feb 12, 2024
88b7460
Fix some dpc comments
raymosun Feb 12, 2024
acc235e
Merge branch 'main' into raymond/store-cart-page-ii
raymosun Feb 12, 2024
b2d1d40
Update criteria for showing /debug page
raymosun Feb 12, 2024
5e54e0c
Merge branch 'raymond/store-cart-page-ii' of https://github.com/acmuc…
raymosun Feb 12, 2024
81c107a
Rework confirmation to omit modal-in-modal
raymosun Feb 13, 2024
df47a9f
Fix prop type
raymosun Feb 13, 2024
3c5f154
Add back button
raymosun Feb 13, 2024
2dfb5b2
Fix event confirmation modal width
raymosun Feb 13, 2024
48be788
Refactor placeMerchOrder to StoreManager
raymosun Feb 15, 2024
befa3ad
Merge branch 'main' into raymond/store-cart-page-ii
raymosun Feb 27, 2024
e9a8f7d
Fix merge problems
raymosun Feb 27, 2024
5fad921
Fix more merge problems
raymosun Feb 27, 2024
fe55861
Fix more merge problems (2)
raymosun Feb 27, 2024
655bf86
Fix more merge problems (3) 🙄
raymosun Feb 27, 2024
f4fae15
Fix some nits
raymosun Feb 27, 2024
7bd9578
Update remove/cancel buttons
raymosun Mar 4, 2024
2986fa8
Fix bug with uuid for pickup events
raymosun Mar 4, 2024
0476a72
Updated event picker cards with no modal
raymosun Mar 4, 2024
e47cb8a
Refactor event width from css
raymosun Mar 4, 2024
abae27d
Remove unnecessary ??
raymosun Mar 4, 2024
a443204
Update purchase limit messages
raymosun Mar 4, 2024
9006377
Merge branch 'main' into raymond/store-cart-page-ii
raymosun Mar 4, 2024
2600c8e
Fix merge bug
raymosun Mar 4, 2024
fe47539
Merge branch 'main' into raymond/store-cart-page-ii
raymosun Mar 5, 2024
cd1e3a6
Weird stuff
raymosun Mar 5, 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
2 changes: 1 addition & 1 deletion public/assets/icons/arrow-left.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion public/assets/icons/arrow-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions public/assets/icons/empty-cart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 12 additions & 4 deletions src/components/common/Modal/index.tsx
raymosun marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,27 @@ const Modal = ({ title, open, onClose, children }: ModalProps) => {
e.currentTarget.close();
}
}}
onClose={onClose}
onClose={e => {
e.stopPropagation();
onClose();
}}
>
<form method="dialog" className={`${styles.modalBody} ${title ? styles.hasHeader : ''}`}>
<div className={`${styles.modalBody} ${title ? styles.hasHeader : ''}`}>
{title && (
<div className={styles.header}>
<h1>{title}</h1>
<button type="submit" className={styles.close} aria-label="Close">
<button
type="button"
onClick={() => ref.current?.close()}
className={styles.close}
aria-label="Close"
>
<CloseIcon aria-hidden />
</button>
</div>
)}
{children}
</form>
</div>
</dialog>
);
};
Expand Down
85 changes: 85 additions & 0 deletions src/components/store/CartItemCard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { Typography } from '@/components/common';
import Diamonds from '@/components/store/Diamonds';
import StoreModal from '@/components/store/StoreModal';
import { config } from '@/lib';
import { UUID } from '@/lib/types';
import { ClientCartItem } from '@/lib/types/client';
import { capitalize } from '@/lib/utils';
import Image from 'next/image';
import Link from 'next/link';
import styles from './style.module.scss';

interface CartItemCardProps {
item: ClientCartItem;
removeItem?: (optionUUID: UUID) => void;
removable: boolean;
}

const CartItemCard = ({ item, removeItem, removable }: CartItemCardProps) => {
const itemPage = `${config.itemRoute}${item.uuid}`;

return (
<div className={styles.cartItem}>
{item.merchPhotos?.[0] && (
<div className={styles.leftCol}>
<Link href={itemPage}>
<div className={styles.imageWrapper}>
<Image
src={item.merchPhotos[0].uploadedPhoto}
raymosun marked this conversation as resolved.
Show resolved Hide resolved
alt={item.itemName}
sizes={`(max-width: ${config.cssVars.breakpointMd}) 100px, 150px`}
fill
/>
</div>
</Link>
</div>
)}
<div className={styles.rightCol}>
<div className={styles.cartItemInfo}>
<div className={styles.title}>
<Link href={itemPage}>
<Typography variant="h4/medium" component="h3">
{item.itemName}
</Typography>
</Link>
<Diamonds count={item.option.price * item.quantity ?? 0} className={styles.price} />
raymosun marked this conversation as resolved.
Show resolved Hide resolved
</div>

{item.option.metadata && (
<Typography variant="h5/bold" component="p">
{capitalize(item.option.metadata?.type)}&nbsp;
<Typography variant="h5/regular" component="span">
{item.option.metadata?.value}
</Typography>
</Typography>
)}
<Typography variant="h5/bold" component="p">
Quantity:&nbsp;
<Typography variant="h5/regular" component="span">
{item.quantity}
</Typography>
</Typography>
</div>
</div>
{removable && (
raymosun marked this conversation as resolved.
Show resolved Hide resolved
<StoreModal
opener={
<button type="button" className={styles.removeBtn}>
<Typography variant="h5/regular" component="span">
Remove Item
</Typography>
</button>
}
title="Are you sure you want to remove this item?"
onConfirm={() => {
setTimeout(() => removeItem && removeItem(item.option.uuid), 100);
}}
>
<CartItemCard item={item} removable={false} />
</StoreModal>
)}
</div>
);
};

export default CartItemCard;
89 changes: 89 additions & 0 deletions src/components/store/CartItemCard/style.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
@use 'src/styles/vars.scss' as vars;

.cartItem {
--desktop-image-size: 150px;
--mobile-image-size: 100px;
display: grid;
gap: 1.5rem;
grid-template-areas:
"left right"
"left remove";
grid-template-columns: var(--desktop-image-size) 1fr;
padding: 0.75rem 1rem;

@media (max-width: vars.$breakpoint-md) {
grid-template-areas:
"left right"
"remove right";
grid-template-columns: var(--mobile-image-size) 1fr;
}

.leftCol {
align-items: center;
display: flex;
flex-direction: column;
gap: 1rem;
grid-area: left;
justify-content: space-between;

.imageWrapper {
height: var(--desktop-image-size);
position: relative;
width: var(--desktop-image-size);

@media (max-width: vars.$breakpoint-md) {
height: var(--mobile-image-size);
width: var(--mobile-image-size);
}
}
}

.rightCol {
display: flex;
flex: 1;
flex-direction: column;
grid-area: right;
justify-content: space-between;

.cartItemInfo {
align-self: stretch;
display: flex;
flex-direction: column;
flex-grow: 1;
gap: 0.5rem;

.title {
align-items: baseline;
display: flex;
gap: 1rem;
justify-content: space-between;

@media (max-width: vars.$breakpoint-md) {
flex-direction: column;
}

h3:hover {
text-decoration: underline;
}

.price {
justify-self: flex-end;
white-space: nowrap;
}
}
}
}

.removeBtn {
align-self: end;
background-color: transparent;
color: var(--theme-danger-1);
grid-area: remove;
padding: 0;
width: fit-content;

@media (max-width: vars.$breakpoint-md) {
margin: auto;
}
}
}
16 changes: 16 additions & 0 deletions src/components/store/CartItemCard/style.module.scss.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export type Styles = {
cartItem: string;
cartItemInfo: string;
imageWrapper: string;
leftCol: string;
price: string;
removeBtn: string;
rightCol: string;
title: string;
};

export type ClassNames = keyof Styles;

declare const styles: Styles;

export default styles;
64 changes: 64 additions & 0 deletions src/components/store/PickupEventPicker/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Typography } from '@/components/common';
import EventCard from '@/components/events/EventCard';
import { PublicEvent } from '@/lib/types/apiResponses';
import ArrowLeft from '@/public/assets/icons/arrow-left.svg';
import ArrowRight from '@/public/assets/icons/arrow-right.svg';
import styles from './style.module.scss';

interface EventPickerProps {
events: PublicEvent[];
eventIndex: number;
setEventIndex: (...args: any[]) => any;
active: boolean;
}

const PickupEventPicker = ({ events, eventIndex, setEventIndex, active }: EventPickerProps) => {
return (
<div className={styles.eventPicker}>
<div className={styles.window}>
{events.length > 0 ? (
<div
className={styles.slider}
style={{ transform: `translateX(${-320 * eventIndex}px)` }}
raymosun marked this conversation as resolved.
Show resolved Hide resolved
>
{events.map(event => (
<EventCard key={event.uuid} event={event} attended={false} />
))}
</div>
) : (
<div className={styles.noEvents}>
<Typography variant="h3/medium" component="span">
No upcoming pickup events. Check back later!
</Typography>
</div>
)}
</div>

{active && (
<div className={styles.eventNavigation}>
<button
type="button"
onClick={() => setEventIndex((i: number) => (i > 0 ? i - 1 : 0))}
aria-label="Previous Event"
disabled={eventIndex <= 0}
>
<ArrowLeft />
</button>
<Typography variant="h5/regular" component="p">{`${eventIndex + 1}/${
events.length
}`}</Typography>
<button
type="button"
onClick={() => setEventIndex((i: number) => Math.min(i + 1, events.length - 1))}
aria-label="Next Event"
disabled={eventIndex >= events.length - 1}
>
<ArrowRight />
</button>
</div>
)}
</div>
);
};

export default PickupEventPicker;
57 changes: 57 additions & 0 deletions src/components/store/PickupEventPicker/style.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.eventPicker {
align-items: center;
display: flex;
flex-direction: column;

.window {
height: 270px;
overflow: hidden;
position: relative;
width: 320px;

.slider {
display: flex;
position: absolute;
transition: transform 0.3s ease-in-out;
}

.noEvents {
align-items: center;
color: var(--theme-text-on-background-3);
display: flex;
height: 100%;
text-align: center;
width: 100%
}
}

.eventNavigation {
align-items: center;
align-self: stretch;
display: flex;
justify-content: space-between;

button {
background-color: var(--theme-surface-1);
border-radius: 0.9375rem;
display: flex;
height: 1.875rem;
margin: 0.5rem 1rem;
padding: 0;
width: 1.875rem;

svg {
color: var(--theme-text-on-background-3);
transition: color 0.25s ease;
}

&:disabled {
cursor: default;

svg {
color: transparent
}
}
}
}
}
13 changes: 13 additions & 0 deletions src/components/store/PickupEventPicker/style.module.scss.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export type Styles = {
eventNavigation: string;
eventPicker: string;
noEvents: string;
slider: string;
window: string;
};

export type ClassNames = keyof Styles;

declare const styles: Styles;

export default styles;
Loading
Loading