mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-09 04:02:40 -05:00
These changes are not too scientific, can't reproduce this locally. Just trying something that seems like a reasonable bet.
149 lines
3.6 KiB
TypeScript
149 lines
3.6 KiB
TypeScript
import * as React from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import type { z } from "zod";
|
|
import { UserSearch } from "~/components/elements/UserSearch";
|
|
import { FormMessage } from "~/components/FormMessage";
|
|
import { useUser } from "~/features/auth/core/user";
|
|
import { SCRIM } from "~/features/scrims/scrims-constants";
|
|
import {
|
|
FormFieldWrapper,
|
|
useTranslatedTexts,
|
|
} from "~/form/fields/FormFieldWrapper";
|
|
import { errorMessageId } from "~/form/utils";
|
|
import { nullFilledArray } from "~/utils/arrays";
|
|
import type { CommonUser } from "~/utils/kysely.server";
|
|
import type { fromSchema } from "../scrims-schemas";
|
|
|
|
type FromValue = z.infer<typeof fromSchema>;
|
|
|
|
interface WithFormFieldProps {
|
|
usersTeams: Array<{
|
|
id: number;
|
|
name: string;
|
|
members: Array<CommonUser>;
|
|
}>;
|
|
name: string;
|
|
value: unknown;
|
|
onChange: (value: unknown) => void;
|
|
error: string | undefined;
|
|
}
|
|
|
|
export function WithFormField({
|
|
usersTeams,
|
|
name,
|
|
value,
|
|
onChange,
|
|
error,
|
|
}: WithFormFieldProps) {
|
|
const { t } = useTranslation(["scrims"]);
|
|
const user = useUser();
|
|
const id = React.useId();
|
|
const { translatedError } = useTranslatedTexts({ error });
|
|
|
|
const fromValue = value as FromValue | null;
|
|
|
|
const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
|
if (e.target.value === "PICKUP") {
|
|
onChange({
|
|
mode: "PICKUP",
|
|
users: nullFilledArray(SCRIM.MAX_PICKUP_SIZE_EXCLUDING_OWNER),
|
|
});
|
|
return;
|
|
}
|
|
|
|
onChange({ teamId: Number(e.target.value), mode: "TEAM" });
|
|
};
|
|
|
|
const handleUserChange = React.useCallback(
|
|
(selectedUser: { id: number } | null, index: number) => {
|
|
if (!fromValue || fromValue.mode !== "PICKUP") return;
|
|
|
|
onChange({
|
|
mode: "PICKUP",
|
|
users: fromValue.users.map((u, j) =>
|
|
j === index ? selectedUser?.id : u,
|
|
),
|
|
});
|
|
},
|
|
[fromValue, onChange],
|
|
);
|
|
|
|
const selectValue = fromValue?.mode === "TEAM" ? fromValue.teamId : "PICKUP";
|
|
|
|
return (
|
|
<FormFieldWrapper
|
|
id={id}
|
|
name={name}
|
|
label={t("scrims:forms.with.title")}
|
|
error={fromValue?.mode === "TEAM" ? error : undefined}
|
|
>
|
|
<select id={id} value={selectValue} onChange={handleSelectChange}>
|
|
{usersTeams.map((team) => (
|
|
<option key={team.id} value={team.id}>
|
|
{team.name}
|
|
</option>
|
|
))}
|
|
<option value="PICKUP">{t("scrims:forms.with.pick-up")}</option>
|
|
</select>
|
|
{fromValue?.mode === "PICKUP" ? (
|
|
<div className="stack md mt-4">
|
|
<UserSearch
|
|
initialUserId={user!.id}
|
|
isDisabled
|
|
label={t("scrims:forms.with.user", { nth: 1 })}
|
|
/>
|
|
{fromValue.users.map((userId, i) => (
|
|
<PickupUserSearch
|
|
key={i}
|
|
index={i}
|
|
initialUserId={userId}
|
|
isRequired={i < 3}
|
|
label={t("scrims:forms.with.user", { nth: i + 2 })}
|
|
onUserChange={handleUserChange}
|
|
/>
|
|
))}
|
|
{translatedError ? (
|
|
<FormMessage type="error" id={errorMessageId(name)}>
|
|
{translatedError}
|
|
</FormMessage>
|
|
) : (
|
|
<FormMessage type="info">
|
|
{t("scrims:forms.with.explanation")}
|
|
</FormMessage>
|
|
)}
|
|
</div>
|
|
) : null}
|
|
</FormFieldWrapper>
|
|
);
|
|
}
|
|
|
|
function PickupUserSearch({
|
|
index,
|
|
initialUserId,
|
|
isRequired,
|
|
label,
|
|
onUserChange,
|
|
}: {
|
|
index: number;
|
|
initialUserId: number | null | undefined;
|
|
isRequired: boolean;
|
|
label: string;
|
|
onUserChange: (selectedUser: { id: number } | null, index: number) => void;
|
|
}) {
|
|
const handleChange = React.useCallback(
|
|
(selectedUser: { id: number } | null) => {
|
|
onUserChange(selectedUser, index);
|
|
},
|
|
[index, onUserChange],
|
|
);
|
|
|
|
return (
|
|
<UserSearch
|
|
initialUserId={initialUserId ?? undefined}
|
|
onChange={handleChange}
|
|
isRequired={isRequired}
|
|
label={label}
|
|
/>
|
|
);
|
|
}
|