Raid Layout page working

This commit is contained in:
2025-03-09 12:15:29 -04:00
parent c2f13d9900
commit 8b8538a968
15 changed files with 973 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
import { ClassGroup } from "@/interface/ClassGroup";
import SelectClassGroupModal from "@/ui/classGroup/modal/SelectClassGroupModal";
import { useEffect, useState } from "react";
export default function ClassGroupSelector({
raidGroupId,
selectedClassGroups,
onChange
}:{
raidGroupId: string;
selectedClassGroups: (ClassGroup | null)[];
onChange: (classGroups: (ClassGroup | null)[]) => void;
}){
const [ classGroups, setClassGroups ] = useState(selectedClassGroups);
const [ displaySelectClassGroupModal, setDisplaySelectClassGroupModal ] = useState(false);
const [ selectedCell, setSelectedCell ] = useState(0);
useEffect(() => {
setClassGroups(selectedClassGroups);
}, [selectedClassGroups]);
const updateClassGroups = (classGroup?: ClassGroup | null) => {
const newClassGroups = [...classGroups];
if(classGroup){
newClassGroups[selectedCell] = classGroup;
}
else{
newClassGroups[selectedCell] = null;
}
setClassGroups(newClassGroups);
onChange(newClassGroups);
}
return (
<>
<div
className="grid grid-cols-3 gap-4"
style={{flex: "0 0 33.333333333%"}}
>
{
classGroups.map((classGroup, index) => (
<div
key={`${index}`}
className="cursor-pointer border px-2 py-1"
onClick={() => {
setDisplaySelectClassGroupModal(true);
setSelectedCell(index);
}}
>
{classGroup?.classGroupName ?? "Any"}
</div>
))
}
</div>
<SelectClassGroupModal
display={displaySelectClassGroupModal}
close={() => setDisplaySelectClassGroupModal(false)}
selectedClassGroup={classGroups[selectedCell]}
onChange={updateClassGroups}
raidGroupId={raidGroupId}
/>
</>
);
}

View File

@@ -0,0 +1,41 @@
import { useGetClassGroupsByRaidLayout } from "@/hooks/ClassGroupHooks";
import DangerMessage from "../message/DangerMessage";
export default function ClassGroupsByRaidLayoutDisplay({
raidGroupId,
raidLayoutId
}:{
raidGroupId: string;
raidLayoutId: string;
}){
const classGroupsQuery = useGetClassGroupsByRaidLayout(raidGroupId, raidLayoutId);
if(classGroupsQuery.status === "pending"){
return (<div>Loading...</div>);
}
else if(classGroupsQuery.status === "error"){
return (<DangerMessage>Error: {classGroupsQuery.error.message}</DangerMessage>);
}
else{
return (
<div
className="flex flex-row gap-x-4"
>
{
classGroupsQuery.data.map((classGroup, index) => (
<div
key={classGroup?.classGroupId ?? index}
>
{classGroup?.classGroupName ?? "Any"}
</div>
))
}
{
classGroupsQuery.data.length === 0 &&
<>&nbsp;</>
}
</div>
);
}
}

View File

@@ -0,0 +1,86 @@
import clsx from "clsx";
import { useEffect, useState } from "react";
export default function NumberInput({
id,
name,
label,
defaultValue,
value,
min,
max,
onChange,
disabled
}:{
id: string;
name?: string;
accepted?: boolean;
label?: string;
defaultValue?: number;
value?: number;
min?: number;
max?: number;
onChange?: (value: number) => void;
disabled?: boolean;
}){
const [ inputValue, setInputValue ] = useState(value ?? 1);
const [ minValue, setMinValue ] = useState(min ?? Number.MIN_VALUE);
const [ maxValue, setMaxValue ] = useState(max ?? Number.MAX_VALUE);
const inputId = crypto.randomUUID().replaceAll("-", "");
useEffect(() => {
setMinValue(min ?? Number.MIN_VALUE);
setMaxValue(max ?? Number.MAX_VALUE);
setInputValue(value ?? defaultValue ?? 0);
}, [ id, min, max, defaultValue, value ]);
const changeInput = (value: number) => {
if(value < minValue){
value = maxValue;
}
else if(value > maxValue){
value = minValue;
}
setInputValue(value);
onChange?.(value);
}
return (
<div
className="bg-inherit px-4 rounded-sm w-full md:flex md:justify-center"
>
<div
className="relative bg-inherit w-18"
>
<input
id={`${id}NumberInput${inputId}`}
type="number"
name={name}
className={clsx(
"peer px-2 py-1 w-16 rounded-lg ring-2 ring-gray-500 focus:ring-sky-600 outline-hidden",
)}
onChange={(e) => changeInput(parseInt(e.target.value || "1"))}
value={inputValue}
disabled={disabled}
/>
<label
htmlFor={`${id}NumberInput${inputId}`}
id={`${id}NumberInput${inputId}Label`}
className={clsx(
"absolute cursor-pointer left-0 -top-3 mx-1 px-1",
"bg-white dark:bg-neutral-800 text-sm",
"text-gray-500 peer-focus:text-sky-600"
)}
style={{transitionProperty: "top, font-size, line-height", transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)", transitionDuration: "150ms"}}
>
{label}
</label>
</div>
</div>
);
}