|
| 1 | +"use client"; |
| 2 | +import { api } from "~/trpc/react" |
| 3 | +import { BsEyeFill, BsEyeSlashFill, BsCartPlusFill, BsPencilSquare } from "react-icons/bs"; |
| 4 | +import Subtitle from "~/app/_components/subtitle"; |
| 5 | +import AdminViewRow from "~/app/_components/admin/adminViewRow"; |
| 6 | +import type { Prisma, Week } from "@prisma/client"; |
| 7 | + |
| 8 | +type ProblemWithSolvedBy = Prisma.ProblemGetPayload<{ |
| 9 | + include: {solvedBy: true } |
| 10 | +}> |
| 11 | + |
| 12 | +interface AdminViewBlockProps { |
| 13 | + week: Week, |
| 14 | + problems: ProblemWithSolvedBy[], |
| 15 | +}; |
| 16 | + |
| 17 | +const AdminViewBlock = ({week, problems}: AdminViewBlockProps) => { |
| 18 | + const utils = api.useUtils(); |
| 19 | + const changeWeekTitle = api.week.changeWeekTitle.useMutation({ |
| 20 | + onSuccess: async () => { |
| 21 | + await utils.week.invalidate(); |
| 22 | + }, |
| 23 | + onError: () => { |
| 24 | + alert('Error: Could not update week title.'); |
| 25 | + } |
| 26 | + }); |
| 27 | + |
| 28 | + const handleWeekTitleChange = () => { |
| 29 | + const nt = prompt('Enter new title:'); |
| 30 | + if(!nt) |
| 31 | + { |
| 32 | + return; |
| 33 | + } |
| 34 | + changeWeekTitle.mutate({id: week.id || "", title: nt}); |
| 35 | + }; |
| 36 | + |
| 37 | + const setWeekStatus = api.week.setWeekHidden.useMutation({ |
| 38 | + onSuccess: async () => { |
| 39 | + await utils.week.invalidate(); |
| 40 | + }, |
| 41 | + onError: () => { |
| 42 | + alert(`Error: Could not change visibility.`); |
| 43 | + }, |
| 44 | + }); |
| 45 | + |
| 46 | + const createFromSlug = api.problem.createFromSlug.useMutation({ |
| 47 | + onSuccess: async (data) => { |
| 48 | + if(data) { |
| 49 | + await utils.problem.invalidate(); |
| 50 | + } |
| 51 | + else { |
| 52 | + alert('Problem does not exist or could not be found.'); |
| 53 | + } |
| 54 | + }, |
| 55 | + onError: () => { |
| 56 | + alert(`Error: Could not create problem.`); |
| 57 | + }, |
| 58 | + }); |
| 59 | + |
| 60 | + const handleSetWeekStatus = () => { |
| 61 | + setWeekStatus.mutate({id: week.id, isBlocked: !week.isBlocked}); |
| 62 | + }; |
| 63 | + |
| 64 | + const newSlugIn = () => { |
| 65 | + const ns = prompt('Leetcode title slug:'); |
| 66 | + if( !ns ) |
| 67 | + { |
| 68 | + return; |
| 69 | + } |
| 70 | + createFromSlug.mutate({slug: ns, weekId: week.id}); |
| 71 | + }; |
| 72 | + |
| 73 | + problems = problems.filter((p) => p.weekId == week.id); |
| 74 | + |
| 75 | + return ( |
| 76 | + <div> |
| 77 | + <div className="flex items-center gap-3"> |
| 78 | + <button title='Toggle view' onClick={handleSetWeekStatus}> |
| 79 | + { |
| 80 | + week.isBlocked ? |
| 81 | + <BsEyeSlashFill className="fill-neutral-400 hover:fill-accent" /> : |
| 82 | + <BsEyeFill className="fill-neutral-400 hover:fill-accent" /> |
| 83 | + } |
| 84 | + </button> |
| 85 | + <button title='Buy more problems' onClick={newSlugIn}> |
| 86 | + <BsCartPlusFill className="fill-neutral-400 hover:fill-accent"/> |
| 87 | + </button> |
| 88 | + <button title='Change week title' onClick={handleWeekTitleChange}> |
| 89 | + <BsPencilSquare className="fill-neutral-400 hover:fill-accent"/> |
| 90 | + </button> |
| 91 | + <Subtitle label={week.title}/> |
| 92 | + </div> |
| 93 | + <table className="w-full table-fixed"> |
| 94 | + <thead className="border-b border-white text-left font-semibold text-white"> |
| 95 | + <tr> |
| 96 | + <th>Problem</th> |
| 97 | + <th className="text-center">Difficulty</th> |
| 98 | + <th className="text-center">Solved by</th> |
| 99 | + <th className="text-center">😵</th> |
| 100 | + </tr> |
| 101 | + </thead> |
| 102 | + <tbody> |
| 103 | + { |
| 104 | + problems.map((prob) => (<AdminViewRow key={prob.id} problem={prob} solvedBy={prob.solvedBy.length || 0}/>)) |
| 105 | + } |
| 106 | + </tbody> |
| 107 | + </table> |
| 108 | + </div> |
| 109 | + ) |
| 110 | +} |
| 111 | + |
| 112 | + |
| 113 | +export default AdminViewBlock; |
0 commit comments