diff --git a/app/admin/review/page.tsx b/app/admin/review/page.tsx
index b73e24a..ad5b201 100644
--- a/app/admin/review/page.tsx
+++ b/app/admin/review/page.tsx
@@ -2,6 +2,7 @@
import { useMutation, useQuery } from "convex/react";
import { Map } from "@/components/Map";
+import { PlayMapButton } from "@/components/PlayMapButton";
import { Button } from "@/components/ui/button";
import {
Card,
@@ -50,6 +51,7 @@ export default function AdminReviewPage() {
>
Reject
+
))}
diff --git a/app/playground/page.tsx b/app/playground/page.tsx
index 7ec09e8..41ece90 100644
--- a/app/playground/page.tsx
+++ b/app/playground/page.tsx
@@ -3,6 +3,7 @@
import * as React from "react";
import { useAction, useMutation, useQuery } from "convex/react";
import { ChevronLeft, UploadIcon } from "lucide-react";
+import { useSearchParams } from "next/navigation";
import { Map } from "@/components/Map";
import { MapStatus } from "@/components/MapStatus";
import { ModelSelector } from "@/components/ModelSelector";
@@ -11,6 +12,7 @@ import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { useToast } from "@/components/ui/use-toast";
import { api } from "@/convex/_generated/api";
+import { Id } from "@/convex/_generated/dataModel";
import { errorMessage } from "@/lib/utils";
import { ZombieSurvival } from "@/simulators/zombie-survival";
@@ -20,6 +22,13 @@ export default function PlaygroundPage() {
const isAdmin = useQuery(api.users.isAdmin);
const submitMap = useMutation(api.maps.submitMap);
const testMap = useAction(api.maps.testMap);
+ const searchParams = useSearchParams();
+ const mapId = searchParams.get("map") as Id<"maps"> | null;
+ const adminMapMaybe = useQuery(
+ api.maps.adminGetMapById,
+ !isAdmin || mapId === null ? "skip" : { mapId },
+ );
+ const adminMap = adminMapMaybe ?? null;
const { toast } = useToast();
const [map, setMap] = React.useState([
[" ", " ", " ", " ", " "],
@@ -97,7 +106,9 @@ export default function PlaygroundPage() {
function handleChangeMap(value: string[][]) {
setMap(value);
setError(null);
- window.localStorage.setItem(STORAGE_MAP_KEY, JSON.stringify(value));
+ if (adminMap === null) {
+ window.localStorage.setItem(STORAGE_MAP_KEY, JSON.stringify(value));
+ }
}
function handleChangeModel(value: string) {
@@ -167,6 +178,12 @@ export default function PlaygroundPage() {
}
}, []);
+ React.useEffect(() => {
+ if (adminMap !== null) {
+ setMap(adminMap.grid);
+ }
+ }, [adminMap]);
+
const visualizing = solution !== null || visualizingUserSolution;
return (
diff --git a/components/PlayMapButton.tsx b/components/PlayMapButton.tsx
new file mode 100644
index 0000000..21ec6a2
--- /dev/null
+++ b/components/PlayMapButton.tsx
@@ -0,0 +1,16 @@
+"use client";
+
+import * as React from "react";
+import { ExternalLinkIcon } from "lucide-react";
+import Link from "next/link";
+import { Button } from "./ui/button";
+
+export function PlayMapButton({ mapId }: { mapId: string }) {
+ return (
+
+ );
+}
diff --git a/convex/maps.ts b/convex/maps.ts
index f824bf4..547d599 100644
--- a/convex/maps.ts
+++ b/convex/maps.ts
@@ -11,7 +11,11 @@ import {
query,
} from "./_generated/server";
import { Prompt } from "./prompts";
-import { adminMutationBuilder, authenticatedMutation } from "./users";
+import {
+ adminMutationBuilder,
+ adminQueryBuilder,
+ authenticatedMutation,
+} from "./users";
const LEVELS = [
{
@@ -263,6 +267,15 @@ export const getMapByLevel = query({
},
});
+export const adminGetMapById = adminQueryBuilder({
+ args: {
+ mapId: v.id("maps"),
+ },
+ handler: async (ctx, args) => {
+ return await ctx.db.get(args.mapId);
+ },
+});
+
export const playMapAction = internalAction({
args: {
gameId: v.id("games"),