-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(fe): show alert modal after editting problem score (#2209)
* feat(fe): add score caution modal * chore(fe): apply belonged contest queries update * feat(fe): create set to zero button * feat(fe): create revert score button * feat(fe): apply update contest problems score * feat(fe): remove create problem alert dialog * feat(fe): remove create contest alert dialog * chore(fe): resolve reviews
- Loading branch information
Showing
11 changed files
with
483 additions
and
155 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
91
apps/frontend/app/admin/problem/[problemId]/edit/_components/BelongedContestTable.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
'use client' | ||
|
||
import DataTable from '@/app/admin/_components/table/DataTable' | ||
import DataTableFallback from '@/app/admin/_components/table/DataTableFallback' | ||
import DataTableRoot from '@/app/admin/_components/table/DataTableRoot' | ||
import { GET_BELONGED_CONTESTS } from '@/graphql/contest/queries' | ||
import { useSuspenseQuery } from '@apollo/client' | ||
import { useEffect, useState } from 'react' | ||
import { columns, type BelongedContest } from './BelongedContestTableColumns' | ||
import RevertScoreButton from './RevertScoreButton' | ||
import SetToZeroButton from './SetToZeroButton' | ||
|
||
export function BelongedContestTable({ | ||
problemId, | ||
onSetToZero, | ||
onRevertScore | ||
}: { | ||
problemId: number | ||
onSetToZero: (data: number[]) => void | ||
onRevertScore: () => void | ||
}) { | ||
const [contests, setContests] = useState<BelongedContest[]>([]) | ||
|
||
const { data } = useSuspenseQuery(GET_BELONGED_CONTESTS, { | ||
variables: { | ||
problemId | ||
} | ||
}) | ||
|
||
useEffect(() => { | ||
if (data) { | ||
const mappedData: BelongedContest[] = [ | ||
...data.getContestsByProblemId.upcoming.map((contest) => ({ | ||
id: Number(contest.id), | ||
title: contest.title, | ||
state: 'Upcoming', | ||
problemScore: contest.problemScore, | ||
totalScore: contest.totalScore, | ||
isSetToZero: false | ||
})), | ||
...data.getContestsByProblemId.ongoing.map((contest) => ({ | ||
id: Number(contest.id), | ||
title: contest.title, | ||
state: 'Ongoing', | ||
problemScore: contest.problemScore, | ||
totalScore: contest.totalScore, | ||
isSetToZero: false | ||
})), | ||
...data.getContestsByProblemId.finished.map((contest) => ({ | ||
id: Number(contest.id), | ||
title: contest.title, | ||
state: 'Finished', | ||
problemScore: contest.problemScore, | ||
totalScore: contest.totalScore, | ||
isSetToZero: false | ||
})) | ||
] | ||
setContests(mappedData) | ||
} | ||
}, [data]) | ||
|
||
return ( | ||
<DataTableRoot data={contests} columns={columns}> | ||
<DataTable /> | ||
<SetToZeroButton | ||
onSetToZero={(contestsToSetZero) => { | ||
setContests((contests) => | ||
contests.map((contest) => | ||
contestsToSetZero.includes(contest.id) | ||
? { ...contest, isSetToZero: true } | ||
: contest | ||
) | ||
) | ||
onSetToZero(contestsToSetZero) | ||
}} | ||
/> | ||
<RevertScoreButton | ||
onRevertScore={() => { | ||
setContests( | ||
contests.map((contest) => ({ ...contest, isSetToZero: false })) | ||
) | ||
onRevertScore() | ||
}} | ||
/> | ||
</DataTableRoot> | ||
) | ||
} | ||
|
||
export function BelongedContestTableFallback() { | ||
return <DataTableFallback withSearchBar={false} columns={columns} /> | ||
} |
99 changes: 99 additions & 0 deletions
99
apps/frontend/app/admin/problem/[problemId]/edit/_components/BelongedContestTableColumns.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
'use client' | ||
|
||
import DataTableColumnHeader from '@/app/admin/_components/table/DataTableColumnHeader' | ||
import { Checkbox } from '@/components/shadcn/checkbox' | ||
import { cn } from '@/lib/utils' | ||
import type { ColumnDef } from '@tanstack/react-table' | ||
|
||
export interface BelongedContest { | ||
id: number | ||
title: string | ||
state: string | ||
problemScore: number | ||
totalScore: number | ||
isSetToZero: boolean | ||
} | ||
|
||
export const columns: ColumnDef<BelongedContest>[] = [ | ||
{ | ||
id: 'select', | ||
header: ({ table }) => ( | ||
<Checkbox | ||
onClick={(e) => e.stopPropagation()} | ||
checked={table.getIsAllPageRowsSelected()} | ||
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)} | ||
aria-label="Select all" | ||
className="translate-y-[2px] bg-white" | ||
/> | ||
), | ||
cell: ({ row }) => ( | ||
<Checkbox | ||
onClick={(e) => e.stopPropagation()} | ||
checked={row.getIsSelected()} | ||
onCheckedChange={(value) => row.toggleSelected(!!value)} | ||
aria-label="Select row" | ||
className="translate-y-[2px] bg-white" | ||
/> | ||
), | ||
enableSorting: false, | ||
enableHiding: false | ||
}, | ||
{ | ||
accessorKey: 'title', | ||
header: ({ column }) => ( | ||
<DataTableColumnHeader column={column} title="Contest Title" /> | ||
), | ||
cell: ({ row }) => ( | ||
<p className="max-w-[700px] overflow-hidden text-ellipsis whitespace-nowrap text-left font-medium"> | ||
{row.getValue('title')} | ||
</p> | ||
), | ||
enableSorting: false, | ||
enableHiding: false | ||
}, | ||
{ | ||
accessorKey: 'state', | ||
header: () => ( | ||
<p className="text-center font-mono text-sm font-medium">State</p> | ||
), | ||
cell: ({ row }) => ( | ||
<p className="text-center font-normal">{row.getValue('state')}</p> | ||
) | ||
}, | ||
{ | ||
accessorKey: 'problemScore', | ||
header: () => ( | ||
<p className="text-center font-mono text-sm font-medium">Problem Score</p> | ||
), | ||
cell: ({ row }) => ( | ||
<p | ||
className={cn( | ||
'text-center font-normal', | ||
row.original.isSetToZero && 'text-primary' | ||
)} | ||
> | ||
{row.original.isSetToZero ? '0' : row.getValue('problemScore')} | ||
</p> | ||
) | ||
}, | ||
{ | ||
accessorKey: 'totalScore', | ||
header: () => ( | ||
<p className="text-center font-mono text-sm font-medium">Total Score</p> | ||
), | ||
cell: ({ row }) => ( | ||
<p | ||
className={cn( | ||
'text-center font-normal', | ||
row.original.isSetToZero && 'text-primary' | ||
)} | ||
> | ||
{row.original.isSetToZero ? '0' : row.getValue('problemScore')}/ | ||
{row.original.isSetToZero | ||
? Number(row.getValue('totalScore')) - | ||
Number(row.getValue('problemScore')) | ||
: row.getValue('totalScore')} | ||
</p> | ||
) | ||
} | ||
] |
32 changes: 32 additions & 0 deletions
32
apps/frontend/app/admin/problem/[problemId]/edit/_components/RevertScoreButton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { useDataTable } from '@/app/admin/_components/table/context' | ||
import { Button } from '@/components/shadcn/button' | ||
import type { BelongedContest } from './BelongedContestTableColumns' | ||
|
||
interface SetToZeroButtonProps { | ||
onRevertScore: () => void | ||
} | ||
|
||
export default function RevertScoreButton({ | ||
onRevertScore | ||
}: SetToZeroButtonProps) { | ||
const { table } = useDataTable<BelongedContest>() | ||
|
||
const selectedContests = table.getSelectedRowModel().rows | ||
|
||
return ( | ||
<> | ||
{selectedContests.length > 0 && ( | ||
<Button | ||
onClick={() => { | ||
table.resetRowSelection() | ||
onRevertScore() | ||
}} | ||
variant="filter" | ||
className="ml-3" | ||
> | ||
Revert Score | ||
</Button> | ||
)} | ||
</> | ||
) | ||
} |
Oops, something went wrong.