Merge pull request #1255 from SkyfallWasTaken/main

Add signed-out view to Arcade Shop
This commit is contained in:
Max Wofford 2024-06-23 16:47:03 +00:00 committed by GitHub
commit d85f3f19b6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 181 additions and 82 deletions

View file

@ -1,5 +1,5 @@
import React, { useState, useRef, useEffect } from 'react'
import { Box, Button, Text, Flex, Grid, Card, Link, Close, Divider } from 'theme-ui'
import React from 'react'
import { Button, Text, Flex, Close, Divider } from 'theme-ui'
import Balancer from 'react-wrap-balancer'
import Quantity from './quantity'
/** @jsxImportSource theme-ui */
@ -14,11 +14,11 @@ const Prizes = ({
cost,
polaroidRotation,
ticketRotation,
link,
link = null,
quantity,
onQuantityChange,
index,
hoursBalance,
hoursBalance = null,
stock,
...props
}) => {
@ -26,11 +26,13 @@ const Prizes = ({
/\[(.*?)\]\((.*?)\)/g,
'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'
)
const parsedSubText = subtext?.replace(/\[(.*?)\]\((.*?)\)/g,
'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>')
const parsedFullName = fullName?.replace(" ", "-")
const parsedSubText = subtext?.replace(
/\[(.*?)\]\((.*?)\)/g,
'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'
)
const parsedFullName = fullName?.replace(' ', '-')
return (
<Flex
sx={{
@ -48,23 +50,22 @@ const Prizes = ({
}}
{...props}
>
<Flex sx={{flexDirection: 'column'}}>
<Flex
sx={{
background: '#FFEEC6',
height: '250px',
justifyContent: 'center',
alignItems: 'center'
}}
>
<img
src={img}
sx={{ height: 'auto', maxWidth: '280px', maxHeight: '250px' }}
alt={text}
/>
</Flex>
{stock && stock != null && stock > 0 && stock <= 100 && (
<Flex sx={{ flexDirection: 'column' }}>
<Flex
sx={{
background: '#FFEEC6',
height: '250px',
justifyContent: 'center',
alignItems: 'center'
}}
>
<img
src={img}
sx={{ height: 'auto', maxWidth: '280px', maxHeight: '250px' }}
alt={text}
/>
</Flex>
{stock && stock != null && stock > 0 && stock <= 100 && (
<Text
sx={{
background: '#CC6CE7',
@ -82,61 +83,71 @@ const Prizes = ({
Only {stock} left!
</Text>
)}
<Text
className="slackey"
variant="headline"
sx={{ color: '#FFEEC6', mb: 0 }}
>
{name}
</Text>
<Text variant="subtitle" sx={{ color: '#FFEEC6' }}>
{smallName}
</Text>
<Balancer>
<Text
as="p"
variant="caption"
sx={{ color: '#FFEEC6', mb: 2, overflowWrap: 'break-word' }}
dangerouslySetInnerHTML={{ __html: parsedSubText }}
/>
</Balancer>
className="slackey"
variant="headline"
sx={{ color: '#FFEEC6', mb: 0 }}
>
{name}
</Text>
<Text variant="subtitle" sx={{ color: '#FFEEC6' }}>
{smallName}
</Text>
<Balancer>
<Text
as="p"
variant="caption"
sx={{ color: '#FFEEC6', mb: 2, overflowWrap: 'break-word' }}
dangerouslySetInnerHTML={{ __html: parsedSubText }}
/>
</Balancer>
</Flex>
{link && (
<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>
<Flex>
{// only show the quantity dropdown if you have enough hours to buy at least 2 of the item
hoursBalance / cost < 2 ? (null) : <Quantity numOptions={Math.min(quantity, Math.floor(hoursBalance / cost))} label={text} onQuantityChange={onQuantityChange} index={index} />
}
{
// only show the buy button if you have enough hours to buy at least 1 of the item
hoursBalance / cost < 1 ? (null) :
<Button
sx={{
borderRadius: '5px',
color: '#FFEEC6',
backgroundColor: '#09878b',
width: 'fit-content'
}}
as="a"
href={link}
className="gaegu"
>
Buy
</Button>
}
</Flex>
<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>
{link && (<Flex>
{
// 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}
/>
)
}
{
// 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"
>
Buy
</Button>
)
}
</Flex>
)}
)}
</Flex>
<Text
sx={{
background: '#FF8C37',
@ -231,10 +242,10 @@ const Prizes = ({
/>
<Balancer>
<Text
variant="subtitle" sx={{ color: '#FFEEC6' }}
variant="subtitle"
sx={{ color: '#FFEEC6' }}
dangerouslySetInnerHTML={{ __html: parsedSubText }}
/>
</Balancer>
<Text
variant="subtitle"

View file

@ -44,7 +44,7 @@ export default function ShopComponent({
return `https://forms.hackclub.com/arcade-order?user_id=${userAirtableID}&item_id=${itemID}&quantity=${quantity}`;
}
const includeBuyLink = userAirtableID !== null;
const canPurchaseItems = userAirtableID !== null;
useEffect(() => {
setPRotate(2 + Math.random() * 4) * (Math.random() > 0.5 ? 1 : -1)
setTRotate(5 + Math.random() * 14) * (Math.random() > 0.5 ? 1 : -1)
@ -93,7 +93,7 @@ export default function ShopComponent({
fullName={item['Full Name']}
polaroidRotation={pRotate}
ticketRotation={tRotate}
link={buyLink(item.id)}
link={canPurchaseItems ? buyLink(item.id) : null}
key={item.id}
id={item.id}
onQuantityChange={(id, q) => handleQuantityChange(item.id, q)} // Pass handler to update quantity

88
pages/arcade/shop.js Normal file
View file

@ -0,0 +1,88 @@
import ShopComponent from "../../components/arcade/shop-component"
import { shopParts } from "../api/arcade/shop"
import { Link, Text } from 'theme-ui'
import { Balancer } from "react-wrap-balancer"
import Meta from '@hackclub/meta'
import Head from 'next/head'
/** @jsxImportSource theme-ui */
const styled = `
@import url('https://fonts.googleapis.com/css2?family=Slackey&family=Emblema+One&family=Gaegu&display=swap');
.slackey {
font-family: "Slackey", sans-serif;
}
.gaegu {
font-family: "Gaegu", sans-serif;
}
body {
background-color: #FAEFD6;
}
`
export default function Shop({ availableItems, userAirtableID = null, hoursBalance = 0 }) {
return (
<>
<Meta
as={Head}
title="Arcade Shop"
description="Check out the prizes at the Arcade Shop!"
image="https://cloud-luaw423i2-hack-club-bot.vercel.app/0frame_33__1_.png"
/>
<style>
{`
._title-container {
width: 100%;
}
`}
</style>
<Balancer className="_title-container">
<h1
sx={{
textAlign: 'center',
fontSize: 5,
color: '#FF8C37',
my: 0,
pt: 5,
display: 'block',
width: '100%'
}}
className="slackey"
>
Welcome to the shop
</h1>
</Balancer>
<Text sx={{ display: 'block', textAlign: 'center', color: '#35290F' }} className='gaegu' variant='subtitle' >Like what you see? Check out <Link href="/arcade">the Hack Club Arcade!</Link></Text>
<ShopComponent availableItems={availableItems} />
</>
)
}
export async function getStaticProps() {
const props = {};
await Promise.all([
shopParts().then(items => {
const availableItems = items.filter((item) => item['Enabled']).map(item => ({
'Name': item['Name'] || null,
'Small Name': item['Small Name'] || null,
'Full Name': item['Full Name'] || null,
'Description': item['Description'] || null,
'Fulfillment Description': item['Fulfillment Description'] || null,
'Cost Hours': item['Cost Hours'] || 0,
id: item.id,
'Image URL': item['Image URL'] || null,
'Max Order Quantity': item['Max Order Quantity'] || 1
}))
props.availableItems = availableItems
}),
])
return { props, revalidate: 10 }
}