Skip to content

Commit

Permalink
1337 code my dude
Browse files Browse the repository at this point in the history
  • Loading branch information
brekk committed Dec 8, 2021
1 parent 2c4a42b commit 6e23d35
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 28 deletions.
21 changes: 21 additions & 0 deletions apiClient/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,27 @@ export async function createUser(
return await res.json()
}

type ChangeOrder = {
email?: string
graffiti?: string
socialChoice?: string
social?: string
countryCode?: string
}

export async function updateUser(id: number, partial: ChangeOrder) {
const body = JSON.stringify(partial)
const res = await fetch(`${API_URL}/user/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${API_KEY}`,
},
body,
})
return await res.json()
}

export async function listLeaderboard({
search,
country_code: countryCode,
Expand Down
124 changes: 98 additions & 26 deletions components/user/Tabs/SettingsContent.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import React from 'react'
import { useState, useCallback } from 'react'
import { useRouter } from 'next/router'

import * as API from 'apiClient'
import { FieldError } from 'components/Form/FieldStatus'
import Loader from 'components/Loader'
import Select from 'components/Form/Select'
import TextField from 'components/Form/TextField'
import Button from 'components/Button'

import { useField } from 'hooks/useForm'
import { FIELDS } from 'pages/signup'

import { scrollUp } from 'utils/scroll'
import { UNSET } from 'utils/forms'
import { encode as btoa } from 'base-64'

import * as API from 'apiClient'

type Props = {
authedUser: API.ApiUserMetadata
}
Expand All @@ -22,40 +32,102 @@ const getSocialChoice = (
}

export default function SettingsContent({ authedUser }: Props) {
const $router = useRouter()
const $email = useField(FIELDS.email)
const $graffiti = useField(FIELDS.graffiti)
const $social = useField(FIELDS.social)
const $country = useField(FIELDS.country)
const [$error, $setError] = useState<string>(UNSET)
const [$loaded, $setLoaded] = useState<boolean>(false)
const testInvalid = useCallback(() => {
const noEmail = !$email?.touched
const noGraffiti = !$graffiti?.touched
const noSocial = !$social?.touched
const noCountry = !$country?.touched
const untouched = noEmail || noGraffiti || noSocial || noCountry
const invalid =
!$email?.valid || !$graffiti?.valid || !$social?.valid || !$country?.valid

if (invalid || untouched) {
if (untouched) {
$setError('Please fill out all fields')
if (noEmail) $email?.setTouched(true)
if (noGraffiti) $graffiti?.setTouched(true)
if (noSocial) $social?.setTouched(true)
if (noCountry) $country?.setTouched(true)
} else {
$setError('Please correct the invalid fields below')
}
scrollUp()
} else {
$setError(UNSET)
}
return invalid || untouched
}, [$email, $graffiti, $social, $country])

const { choice: socialChoice, value: socialValue } =
getSocialChoice(authedUser)
const update = useCallback(async () => {
if (!$email || !$graffiti || !$social || !$country) return
if (testInvalid()) return
const email = $email?.value
const graffiti = $graffiti?.value
const social = $social?.value
const socialChoiceValue = $social?.choice
const country = $country?.value
$setLoaded(false)

const updates = {
email,
graffiti,
[socialChoiceValue]: social,
countryCode: country,
}
// eslint-disable-next-line no-console
console.log({ updates })

const result = await API.updateUser(authedUser.id, updates)

$setLoaded(true)

if ('error' in result) {
const error = '' + result.message
$setError(error)
} else {
$router.push(
`/users/${authedUser.id}?toast=${btoa('User settings updated!')}`,
undefined,
{ shallow: true }
)
scrollUp()
}
}, [$email, $graffiti, $social, $country, authedUser, testInvalid, $router])

return (
<div className="flex">
<div className="flex-initial">
<div className="font-favorit mt-8">User Settings</div>
{$email && (
<TextField {...$email} defaultValue={authedUser.email} disabled />
)}
{$graffiti && (
<TextField
{...$graffiti}
defaultValue={authedUser.graffiti}
disabled
/>
)}
{$social && (
<TextField
{...$social}
choice={socialChoice}
defaultValue={socialValue}
disabled
/>
)}
{$country && (
<Select {...$country} disabled value={authedUser.country_code} />
)}
</div>
{!$loaded ? (
<Loader />
) : (
<div className="flex-initial">
<div className="font-favorit mt-8">User Settings</div>
{$error !== UNSET && <FieldError text={$error} size="text-md" />}
{$email && (
<TextField {...$email} defaultValue={authedUser.email} disabled />
)}
{$graffiti && (
<TextField {...$graffiti} defaultValue={authedUser.graffiti} />
)}
{$social && (
<TextField
{...$social}
choice={socialChoice}
defaultValue={socialValue}
/>
)}
{$country && <Select {...$country} value={authedUser.country_code} />}
<Button onClick={update} />
</div>
)}
</div>
)
}
2 changes: 1 addition & 1 deletion pages/signup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ export default function SignUp({ loginContext }: SignUpProps) {
duration: 8e3,
})

const [$error, $setError] = useState<string>(UNSET)
const $email = useField(FIELDS.email)
const $social = useField(FIELDS.social)
const $graffiti = useField(FIELDS.graffiti)
const $country = useField(FIELDS.country)
const [$error, $setError] = useState<string>(UNSET)
const [$signedUp, $setSignedUp] = useState<boolean>(false)
const [$loaded, $setLoaded] = useState<boolean>(false)
useEffect(() => {
Expand Down
7 changes: 6 additions & 1 deletion pages/users/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { encode as btoa } from 'base-64'
import * as API from 'apiClient'
import { graffitiToColor, numberToOrdinal } from 'utils'
import { LoginAware } from 'hooks/useLogin'
import { useQueriedToast, Toast, Alignment } from 'hooks/useToast'

// The number of events to display in the Recent Activity list.
const EVENTS_LIMIT = 7
Expand Down Expand Up @@ -112,6 +113,10 @@ export default function User({
weeklyMetrics,
metricsConfig,
}: LoginAwareProps) {
const { visible: $visible, message: $toast } = useQueriedToast({
queryString: 'toast',
duration: 8e3,
})
const id = (user && user.id && user.id.toString()) || 'unknown'
// Recent Activity hooks
const { $events, $hasPrevious, $hasNext, fetchPrevious, fetchNext } =
Expand Down Expand Up @@ -248,7 +253,7 @@ export default function User({
)}
</div>
</main>

<Toast message={$toast} visible={$visible} alignment={Alignment.Top} />
<Footer />
</div>
)
Expand Down

0 comments on commit 6e23d35

Please sign in to comment.