Files
supabase/apps/www/components/LaunchWeek/12/Ticket/TicketCustomizationForm.tsx
Jonathan Summers-MuirandFrancesco Sansalvadore 1f1f8a5fa4 Feat/whale init (#28243)
* duplicate page

* whale init

* table background

* prepare

* sync undocumented remote schema from master

* revert remote schema sync

* add lw12 tickets migration file

* ticket init

* set up lw12 ticket layout

* finish ticket layout and customization form

* lw12 ticket og

* ticket styling

* code highlight border

* launch week migrations

* local dev progress

* keep local gh config

* comment section

* comment section

* comment out username.tsx

* remove lw/ticekts temp

* update copy

* fix migration view

* redirect to try

* use misc

* lw12 og

* share

* share correct

* env var

* username page

* update example env

* push new db schema

* trigger deploy

* update ticket og

* ticket themes

* bypass browser

* change env var name

* fix

* fix

* process env

* create client server side

* lw announcements

* promoToast

* animated bg

* update ticket og bg

* minor details

* secret ticket

* social share text

* social share textgst

* flow text

* update og

* update og handler

* Update index.ts

* use functions.invoke and use generic supabase URL

* Update index.ts

* Update handler.tsx

* Update package-lock.json

* Update handler.tsx

* add next api route

* moved to vercel edge function

* set revalidate

* Update route.tsx

* Delete lw-ticket-og.tsx

* Update route.tsx

* Update [username].tsx

* Update [username].tsx

* add more fetches

* Update turbo.json

* ticket themes updated

* copy and layout updated

* Update index.tsx

* Update Ticket.tsx

* Update TicketingFlow.tsx

* update countdown

* updated bg

* small updates

* moat

* Update [username].tsx

* Update 20240723155310_add_lw12_ticketing_schema.sql

* optimistic ticket stuff og generation

* Update index.tsx

* updated layout

* update themes in og

* Update constants.ts

* attr renamed

* Update TicketingFlow.tsx

* Update TicketActions.tsx

* grammar

* moar updates

* Update TicketActions.tsx

* Update TicketActions2.tsx

* Update TicketActions.tsx

* Update Hero.tsx

* Update TicketingFlow.tsx

* remove console logs

---------

Co-authored-by: Francesco Sansalvadore <f.sansalvadore@gmail.com>
2024-08-01 01:59:01 +08:00

176 lines
5.3 KiB
TypeScript

import React, { useEffect, useState } from 'react'
import { Button, Input, cn } from 'ui'
import { Check } from 'lucide-react'
import useConfData from '~/components/LaunchWeek/hooks/use-conf-data'
import { useBreakpoint, useDebounce } from 'common'
import { useKey } from 'react-use'
const TicketCustomizationForm = ({ className }: { className?: string }) => {
const isMobile = useBreakpoint()
const {
supabase,
userData: user,
showCustomizationForm,
setShowCustomizationForm,
} = useConfData()
const defaultFormValues = {
role: user.role,
company: user.company,
location: user.location,
}
const [formData, setFormData] = useState(defaultFormValues)
const [formState, setFormState] = useState<'idle' | 'saved' | 'saving' | 'error'>('idle')
const IS_SAVING = formState === 'saving'
const IS_SAVED = formState === 'saved'
const HAS_ERROR = formState === 'error'
useKey('Escape', () => setShowCustomizationForm && setShowCustomizationForm(false))
const handleInputChange = (name: string, value: string | boolean) => {
setFormData((prev) => ({ ...prev, [name]: value }))
}
const handleFormSubmit = async () => {
setFormState('saving')
const payload = formData
if (supabase) {
await supabase
.from('tickets')
.update(payload)
.eq('launch_week', 'lw12')
.eq('username', user.username)
.then((res) => {
if (res.error) return setFormState('error')
setFormState('saved')
setTimeout(() => {
setFormState('idle')
}, 1200)
})
}
}
const debouncedChangeHandler = useDebounce(handleFormSubmit, 1200)
useEffect(() => {
return () => setShowCustomizationForm && setShowCustomizationForm(false)
}, [])
return (
<form
className={cn(
'w-full rounded-xl bg-alternative border p-4 flex flex-col gap-2 mx-auto transition-all opacity-0 translate-y-full text-foreground-light',
showCustomizationForm && 'opacity-100 translate-y-0 duration-300',
isMobile && 'mt-2',
className
)}
onChange={(e) => {
e.preventDefault()
debouncedChangeHandler()
}}
onSubmit={(e) => {
e.preventDefault()
handleFormSubmit()
}}
>
<Input
size="small"
type="text"
placeholder="role (optional)"
value={formData.role}
onChange={(event) => {
handleInputChange('role', event.target.value)
}}
onFocus={() =>
!showCustomizationForm && setShowCustomizationForm && setShowCustomizationForm(true)
}
inputClassName={cn(IS_SAVING && 'text-foreground-lighter')}
maxLength={25}
icon={
<Check
strokeWidth={2}
className={cn(
'w-3',
!!formData.role ? 'text-brand' : 'text-foreground-lighter',
IS_SAVING && 'text-background-surface-300'
)}
/>
}
/>
<Input
size="small"
type="text"
placeholder="company (optional)"
value={formData.company}
maxLength={25}
onChange={(event) => {
handleInputChange('company', event.target.value)
}}
onFocus={() =>
!showCustomizationForm && setShowCustomizationForm && setShowCustomizationForm(true)
}
inputClassName={cn(IS_SAVING && 'text-foreground-lighter')}
icon={
<Check
strokeWidth={2}
className={cn(
'w-3',
!!formData.company ? 'text-brand' : 'text-foreground-lighter',
IS_SAVING && 'text-background-surface-300'
)}
/>
}
/>
<Input
size="small"
type="text"
placeholder="location (optional)"
value={formData.location}
maxLength={25}
onChange={(event) => {
handleInputChange('location', event.target.value)
}}
onFocus={() =>
!showCustomizationForm && setShowCustomizationForm && setShowCustomizationForm(true)
}
inputClassName={cn(IS_SAVING && 'text-foreground-lighter')}
icon={
<Check
strokeWidth={2}
className={cn(
'w-3',
!!formData.location ? 'text-brand' : 'text-foreground-lighter',
IS_SAVING && 'text-background-surface-300'
)}
/>
}
/>
<div className="flex flex-col lg:flex-row items-center justify-center md:justify-between gap-2 mt-2">
<div className="inline opacity-0 animate-fade-in text-xs text-foreground-light">
{IS_SAVED && (
<span className="inline opacity-0 animate-fade-in text-xs text-foreground-light">
Saved
</span>
)}
{HAS_ERROR && (
<span className="inline opacity-0 animate-fade-in text-xs text-foreground-light">
Something went wrong
</span>
)}
</div>
<Button
type="outline"
size="tiny"
htmlType="submit"
block={isMobile}
onClick={() => setShowCustomizationForm && setShowCustomizationForm(false)}
>
Done
</Button>
</div>
</form>
)
}
export default TicketCustomizationForm