Skip to content

Commit

Permalink
Merge pull request #72 from Ashutoshbind15/main
Browse files Browse the repository at this point in the history
Add map review for admins and some admin helpers
  • Loading branch information
webdevcody authored Oct 18, 2024
2 parents a2b3b2d + e83e040 commit 4ab3a51
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 9 deletions.
6 changes: 6 additions & 0 deletions app/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default function Header() {
const { signOut } = useAuthActions();
const { isAuthenticated } = useConvexAuth();
const flags = useQuery(api.flags.getFlags);
const isAdminQuery = useQuery(api.users.isAdmin);

return (
<header className="flex justify-between items-center py-4 px-6 shadow-sm border-b">
Expand All @@ -49,6 +50,11 @@ export default function Header() {
<Button variant="ghost">Submit Map</Button>
</Link>
)}
{isAdminQuery && (
<Link href="/maps/review">
<Button variant="ghost">Review Maps</Button>
</Link>
)}
{flags?.showTestPage && (
<Link href="/test">
<Button variant="ghost">Test</Button>
Expand Down
55 changes: 55 additions & 0 deletions app/maps/review/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"use client";

import { Map } from "@/components/Map";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { api } from "@/convex/_generated/api";
import { useMutation, useQuery } from "convex/react";

const Page = () => {
const isAdmin = useQuery(api.users.isAdmin);
const maps = useQuery(api.maps.getMaps, { isReviewed: false });
const adminApprovalMutation = useMutation(api.maps.approveMap);

if (isAdmin == true) {
return (
<div className="py-6">
<h1 className="text-center font-semibold mb-4">Review Maps</h1>
<div className="flex items-center justify-around">
{maps?.map((map) => (
<Card key={map._id}>
<CardHeader>
<CardTitle> </CardTitle>
</CardHeader>

<CardContent>
<Map map={map.grid} />
</CardContent>

<CardFooter className="flex justify-center">
<Button
variant="outline"
onClick={async () => {
await adminApprovalMutation({ mapId: map._id });
}}
>
Approve
</Button>
</CardFooter>
</Card>
))}
</div>
</div>
);
}

return <div>Not an admin</div>;
};

export default Page;
2 changes: 1 addition & 1 deletion app/play/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { useEffect, useState } from "react";
import { Skeleton } from "@/components/ui/skeleton";

export default function PlayPage() {
const maps = useQuery(api.maps.getMaps);
const maps = useQuery(api.maps.getMaps, {});
const userMapResults = useQuery(api.playerresults.getUserMapStatus);
const mapCountResults = useQuery(api.playerresults.getMapsWins);

Expand Down
73 changes: 67 additions & 6 deletions convex/maps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,10 @@ export const addMap = mutation({
throw new Error("User not authenticated");
}

const maps = await ctx.db.query("maps").collect();

await ctx.db.insert("maps", {
level: maps.length + 1,
grid: args.grid,
submittedBy: userId,
isReviewed: false,
});
},
});
Expand All @@ -82,6 +80,7 @@ export const seedMaps = internalMutation({
ctx.db.insert("maps", {
level: idx + 1,
grid: map.grid,
isReviewed: true,
});
}
}),
Expand All @@ -90,9 +89,71 @@ export const seedMaps = internalMutation({
});

export const getMaps = query({
args: {},
handler: async (ctx) => {
return await ctx.db.query("maps").withIndex("by_level").collect();
args: {
isReviewed: v.optional(v.boolean()),
},
handler: async (ctx, args) => {
if (args.isReviewed !== undefined) {
// todo: take this out into a helper function
// if a manual query is made, check if the user is an admin

const userId = await getAuthUserId(ctx);
if (userId === null) {
return null;
}

const admins = await ctx.db.query("admins").collect();
const isAdmin = admins.some((admin) => admin.userId === userId);

if (isAdmin) {
return await ctx.db
.query("maps")
.filter((q) => q.eq(q.field("isReviewed"), args.isReviewed))
.collect();
} else {
return null;
}
}

return await ctx.db
.query("maps")
.filter((q) => q.eq(q.field("isReviewed"), true))
.collect();
},
});

export const approveMap = mutation({
args: {
mapId: v.id("maps"),
},
handler: async (ctx, args) => {
// todo: take this out into a helper function

const userId = await getAuthUserId(ctx);
if (userId === null) {
throw new Error("Unauthorized");
}

const admins = await ctx.db.query("admins").collect();
const isAdmin = admins.some((admin) => admin.userId === userId);

if (!isAdmin) {
throw new Error("Unauthorized");
} else {
const maps = await ctx.db.query("maps").collect();

const lastLevel = maps.reduce((acc, map) => {
if (map.level) {
return Math.max(acc, map.level);
}
return acc;
}, 0);

await ctx.db.patch(args.mapId, {
isReviewed: true,
level: lastLevel + 1,
});
}
},
});

Expand Down
7 changes: 6 additions & 1 deletion convex/results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,12 @@ export const updateResult = internalMutation({

const maps = await ctx.db.query("maps").collect();

const lastLevel = maps.reduce((max, map) => Math.max(max, map.level), 0);
const lastLevel = maps.reduce((acc, map) => {
if (map.level) {
return Math.max(acc, map.level);
}
return acc;
}, 0);

await ctx.runMutation(internal.leaderboard.updateRankings, {
modelId: game.modelId,
Expand Down
6 changes: 5 additions & 1 deletion convex/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ export default defineSchema({
status: v.union(v.literal("in_progress"), v.literal("completed")),
}),
maps: defineTable({
level: v.number(),
level: v.optional(v.number()),
grid: v.array(v.array(v.string())),
submittedBy: v.optional(v.id("users")),
isReviewed: v.boolean(),
}).index("by_level", ["level"]),
scores: defineTable({
modelId: v.string(),
Expand Down Expand Up @@ -61,4 +62,7 @@ export default defineSchema({
attempts: v.array(v.id("attempts")),
hasWon: v.boolean(),
}).index("by_mapId_userId", ["mapId", "userId"]),
admins: defineTable({
userId: v.id("users"),
}),
});
13 changes: 13 additions & 0 deletions convex/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,16 @@ export const getUserOrNull = query({
return await ctx.db.get(userId);
},
});

export const isAdmin = query({
handler: async (ctx) => {
const userId = await getAuthUserId(ctx);
if (userId === null) {
return false;
}

const admins = await ctx.db.query("admins").collect();

return admins.some((admin) => admin.userId === userId);
},
});

0 comments on commit 4ab3a51

Please sign in to comment.