Raid Layout page working
This commit is contained in:
68
src/components/classGroup/ClassGroupSelector.tsx
Normal file
68
src/components/classGroup/ClassGroupSelector.tsx
Normal 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}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
41
src/components/classGroup/ClassGroupsByRaidLayoutDisplay.tsx
Normal file
41
src/components/classGroup/ClassGroupsByRaidLayoutDisplay.tsx
Normal 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 &&
|
||||
<> </>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
86
src/components/input/NumberInput.tsx
Normal file
86
src/components/input/NumberInput.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user