diff --git a/components/admin/stygian-editor.tsx b/components/admin/stygian-editor.tsx
index 3bb1422..9deace3 100644
--- a/components/admin/stygian-editor.tsx
+++ b/components/admin/stygian-editor.tsx
@@ -4,6 +4,7 @@ import Image from "@/components/ui/resilient-image";
import Link from "next/link";
import { useEffect, useMemo, useRef, useState, type ReactNode } from "react";
import {
+ CopyIcon,
GripVerticalIcon,
PlusIcon,
Trash2Icon,
@@ -742,10 +743,12 @@ function VisualRecommendationGrid({
function SortableTeam({
id,
position,
+ onCopy,
children,
}: {
id: string;
position: number;
+ onCopy: () => void;
children: ReactNode;
}) {
const {
@@ -765,17 +768,29 @@ function SortableTeam({
Team {position + 1}
-
+
+
+
+
{children}
@@ -934,6 +949,17 @@ function BossRecommendationEditor({
key={team.id}
id={team.id}
position={teamIndex}
+ onCopy={() =>
+ setTeams((current) => {
+ const sourceIndex = current.findIndex((entry) => entry.id === team.id);
+ if (sourceIndex === -1) return current;
+ const source = current[sourceIndex];
+ return current.toSpliced(sourceIndex + 1, 0, {
+ id: crypto.randomUUID(),
+ items: source.items.map((item) => ({ ...item })),
+ });
+ })
+ }
>
setLevel(Number(next) as 105 | 110)}
+ className="grid grid-cols-1"
>
-
+
{stygianLevels.map((entry) => (
Level {entry}
))}
{stygianLevels.map((entry) => (
-
+
setBossPosition(Number(next))}
+ className="row-span-3 grid grid-rows-subgrid"
>
{stygianBossPositions.map((position) => {
@@ -1104,7 +1132,7 @@ export function StygianEditor({
- เลือกระดับบอส
-
- {stygianLevels.map((level) => (
- เลเวล {level}
- ))}
-
+
+
+
เลือกระดับบอส
+
+ {stygianLevels.map((level) => (
+ เลเวล {level}
+ ))}
+
+
{stygianLevels.map((level) => (
-
-
- เลือกบอส
-
- {stygianBossPositions.map((position) => {
- const boss = schedule.bosses.find((candidate) => candidate.level === level && candidate.position === position);
- const label = boss?.name ?? `Boss ${position + 1}`;
- const positionLabel = stygianBossPositionLabels[position];
- return
-
- ;
- })}
-
- {stygianBossPositions.map((position) => )}
-
+
+
+
+
เลือกบอส
+
+ {stygianBossPositions.map((position) => {
+ const boss = schedule.bosses.find((candidate) => candidate.level === level && candidate.position === position);
+ const label = boss?.name ?? `Boss ${position + 1}`;
+ const positionLabel = stygianBossPositionLabels[position];
+ return
+
+ ;
+ })}
+
+
+ {stygianBossPositions.map((position) => )}
+
))}
-
+
);
}
diff --git a/components/stygian/stygian-navigation.tsx b/components/stygian/stygian-navigation.tsx
new file mode 100644
index 0000000..079b814
--- /dev/null
+++ b/components/stygian/stygian-navigation.tsx
@@ -0,0 +1,37 @@
+"use client";
+
+import { createContext, useContext, useState, type ReactNode } from "react";
+
+import { Tabs } from "@/components/ui/tabs";
+
+const BossSelectionContext = createContext<{
+ position: string;
+ onPositionChange: (position: string) => void;
+} | null>(null);
+
+export function StygianNavigation({ children }: { children: ReactNode }) {
+ const [position, onPositionChange] = useState("0");
+
+ return (
+
+
+ {children}
+
+
+ );
+}
+
+export function StygianBossTabs({ children }: { children: ReactNode }) {
+ const selection = useContext(BossSelectionContext);
+ if (!selection) throw new Error("StygianBossTabs requires StygianNavigation.");
+
+ return (
+
+ {children}
+
+ );
+}