mirror of
https://github.com/System-End/site.git
synced 2026-04-19 22:05:11 +00:00
Merge pull request #1270 from DillonB07/SkyfallWasTaken/main
Update shop stock indicator
This commit is contained in:
commit
f50f74ea61
5 changed files with 125 additions and 43 deletions
|
|
@ -20,6 +20,7 @@ const Prizes = ({
|
|||
index,
|
||||
hoursBalance = null,
|
||||
stock,
|
||||
inStock = true,
|
||||
...props
|
||||
}) => {
|
||||
const parsedFulfillmentDesc = fulfillmentDescription?.replace(
|
||||
|
|
@ -36,7 +37,7 @@ const Prizes = ({
|
|||
return (
|
||||
<Flex
|
||||
sx={{
|
||||
background: '#09AFB4',
|
||||
background: inStock ? '#09AFB4' : '#808080',
|
||||
borderRadius: '10px',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-between',
|
||||
|
|
@ -61,11 +62,12 @@ const Prizes = ({
|
|||
>
|
||||
<img
|
||||
src={img}
|
||||
sx={{ height: 'auto', maxWidth: '280px', maxHeight: '250px' }}
|
||||
sx={{ height: 'auto', maxWidth: '280px', maxHeight: '250px', filter: inStock ? 'none' : 'greyscale(1)' }}
|
||||
alt={text}
|
||||
|
||||
/>
|
||||
</Flex>
|
||||
{stock && stock != null && stock > 0 && stock <= 100 && (
|
||||
{inStock && stock != null && stock > 0 && stock <= 100 && (
|
||||
<Text
|
||||
sx={{
|
||||
background: '#CC6CE7',
|
||||
|
|
@ -102,14 +104,15 @@ const Prizes = ({
|
|||
/>
|
||||
</Balancer>
|
||||
</Flex>
|
||||
{inStock && (
|
||||
|
||||
<Flex sx={{ flexDirection: 'column' }}>
|
||||
<Flex sx={{ flexDirection: 'column' }}>
|
||||
<Balancer>
|
||||
<Text
|
||||
as="p"
|
||||
variant="caption"
|
||||
sx={{ color: '#FFEEC6', mt: 0, mb: 2 }}
|
||||
>
|
||||
>
|
||||
<em>You can order up to {quantity} of these</em>
|
||||
</Text>
|
||||
</Balancer>
|
||||
|
|
@ -119,10 +122,10 @@ const Prizes = ({
|
|||
// only show the quantity dropdown if you have enough hours to buy at least 2 of the item
|
||||
(hoursBalance ? hoursBalance / cost < 2 : null) ? null : (
|
||||
<Quantity
|
||||
numOptions={Math.min(quantity, Math.floor(hoursBalance / cost))}
|
||||
label={text}
|
||||
onQuantityChange={onQuantityChange}
|
||||
index={index}
|
||||
numOptions={Math.min(quantity, Math.floor(hoursBalance / cost))}
|
||||
label={text}
|
||||
onQuantityChange={onQuantityChange}
|
||||
index={index}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
@ -130,15 +133,15 @@ const Prizes = ({
|
|||
// only show the buy button if you have enough hours to buy at least 1 of the item
|
||||
(hoursBalance ? hoursBalance / cost < 1 : null) ? null : (
|
||||
<Button
|
||||
sx={{
|
||||
borderRadius: '5px',
|
||||
color: '#FFEEC6',
|
||||
backgroundColor: '#09878b',
|
||||
width: 'fit-content'
|
||||
}}
|
||||
as="a"
|
||||
href={link}
|
||||
className="gaegu"
|
||||
sx={{
|
||||
borderRadius: '5px',
|
||||
color: '#FFEEC6',
|
||||
backgroundColor: '#09878b',
|
||||
width: 'fit-content'
|
||||
}}
|
||||
as="a"
|
||||
href={link}
|
||||
className="gaegu"
|
||||
>
|
||||
Buy
|
||||
</Button>
|
||||
|
|
@ -147,6 +150,7 @@ const Prizes = ({
|
|||
</Flex>
|
||||
)}
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
<Text
|
||||
sx={{
|
||||
|
|
@ -161,9 +165,11 @@ const Prizes = ({
|
|||
variant="headline"
|
||||
className="gaegu"
|
||||
>
|
||||
{cost} {link ? '🎟️' : cost == 1 ? 'ticket' : 'tickets'}
|
||||
{cost} 🎟️
|
||||
</Text>
|
||||
<Text
|
||||
{inStock && (
|
||||
|
||||
<Text
|
||||
variant="headline"
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
|
|
@ -177,24 +183,25 @@ const Prizes = ({
|
|||
onClick={() => {
|
||||
document.getElementById(`${parsedFullName}-info`).showModal()
|
||||
}}
|
||||
>
|
||||
>
|
||||
📦
|
||||
</Text>
|
||||
)}
|
||||
<dialog
|
||||
id={`${parsedFullName}-info`}
|
||||
sx={{
|
||||
background: '#09AFB4',
|
||||
borderRadius: '10px',
|
||||
flexDirection: 'column',
|
||||
padding: '30px',
|
||||
border: 'none',
|
||||
scrollbarWidth: 'none',
|
||||
textAlign: 'center',
|
||||
maxWidth: '400px',
|
||||
'@media (max-width: 400px)': {
|
||||
maxWidth: '300px'
|
||||
}
|
||||
}}
|
||||
id={`${parsedFullName}-info`}
|
||||
sx={{
|
||||
background: '#09AFB4',
|
||||
borderRadius: '10px',
|
||||
flexDirection: 'column',
|
||||
padding: '30px',
|
||||
border: 'none',
|
||||
scrollbarWidth: 'none',
|
||||
textAlign: 'center',
|
||||
maxWidth: '400px',
|
||||
'@media (max-width: 400px)': {
|
||||
maxWidth: '300px'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Close
|
||||
sx={{
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ export default function ShopComponent({
|
|||
setTRotate(5 + Math.random() * 14) * (Math.random() > 0.5 ? 1 : -1)
|
||||
}, []);
|
||||
|
||||
|
||||
const inStockItems = availableItems.filter(item => item['Stock'] === null || item['Stock'] > 0 );
|
||||
const outOfStockItems = availableItems.filter(item => item['Stock'] !== null && item['Stock'] <= 0);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Text
|
||||
|
|
@ -79,7 +83,7 @@ export default function ShopComponent({
|
|||
textDecoration: 'italic'
|
||||
}}
|
||||
>
|
||||
{availableItems
|
||||
{inStockItems
|
||||
.sort((a, b) => a['Cost Hours'] - b['Cost Hours'])
|
||||
.map((item) => (
|
||||
<Prizes
|
||||
|
|
@ -99,6 +103,44 @@ export default function ShopComponent({
|
|||
onQuantityChange={(id, q) => handleQuantityChange(item.id, q)} // Pass handler to update quantity
|
||||
hoursBalance={hoursBalance}
|
||||
stock={item['Stock']}
|
||||
inStock={true}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
<Text sx={{ display: 'block', textAlign: 'center', color: '#35290F' }} className='gaegu' variant='headline' >Out of stock items</Text>
|
||||
<Grid
|
||||
sx={{
|
||||
pt: '50px',
|
||||
pb: '150px',
|
||||
gridTemplateColumns: ['1fr', '1fr', '1fr 1fr', '1fr 1fr 1fr'],
|
||||
gap: '50px',
|
||||
maxWidth: '1000px',
|
||||
width: '80vw',
|
||||
margin: 'auto',
|
||||
textDecoration: 'italic'
|
||||
}}
|
||||
>
|
||||
{outOfStockItems
|
||||
.sort((a, b) => a['Cost Hours'] - b['Cost Hours'])
|
||||
.map((item) => (
|
||||
<Prizes
|
||||
img={item['Image URL']}
|
||||
name={item['Name']}
|
||||
smallName={item['Small Name']}
|
||||
subtext={item['Description']}
|
||||
cost={item['Cost Hours']}
|
||||
quantity={item['Max Order Quantity']}
|
||||
fulfillmentDescription={item['Fulfillment Description']}
|
||||
fullName={item['Full Name']}
|
||||
polaroidRotation={pRotate}
|
||||
ticketRotation={tRotate}
|
||||
link={canPurchaseItems ? buyLink(item.id) : null}
|
||||
key={item.id}
|
||||
id={item.id}
|
||||
onQuantityChange={(id, q) => handleQuantityChange(item.id, q)} // Pass handler to update quantity
|
||||
hoursBalance={hoursBalance}
|
||||
stock={item['Stock']}
|
||||
inStock={false}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,46 @@
|
|||
import AirtablePlus from "airtable-plus"
|
||||
|
||||
export const shopParts = async () => {
|
||||
const airtable = new AirtablePlus({
|
||||
const baseID = "app4kCWulfB02bV8Q"
|
||||
const shopItemsTable = new AirtablePlus({
|
||||
apiKey: process.env.AIRTABLE_API_KEY,
|
||||
baseID: "app4kCWulfB02bV8Q",
|
||||
baseID,
|
||||
tableName: "Shop Items"
|
||||
})
|
||||
const ordersTable = new AirtablePlus({
|
||||
apiKey: process.env.AIRTABLE_API_KEY,
|
||||
baseID,
|
||||
tableName: "Orders"
|
||||
})
|
||||
|
||||
const records = await airtable.read()
|
||||
return records.map(record => ({id: record.id, ...record.fields}))
|
||||
const records = await shopItemsTable.read()
|
||||
const newRecordsPromise = records.map(async record => {
|
||||
const fields = record.fields;
|
||||
let stock = fields["Stock"]
|
||||
|
||||
if (stock && fields["Orders"]) {
|
||||
const orderIds = fields["Orders"]
|
||||
const ordersFilter = orderIds.map(id => `RECORD_ID() = "${id}"`).join(", ")
|
||||
const data = await ordersTable.read({
|
||||
filterByFormula: `
|
||||
AND(
|
||||
OR(${ordersFilter}),
|
||||
OR(
|
||||
{Status} = "Fulfilled",
|
||||
{Status} = "Awaiting Fulfillment"
|
||||
)
|
||||
)`
|
||||
})
|
||||
|
||||
stock -= data.length;
|
||||
}
|
||||
return { id: record.id, ...record.fields, "Stock": (stock == null)? null : (stock >= 0 ? stock : 0) }
|
||||
})
|
||||
|
||||
|
||||
const newRecords = await Promise.all(newRecordsPromise)
|
||||
|
||||
return newRecords
|
||||
}
|
||||
|
||||
export default async function handler(req, res) {
|
||||
|
|
@ -21,8 +53,9 @@ export default async function handler(req, res) {
|
|||
description: record['Description'],
|
||||
hours: record['Cost Hours'],
|
||||
imageURL: record['Image URL'],
|
||||
stock: record['Stock'],
|
||||
}
|
||||
})
|
||||
|
||||
res.json(filteredData)
|
||||
return res.json(filteredData)
|
||||
}
|
||||
|
|
@ -88,7 +88,7 @@ export async function getStaticProps({params}) {
|
|||
id: item.id,
|
||||
'Image URL': item['Image URL'] || null,
|
||||
'Max Order Quantity': item['Max Order Quantity'] || 1,
|
||||
Stock: item['Stock'] || null
|
||||
Stock: item['Stock'] >= 0 ? item['Stock'] : null
|
||||
}))
|
||||
props.availableItems = availableItems
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ export async function getStaticProps() {
|
|||
id: item.id,
|
||||
'Image URL': item['Image URL'] || null,
|
||||
'Max Order Quantity': item['Max Order Quantity'] || 1,
|
||||
Stock: item['Stock'] || null
|
||||
Stock: item['Stock'] >= 0 ? item['Stock'] : null
|
||||
}))
|
||||
props.availableItems = availableItems
|
||||
}),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue