Skip to content

Commit

Permalink
Admin store item and collection management (#124)
Browse files Browse the repository at this point in the history
* Rough outline of SizeSelector

* Created a file to represent the item page

* Edited config file to be nested under "Store" header

* Size Toggle V1, Styling Only

Size toggle styling implemented

On selected text goes blue

On hover border goes blue

* State of SizeToggle now passed up to the item page

Made a temporary edit to the title of the page that displays the current size selected as testing

* Updated styling of size selector to match Figma

https://www.figma.com/file/cgbeW6vrqgxW0i1vpbUn1C/Store-(Redesign-2023)?type=design&node-id=2028-16321&mode=design&t=nbIfHwdT8aeDdhsd-0

* Part 1 of AddCartButton styling

Got text color to change depending on if in stock or not (is currently hard coded, not synced to backend)

Button animation still exists, need to make it flat

Text changes based on if in stock or not

Still need to do styling for button if item is out of stock

* Out of Stock Button and "Please Select Size"

Updated button theming to change based on if in stock or not

A size is now not selected by default, message requesting user to select a size added.

* Fixed issue with AddCartButton props breaking

From last update, where made it possible for size to be undefined.

* Began formatting for item header and item page

* Store Component now linked to API, price added

Price now displays. No discount display yet

TODO: Modify size buttons to be dynamic depending on how many options there are.

* Size Selection Buttons Now Dynamically Generated

* Buy ability based on lifetime/monthly limits, added item picture

TODO: Might be a good idea to change the "add to cart" message depending on if you have reached lifetime limits

* Cleaned up some old comments

* Moved Navbar to top of page

* Resolved linting error (unused var)

* Update src/styles/pages/store/item.module.scss

Co-authored-by: Faris Ashai <[email protected]>

* Update src/styles/pages/store/item.module.scss

Co-authored-by: Faris Ashai <[email protected]>

* Update src/styles/pages/store/item.module.scss

Co-authored-by: Faris Ashai <[email protected]>

* Update src/lib/api/StoreAPI.ts

Co-authored-by: Faris Ashai <[email protected]>

* Resolved merge error with calendar

And API type error

* Minor package changes

* Fix package.json

* Make compatible with multiple store gallery images

No carousel yet, uses default photo as photo shown

* Moved item header to be above sizing buttons

* Centered the body of the item page.

* Fixed merge error by updating name of file path

* Update src/styles/pages/store/item.module.scss

Co-authored-by: Faris Ashai <[email protected]>

* Update src/pages/store/item/[uuid].tsx

Co-authored-by: Sean <[email protected]>

* Update src/pages/store/item/[uuid].tsx

Co-authored-by: Sean <[email protected]>

* Update src/pages/store/item/[uuid].tsx

Co-authored-by: Sean <[email protected]>

* Update .vscode/settings.json

Co-authored-by: Faris Ashai <[email protected]>

* Update src/styles/pages/store/item.module.scss

Co-authored-by: Faris Ashai <[email protected]>

* Update src/components/store/AddCartButton/index.tsx

Co-authored-by: Faris Ashai <[email protected]>

* Addressed PR comments, Add to Cart button behavior edit

Updated Add to Cart button to also say "remove from cart"

Quantity Selector now disappear if you can't add to cart or size is not selected.

Add to Cart button disappear if a size is not selected.

Removed various comments

Removed useEffect

* Updated diamond component in Item Header

Diamond component displays cost

* Add To Cart button disappears when UserPurchaseLimit reached

* AddCartButton maxCanBuy saftey checks and styling

Added an option for 0 quantity if user has reached purchase limit

* Renamed styling files, AddToCart Button Behavior Change

Add To Cart button now displays when user has reached purchase limit, but is greyed out and cannot be clicked

* Added border back to disabled AddToCart Button

* Added border back to cart button, cleaned up unused vars

* Hid toggle when maxCanBuy = 1

Also lifted quantity of items up to uuid.tsx

* Removed unused comments

* Removed eslint disable lines

* Removed title attribute from buy button

#94 (comment)

* Removed trailing spaces from button text

#94 (comment)

* Hide price when size is not selected

Also removed mounted checks from `SizeSelector`

importing only types from UUID

* Added back other types accidently deleted from last commit

* Delete blue-diamond.svg

* Basic mobile formatting implemented

Still need to sync it with Figma

* Add edit buttons to store page

* Copy event edit page for store item edit page

* item details form

* Set item collection, preview store as member

* Add create buttons to storefront page

* Collection edit page

* API for creating/deleting store item photos/options

* Fix making changes to collections

* Fixed image clipping issue, reduced image gap on mobile

* Removed vertical scrollbar from mobile view

Used scrollbar hide, may need to look into why is actually overflowing later.

* Removed unnecessary CSS

* item options table

* Add multiple options

* fix type error

* Rename store/collections.module.scss to be consistent with other changes in PR

* Fix duplicate `getCollection` definitions

* Make API .d.ts files normal TypeScript files so it actually reports errors

* Upload photos

* Enforce limits

* PermissionService.allUserTypes is no longer a function

* Make edit and create button components and add them to collection page

* Add edit button to item page, show 404 when item/collection DNE

* Show hidden/archived icons

* Make the edit forms look nicer

* Fixed a linting error with the options dropdown

* Shrunk some UI items for mobile version of site

* Set upper limit on quantity of items can buy

* Deleted unnecessary comments

* Update src/components/store/SizeSelector/index.tsx

Co-authored-by: Sean <[email protected]>

* Fixed various linting errors, removed comments

Also updated gaps

* Decreased font size of dropdown text

* fix item cards' edit button

* Overengineered Draggable component

* drag handle design adjustments

* Some input validation

* Save preview as member option in cookie rather than URL

* My JavaScript is too future for Vercel 😔

* Make design look more acceptable on mobile

* New styling changes to adjust spacing

IN PROGRESS

* Locked width of description and fixed line breaks

Also adjusted title/paragraph sizes and weight

Also centered the webpage

* Title now properly wraps with very long titles

Also deleted some unused styling classes

Also adjusted one column width threshold.

* Made padding a little bigger for right column

Also fixed bug where price would cause an extra gap in object header, even when not visible

* Removed in stock / out of stock messages

Also bumped the "add to cart" button up a little bit

* @media now uses the media breakpoint variables

* Renamed variables and adjusted white space behavior

* Update src/components/store/AddCartButton/index.tsx

Co-authored-by: Faris Ashai <[email protected]>

* Update src/components/store/AddCartButton/style.module.scss

Co-authored-by: Sean <[email protected]>

* Fixed some gap inconsistencies

* Update settings.json

* Update settings.json

* Made SizeSelector title change based on metadata

* Fixed bug where add to cart button no longer worked

Was due to comparison for current option not being properly updated with new system (needed a `.value`)

Also made image container always square.

* Condensed imports in `uuid`, removed "Remove from Cart" text

Note that clicking "Add to Cart" again removes item from cart.

* Fuss with store component imports to avoid dependency cycles

* Flatten profile/edit.module.scss

* Replace all `condition && jsx` with `condition ? jsx : null` to conform with style guide

Per #124 (comment)

* Update placeholder text for name; fix going back after creating item going to create page

The collection/item title placeholder text has been made more relevant

After creating an item, it redirects you to the edit page so when you click back, it doesn't go to an empty create item form anymore. Same with collection

* Restructure details form component files

* Quantity -> Quantity available in table, redirect to public page after creating item/collection, fix admin buttons on mobile

* Before attempting to remove currOption

I think I can collapse it into selectedOption

* rename cookie type PREVIEW -> USER_PREVIEW_ENABLED

* Made the "please select an option" text to show key value

So instead of always saying "size" or "option" it will show "color" if the options are colors

* Add discount and out of stock to item card

* canManageStore -> storeAdminVisible

* Update src/components/store/AddCartButton/style.module.scss

Co-authored-by: Sean <[email protected]>

* Refactor store api stuff to manager, options table to component

* Changed AddCartButton to CartOptionsGroup

Also various small bug fixes from PR

- Made the options `input` tags not selectable

- Removed unecessary CSS

* Removed unnecessary properties, simplified CSS

* Refactor all managers to use `reportError`

* Change Manage Store Merchandise button to View Merch Store when preview is checked

* Debugging cookie desync issue

* how about collection page

* Change service worker strategy to network first

This fixes the admin preview store as member cookie being out of sync, but it also means slower page loads for the user

* Require that monthlyLimit <= lifetimeLimit

* Minor code quality adjustments from store item PR

* Fix store slider scrollbars in Chrome 121+

* Only disable caching for store pages

Also change `withAccessType` to use an options object so it's more clear what the parameters do

* Handle showing error toasts in Cropper

* export scss variable to default collection color

* minor nitfixes

* Move `reportError` out of admin store manager to make error handling more clear

* make spacing of code look more consistent

* Revert back to global NetworkFirst, remove `disableCaching`

---------

Co-authored-by: Andrew Smithwick <[email protected]>
Co-authored-by: Faris Ashai <[email protected]>
Co-authored-by: Alex Zhang <[email protected]>
  • Loading branch information
4 people authored Feb 20, 2024
1 parent 29ac7c4 commit 6621e75
Show file tree
Hide file tree
Showing 93 changed files with 2,435 additions and 328 deletions.
18 changes: 18 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
const env = process.env.NODE_ENV;
const isDevelopment = env !== 'production';

const runtimeCaching = require('next-pwa/cache');

// By default, next-pwa serves from the cache while updating the cache with a
// network request. This results in faster page loads, but the data will be
// stale, most notable when checking into an event (membership points will be
// out of date) or enabling "Preview store as member" on the admin page. Note
// that this only applies to static routes (e.g. /store but not /u/[uuid]).
//
// This makes it fetch data from the server (then falling back to the cache if
// the user is offline). This will result in slower page loads, but the data
// will always be up-to-date.
// https://github.com/vercel/next.js/discussions/52024#discussioncomment-6325542
const nextData = runtimeCaching.find(entry => entry.options.cacheName === 'next-data');
if (nextData) {
nextData.handler = 'NetworkFirst';
}

const withPWA = require('next-pwa')({
dest: 'public',
runtimeCaching,
register: true,
skipWaiting: true,
disable: isDevelopment,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
}
}

input,
input:not([type='checkbox']),
textarea,
select {
border: 1px solid #bbb;
Expand Down
64 changes: 27 additions & 37 deletions src/components/admin/event/EventDetailsForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import EventDetailsFormItem from '@/components/admin/event/EventDetailsFormItem';
import DetailsFormItem from '@/components/admin/DetailsFormItem';
import NotionAutofill from '@/components/admin/event/NotionAutofill';
import { Button, Cropper } from '@/components/common';
import { config, showToast } from '@/lib';
Expand All @@ -9,7 +9,7 @@ import { FillInLater } from '@/lib/types';
import { Event } from '@/lib/types/apiRequests';
import { NotionEventDetails, NotionEventPreview, PublicEvent } from '@/lib/types/apiResponses';
import { CookieType } from '@/lib/types/enums';
import { getMessagesFromError, useObjectUrl } from '@/lib/utils';
import { reportError, useObjectUrl } from '@/lib/utils';
import { DateTime } from 'luxon';
import Image from 'next/image';
import Link from 'next/link';
Expand Down Expand Up @@ -117,7 +117,7 @@ const EventDetailsForm = (props: IProps) => {
},
onFailCallback: error => {
setLoading(false);
showToast('Unable to create event', getMessagesFromError(error).join());
reportError('Unable to create event', error);
},
});
};
Expand Down Expand Up @@ -152,7 +152,7 @@ const EventDetailsForm = (props: IProps) => {
},
onFailCallback: error => {
setLoading(false);
showToast('Unable to create event', getMessagesFromError(error).join());
reportError('Unable to create event', error);
},
});
};
Expand Down Expand Up @@ -183,7 +183,7 @@ const EventDetailsForm = (props: IProps) => {
<h1>{editing ? 'Modify' : 'Create'} Event</h1>
<div className={style.form}>
<label htmlFor="name">Event Name</label>
<EventDetailsFormItem error={errors.title?.message}>
<DetailsFormItem error={errors.title?.message}>
<input
type="text"
id="name"
Expand All @@ -192,10 +192,10 @@ const EventDetailsForm = (props: IProps) => {
required: 'Required',
})}
/>
</EventDetailsFormItem>
</DetailsFormItem>

<label htmlFor="committee">Community</label>
<EventDetailsFormItem error={errors.committee?.message}>
<DetailsFormItem error={errors.committee?.message}>
<select
id="committee"
placeholder="General"
Expand All @@ -209,10 +209,10 @@ const EventDetailsForm = (props: IProps) => {
<option>Hack</option>
<option>Design</option>
</select>
</EventDetailsFormItem>
</DetailsFormItem>

<label htmlFor="location">Location</label>
<EventDetailsFormItem error={errors.location?.message}>
<DetailsFormItem error={errors.location?.message}>
<input
type="text"
id="location"
Expand All @@ -221,72 +221,72 @@ const EventDetailsForm = (props: IProps) => {
required: 'Required',
})}
/>
</EventDetailsFormItem>
</DetailsFormItem>

<label htmlFor="points">Points</label>
<EventDetailsFormItem error={errors.pointValue?.message}>
<DetailsFormItem error={errors.pointValue?.message}>
<input
type="number"
id="points"
{...register('pointValue', {
required: 'Required',
})}
/>
</EventDetailsFormItem>
</DetailsFormItem>

<label htmlFor="start">Starts At</label>
<EventDetailsFormItem error={errors.start?.message}>
<DetailsFormItem error={errors.start?.message}>
<input
type="datetime-local"
id="start"
{...register('start', {
required: 'Required',
})}
/>
</EventDetailsFormItem>
</DetailsFormItem>

<label htmlFor="end">Ends At</label>
<EventDetailsFormItem error={errors.end?.message}>
<DetailsFormItem error={errors.end?.message}>
<input
type="datetime-local"
id="end"
{...register('end', {
required: 'Required',
})}
/>
</EventDetailsFormItem>
</DetailsFormItem>

<label htmlFor="checkin">Check In Code</label>
<EventDetailsFormItem error={errors.attendanceCode?.message}>
<DetailsFormItem error={errors.attendanceCode?.message}>
<input
type="text"
id="checkin"
{...register('attendanceCode', {
required: 'Required',
})}
/>
</EventDetailsFormItem>
</DetailsFormItem>

<label htmlFor="description">Event Link</label>
<EventDetailsFormItem error={errors.eventLink?.message}>
<DetailsFormItem error={errors.eventLink?.message}>
<input type="text" id="eventLink" {...register('eventLink')} />
</EventDetailsFormItem>
</DetailsFormItem>

<label htmlFor="description">Description</label>
<EventDetailsFormItem error={errors.description?.message}>
<DetailsFormItem error={errors.description?.message}>
<textarea
id="description"
{...register('description', {
required: 'Required',
})}
/>
</EventDetailsFormItem>
</DetailsFormItem>

<label htmlFor="cover">Cover Image</label>
<EventDetailsFormItem>
{eventCover && (
<DetailsFormItem>
{eventCover ? (
<Image src={eventCover} alt="Selected cover image" width={480} height={270} />
)}
) : null}
<input
type="file"
id="cover"
Expand All @@ -299,7 +299,7 @@ const EventDetailsForm = (props: IProps) => {
}
}}
/>
</EventDetailsFormItem>
</DetailsFormItem>
<Cropper
file={selectedCover}
aspectRatio={1920 / 1080}
Expand All @@ -313,17 +313,7 @@ const EventDetailsForm = (props: IProps) => {
);
setSelectedCover(null);
}}
onClose={reason => {
setSelectedCover(null);
if (reason === 'cannot-compress') {
showToast(
'Your image has too much detail and cannot be compressed.',
'Try shrinking your image.'
);
} else if (reason !== null) {
showToast('This image format is not supported.');
}
}}
onClose={() => setSelectedCover(null)}
/>
</div>

Expand Down
5 changes: 3 additions & 2 deletions src/components/admin/event/ManageEventCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { GoogleCalendarButton } from '@/components/events/CalendarButtons';
import { config, showToast } from '@/lib';
import { AdminEventManager } from '@/lib/managers';
import { PublicEvent } from '@/lib/types/apiResponses';
import { reportError } from '@/lib/utils';
import Image from 'next/image';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
Expand Down Expand Up @@ -31,7 +32,7 @@ const ManageEventCard = ({ event }: IProps) => {
showToast('Successfully created event!', 'Check your server to confirm all details');
},
onFailCallback: e => {
showToast('Error while generating Discord Event!', e);
reportError('Error while generating Discord Event!', e);
},
});
};
Expand Down Expand Up @@ -62,7 +63,7 @@ const ManageEventCard = ({ event }: IProps) => {
},
onFailCallback: e => {
setAcmurlLoading(false);
showToast('Error while generating ACMURL!', e);
reportError('Error while generating ACMURL!', e);
},
});
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/admin/event/NotionAutofill/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Button } from '@/components/common';
import { showToast } from '@/lib';
import { AdminEventManager } from '@/lib/managers';
import type { NotionEventDetails, NotionEventPreview } from '@/lib/types/apiResponses';
import { reportError } from '@/lib/utils';
import { DateTime } from 'luxon';
import { useEffect, useState } from 'react';
import style from './style.module.scss';
Expand All @@ -28,7 +29,7 @@ const NotionAutofill = ({ setFields, loading, upcomingEvents }: IProps) => {
showToast(`Filled out fields for event: ${data.title}!`);
},
onFailCallback: err => {
showToast('Notion API Error', err);
reportError('Notion API Error', err);
},
});

Expand Down
2 changes: 1 addition & 1 deletion src/components/admin/event/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { default as EventDetailsFormItem } from '../DetailsFormItem';
export { default as EventDetailsForm } from './EventDetailsForm';
export { default as EventDetailsFormItem } from './EventDetailsFormItem';
export { default as ManageEventCard } from './ManageEventCard';
export { default as NotionAutofill } from './NotionAutofill';
Loading

0 comments on commit 6621e75

Please sign in to comment.