Skip to content

Commit

Permalink
refactor: add axios-case-converter to remove case inconsistency
Browse files Browse the repository at this point in the history
  • Loading branch information
bohdancho committed Dec 22, 2023
1 parent f42a2c5 commit 9a1705f
Show file tree
Hide file tree
Showing 22 changed files with 71 additions and 71 deletions.
Binary file modified bun.lockb
Binary file not shown.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@typescript-eslint/parser": "^6.7.3",
"axios": "^1.5.1",
"axios-auth-refresh": "^3.3.6",
"axios-case-converter": "^1.1.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"jwt-decode": "^3.1.2",
Expand Down
2 changes: 1 addition & 1 deletion src/api/accounts/useUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { axiosClient } from '../axios'
import useSWRImmutable from 'swr/immutable'

const API_ROUTE = 'accounts/current_user/'
export type UserData = { username: string; auth_completed: boolean }
type UserData = { username: string; authCompleted: boolean }

export function useUser() {
const { data, error, isLoading } = useSWRImmutable<{ data: UserData }>(API_ROUTE, axiosClient.get)
Expand Down
2 changes: 2 additions & 0 deletions src/api/axios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import axios from 'axios'
import createAuthRefreshInterceptor from 'axios-auth-refresh'
import { refreshAccessToken } from './accounts'
import { createAuthorizedRequestInterceptor } from './authTokens'
import applyCaseMiddleware from 'axios-case-converter'

const axiosParams = {
baseURL: `/api`,
Expand All @@ -12,6 +13,7 @@ const axiosParams = {
}
const _axiosClient = axios.create(axiosParams)

applyCaseMiddleware(_axiosClient)
createAuthorizedRequestInterceptor(_axiosClient)
createAuthRefreshInterceptor(_axiosClient, () => refreshAccessToken(axiosParams))

Expand Down
14 changes: 7 additions & 7 deletions src/api/contests/solveContest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import { Discipline, Scramble } from '@/types'
import useSWRImmutable from 'swr/immutable'

export type SolveContestStateResponse = {
current_solve: {
can_change_to_extra: boolean
currentSolve: {
canChangeToExtra: boolean
scramble: Scramble
solve: SolveNotInited | SolveSuccessful | SolveDnf
}
submitted_solves: Array<(SolveSuccessful | SolveDnf) & { scramble: Scramble }>
submittedSolves: Array<(SolveSuccessful | SolveDnf) & { scramble: Scramble }>
}

type SolveNotInited = null
type SolveSuccessful = { id: number; time_ms: number; dnf: false }
type SolveDnf = { id: number; time_ms: null; dnf: true }
type SolveSuccessful = { id: number; timeMs: number; dnf: false }
type SolveDnf = { id: number; timeMs: null; dnf: true }

const API_ROUTE = '/contests/solve-contest/'
export function useSolveContestState(contestNumber: number, discipline: Discipline) {
Expand All @@ -29,9 +29,9 @@ export async function postSolveResult(
contestNumber: number,
discipline: Discipline,
scrambleId: number,
payload: { reconstruction: string; time_ms: number } | { dnf: true },
payload: { reconstruction: string; timeMs: number } | { dnf: true },
) {
const { data } = await axiosClient.post<{ solve_id: number }>(
const { data } = await axiosClient.post<{ solveId: number }>(
`${API_ROUTE}${contestNumber}/${discipline}/?scramble_id=${scrambleId}`,
payload,
)
Expand Down
6 changes: 3 additions & 3 deletions src/api/contests/useContestResults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { axiosClient } from '../axios'

export type ContestResultsResponse = Array<{
id: number
avg_ms: number | null // TODO fix to camelCase
avgMs: number | null // TODO fix to camelCase
discipline: { name: Discipline }
user: { username: string }
solve_set: Array<{
solveSet: Array<{
id: number
time_ms: number | null // TODO fix to camelCase
timeMs: number | null // TODO fix to camelCase
dnf: boolean
scramble: Pick<Scramble, 'position'>
state: 'submitted' | 'changed_to_extra'
Expand Down
8 changes: 4 additions & 4 deletions src/api/contests/useDashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ import { axiosClient } from '../axios'
import { Discipline } from '@/types'

export type DashboardResponse = {
best_solves: Array<{
bestSolves: Array<{
id: number
contest_number: number // TODO fix to camelCase
time_ms: number // TODO fix to camelCase
contestNumber: number
timeMs: number
user: { username: string }
discipline: { name: Discipline }
}>
contests: Array<{
id: number
contest_number: number // TODO fix to camelCase
contestNumber: number
start: string
end: string | null
ongoing: boolean
Expand Down
4 changes: 2 additions & 2 deletions src/api/contests/useLeaderboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { Discipline, Scramble } from '@/types'

export type LeaderboardResponse = Array<{
id: number
time_ms: number
timeMs: number
created: string
scramble: Pick<Scramble, 'id' | 'scramble'>
discipline: { name: Discipline }
user: { id: number; username: string }
contest: { contest_number: number }
contest: { contestNumber: number }
}>

const API_ROUTE = 'contests/leaderboard/'
Expand Down
2 changes: 1 addition & 1 deletion src/api/contests/useSolveReconstruction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type SolveReconstructionResponse = {
id: number
reconstruction: string
scramble: Pick<Scramble, 'position' | 'scramble'>
contest_number: number
contestNumber: number
discipline: { name: Discipline }
user: { username: string }
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/PickUsernameModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export function PickUsernameModal() {
const { userData } = useUser()

useEffect(() => {
if (userData && !userData.auth_completed) {
if (userData && !userData.authCompleted) {
setIsVisible(true)
}
}, [userData])
Expand Down
6 changes: 3 additions & 3 deletions src/components/ui/ReconstructTimeButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { cn, formatTimeResult } from '@/utils'
import { ButtonHTMLAttributes } from 'react'

type SolveTimeButtonProps = {
time_ms: number
timeMs: number
} & ButtonHTMLAttributes<HTMLButtonElement>
export function ReconstructTimeButton({ time_ms, className, ...props }: SolveTimeButtonProps) {
export function ReconstructTimeButton({ timeMs: timeMs, className, ...props }: SolveTimeButtonProps) {
return (
<button {...props} type='button' className={cn('btn-action w-[70px] text-center md:w-[80px]', className)}>
{formatTimeResult(time_ms)}
{formatTimeResult(timeMs)}
</button>
)
}
6 changes: 3 additions & 3 deletions src/integrations/cube/Cube.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { RefObject, useEffect, useState } from 'react'

export type CubeSolveResult =
| { reconstruction: string; time_ms: number; dnf: false }
| { reconstruction: null; time_ms: null; dnf: true } // TODO fix to camelCase
| { reconstruction: string; timeMs: number; dnf: false }
| { reconstruction: null; timeMs: null; dnf: true } // TODO fix to camelCase
export type CubeSolveFinishCallback = (result: CubeSolveResult) => void
export type CubeTimeStartCallback = () => void

Expand Down Expand Up @@ -51,7 +51,7 @@ const startSolveOnLoad = (() => {

if (event.data.event === 'solveFinish') {
const { reconstruction, timeMs }: { reconstruction: string; timeMs: number } = event.data.payload
savedOnSolveFinish?.({ reconstruction, time_ms: timeMs, dnf: false })
savedOnSolveFinish?.({ reconstruction, timeMs, dnf: false })
savedOnSolveFinish = undefined
}
})
Expand Down
4 changes: 2 additions & 2 deletions src/integrations/cube/CubeProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function CubeProvider({ children }: CubeProviderProps) {
)

useConditionalBeforeUnload(solveState ? solveState.wasTimeStarted : false, () =>
handleSolveFinish({ dnf: true, time_ms: null, reconstruction: null }),
handleSolveFinish({ dnf: true, timeMs: null, reconstruction: null }),
)

const handleOverlayClick = (event: React.MouseEvent) => {
Expand All @@ -58,7 +58,7 @@ export function CubeProvider({ children }: CubeProviderProps) {

const handleAbortConfirm = useCallback(() => {
setIsAbortPromptVisible(false)
handleSolveFinish({ time_ms: null, dnf: true, reconstruction: null })
handleSolveFinish({ timeMs: null, dnf: true, reconstruction: null })
}, [handleSolveFinish])

const handleAbortCancel = useCallback(() => {
Expand Down
6 changes: 3 additions & 3 deletions src/integrations/reconstructor/ReconstructorProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,18 @@ export function ReconstructorProvider({ children }: ReconstructorProviderProps)
}

function parseReconstructionResponse({
contest_number,
contestNumber: contestNumber,
discipline,
id,
scramble,
user: { username },
reconstruction: solution,
}: SolveReconstructionResponse) {
const link = `${window.location.origin}/contest/${contest_number}/${discipline.name}?solveId=${id}`
const link = `${window.location.origin}/contest/${contestNumber}/${discipline.name}?solveId=${id}`
const reconstruction = { scramble: scramble.scramble, solution } satisfies Reconstruction
const metadata = {
link,
contestNumber: contest_number,
contestNumber,
username,
scramblePosition: scramble.position,
formattedTime: formatTimeResult(parseTimeMsFromSolution(reconstruction.solution)),
Expand Down
24 changes: 12 additions & 12 deletions src/pages/contest/components/PublishedSession.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import { useNavigateToSolve } from '../ContestDiscipline'
type PublishedSessionProps = ContestResultsResponse[number]
export function PublishedSession({
user: { username },
avg_ms,
solve_set,
avgMs,
solveSet,
isOwnSession,
placeNumber,
}: PublishedSessionProps & { isOwnSession?: boolean; placeNumber: number }) {
const { navigateToSolve } = useNavigateToSolve()

const submittedSolves = useMemo(() => solve_set.filter(({ state }) => state === 'submitted'), [solve_set])
const submittedSolves = useMemo(() => solveSet.filter(({ state }) => state === 'submitted'), [solveSet])
const { bestId, worstId } = useMemo(() => getBestAndWorstIds(submittedSolves), [submittedSolves])

return (
Expand All @@ -27,12 +27,12 @@ export function PublishedSession({
<span className='overflow-x-hidden text-ellipsis'>{username}</span>
</div>
<span className='border-[#A0A0A0]/50 pr-[9px] text-right md:mr-5 md:border-r-[1px] md:pr-5 lg:mr-[30px] lg:pr-[30px]'>
<span className='inline-block text-center text-[#79A1EF]'>{avg_ms ? formatTimeResult(avg_ms) : 'DNF'}</span>
<span className='inline-block text-center text-[#79A1EF]'>{avgMs ? formatTimeResult(avgMs) : 'DNF'}</span>
</span>
<div className='col-span-3 flex justify-between md:col-span-1 md:-ml-[5px] md:gap-1 lg:gap-2'>
{submittedSolves.map(({ id, time_ms, scramble: { position } }) => {
{submittedSolves.map(({ id, timeMs, scramble: { position } }) => {
const isExtra = position.startsWith('E')
return time_ms ? (
return timeMs ? (
<ReconstructTimeButton
className={cn(
{
Expand All @@ -45,7 +45,7 @@ export function PublishedSession({
title={isExtra ? `Extra ${position[1]}` : undefined}
onClick={() => navigateToSolve(id)}
key={id}
time_ms={time_ms}
timeMs={timeMs}
/>
) : (
<span key={id} className='flex w-[80px] items-center justify-center text-[#E45B5B]'>
Expand All @@ -58,16 +58,16 @@ export function PublishedSession({
)
}

function getBestAndWorstIds(submittedSolves: ContestResultsResponse[number]['solve_set']) {
function getBestAndWorstIds(submittedSolves: ContestResultsResponse[number]['solveSet']) {
const dnfSolve = submittedSolves.find(({ dnf }) => dnf)
const timeArr = submittedSolves
.filter(({ time_ms, dnf }) => typeof time_ms === 'number' && !dnf)
.map(({ time_ms }) => time_ms as number)
.filter(({ timeMs, dnf }) => typeof timeMs === 'number' && !dnf)
.map(({ timeMs }) => timeMs as number)

const bestTime = Math.min(...timeArr)
const bestId = submittedSolves.find(({ time_ms }) => time_ms === bestTime)?.id
const bestId = submittedSolves.find(({ timeMs }) => timeMs === bestTime)?.id
const worstTime = Math.max(...timeArr)
const worstId = dnfSolve?.id ?? submittedSolves.find(({ time_ms }) => time_ms === worstTime)?.id
const worstId = dnfSolve?.id ?? submittedSolves.find(({ timeMs }) => timeMs === worstTime)?.id

return { bestId, worstId }
}
16 changes: 8 additions & 8 deletions src/pages/contest/components/SolveContest/SolveContest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,24 @@ export function SolveContest({ contestNumber, discipline }: SolveContestProps) {
const { userData } = useUser()
const { data: state, mutate: mutateState } = useSolveContestState(contestNumber, discipline)

if (userData && !userData.auth_completed) {
if (userData && !userData.authCompleted) {
return <InfoBox>Please finish registration first</InfoBox>
}
if (!state) {
return <InfoBox>loading...</InfoBox>
}
const { current_solve, submitted_solves } = state
const { currentSolve, submittedSolves } = state

async function solveFinishHandler(result: CubeSolveResult) {
if (!state) return
const { solve_id: newSolveId } = await postSolveResult(contestNumber, discipline, current_solve.scramble.id, result)
const { solveId: newSolveId } = await postSolveResult(contestNumber, discipline, currentSolve.scramble.id, result)

mutateState(
{
data: {
...state,
current_solve: {
...current_solve,
currentSolve: {
...currentSolve,
solve: { id: newSolveId, ...result },
},
},
Expand All @@ -53,18 +53,18 @@ export function SolveContest({ contestNumber, discipline }: SolveContestProps) {

return (
<div className='flex flex-col gap-3 md:gap-6'>
{submitted_solves.map((solve) => (
{submittedSolves.map((solve) => (
<SubmittedSolve className='px-3 py-2 md:h-[54px] md:px-4 md:py-0 lg:px-7' key={solve.id} {...solve} />
))}

<CurrentSolve
className='px-3 py-2 md:h-[54px] md:py-0 md:pl-4 md:pr-3 lg:pl-7 lg:pr-4'
{...current_solve}
{...currentSolve}
onSolveFinish={solveFinishHandler}
onExtra={takeExtraHandler}
onSubmit={submitHandler}
/>
{submitted_solves.length === 0 ? (
{submittedSolves.length === 0 ? (
<InfoBox>You can't see results of an ongoing round until you solve all scrambles or the round ends</InfoBox>
) : null}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useNavigateToSolve } from '@/pages/contest'
import { useCube } from '@/integrations/cube'
import { CubeSolveResult } from '@/integrations/cube'

type CurrentSolveProps = SolveContestStateResponse['current_solve'] & {
type CurrentSolveProps = SolveContestStateResponse['currentSolve'] & {
className?: string
onSolveFinish: (result: CubeSolveResult) => void
onSubmit: () => void
Expand All @@ -14,7 +14,7 @@ type CurrentSolveProps = SolveContestStateResponse['current_solve'] & {
export function CurrentSolve({
scramble,
solve,
can_change_to_extra,
canChangeToExtra,
onSolveFinish,
onSubmit,
onExtra,
Expand All @@ -39,7 +39,7 @@ export function CurrentSolve({
{!isFinished ? (
<span className='block w-[80px] text-center'>??:??.??</span>
) : isSuccessful ? (
<ReconstructTimeButton onClick={() => navigateToSolve(solve.id)} time_ms={solve.time_ms} />
<ReconstructTimeButton onClick={() => navigateToSolve(solve.id)} timeMs={solve.timeMs} />
) : (
<span className='block w-[80px] pl-2'>DNF</span>
)}
Expand All @@ -50,7 +50,7 @@ export function CurrentSolve({
<div className='justify-center max-md:col-start-3 max-md:row-start-1 max-md:row-end-3 max-md:flex max-md:h-full max-md:flex-col'>
{isFinished ? (
<div className='flex gap-[17px]'>
{can_change_to_extra ? (
{canChangeToExtra ? (
<button onClick={onExtra} className='w-[82px] rounded-md bg-[#9B2527] py-2'>
extra
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { ReconstructTimeButton } from '@/components'
import { useNavigateToSolve } from '@/pages/contest'
import { cn } from '@/utils'

type SubmittedSolveProps = SolveContestStateResponse['submitted_solves'][number] & {
type SubmittedSolveProps = SolveContestStateResponse['submittedSolves'][number] & {
className?: string
}
export function SubmittedSolve({ className, time_ms, scramble, id }: SubmittedSolveProps) {
export function SubmittedSolve({ className, timeMs, scramble, id }: SubmittedSolveProps) {
const { navigateToSolve } = useNavigateToSolve()
const isSuccessfull = time_ms !== null
const isSuccessfull = timeMs !== null

return (
<div
Expand All @@ -20,7 +20,7 @@ export function SubmittedSolve({ className, time_ms, scramble, id }: SubmittedSo
<span className='md:mr-[10px] md:text-right'>{scramble.position}.</span>
<span className='md:mr-[20px] md:border-r-[1px] md:border-[#A0A0A0]/50 md:pr-[20px]'>
{isSuccessfull ? (
<ReconstructTimeButton time_ms={time_ms} onClick={() => navigateToSolve(id)} />
<ReconstructTimeButton timeMs={timeMs} onClick={() => navigateToSolve(id)} />
) : (
<span className='block w-[80px] pl-2'>DNF</span>
)}
Expand Down
Loading

0 comments on commit 9a1705f

Please sign in to comment.