Files
kan/apps/web/src/views/board/components/List.tsx
Henry dd061c6d00 feat: localisation and multi-lang support (#95)
* feat: setup localisation with lingui

* Fix hydration and locale issues

* Add missing translations and tweak selector styling

* Extend language support

* Update lang support

* Extend lang support

* Fix build and add dyanmic imports
2025-06-25 21:30:24 +01:00

136 lines
4.0 KiB
TypeScript

import type { ReactNode } from "react";
import { t } from "@lingui/core/macro";
import { Draggable } from "react-beautiful-dnd";
import { useForm } from "react-hook-form";
import {
HiEllipsisHorizontal,
HiOutlinePlusSmall,
HiOutlineSquaresPlus,
HiOutlineTrash,
} from "react-icons/hi2";
import Dropdown from "~/components/Dropdown";
import { useModal } from "~/providers/modal";
import { api } from "~/utils/api";
interface ListProps {
children: ReactNode;
index: number;
list: List;
setSelectedPublicListId: (publicListId: PublicListId) => void;
}
interface List {
publicId: string;
name: string;
}
interface FormValues {
listPublicId: string;
name: string;
}
type PublicListId = string;
export default function List({
children,
index,
list,
setSelectedPublicListId,
}: ListProps) {
const { openModal } = useModal();
const openNewCardForm = (publicListId: PublicListId) => {
openModal("NEW_CARD");
setSelectedPublicListId(publicListId);
};
const updateList = api.list.update.useMutation();
const { register, handleSubmit } = useForm<FormValues>({
defaultValues: {
listPublicId: list.publicId,
name: list.name,
},
values: {
listPublicId: list.publicId,
name: list.name,
},
});
const onSubmit = (values: FormValues) => {
updateList.mutate({
listPublicId: values.listPublicId,
name: values.name,
});
};
const handleOpenDeleteListConfirmation = () => {
setSelectedPublicListId(list.publicId);
openModal("DELETE_LIST");
};
return (
<Draggable key={list.publicId} draggableId={list.publicId} index={index}>
{(provided) => (
<div
key={list.publicId}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
className="dark-text-dark-1000 mr-5 h-fit min-w-[18rem] max-w-[18rem] rounded-md border border-light-400 bg-light-300 py-2 pl-2 pr-1 text-neutral-900 dark:border-dark-300 dark:bg-dark-100"
>
<div className="mb-2 flex justify-between">
<form
onSubmit={handleSubmit(onSubmit)}
className="w-full focus-visible:outline-none"
>
<input
id="name"
type="text"
{...register("name")}
onBlur={handleSubmit(onSubmit)}
className="w-full border-0 bg-transparent px-4 pt-1 text-sm font-medium text-neutral-900 focus:ring-0 focus-visible:outline-none dark:text-dark-1000"
/>
</form>
<div className="flex items-center">
<button
className="mx-1 inline-flex h-fit items-center rounded-md p-1 px-1 text-sm font-semibold text-dark-50 hover:bg-light-400 dark:hover:bg-dark-200"
onClick={() => openNewCardForm(list.publicId)}
>
<HiOutlinePlusSmall
className="h-5 w-5 text-dark-900"
aria-hidden="true"
/>
</button>
<div className="relative mr-1 inline-block">
<Dropdown
items={[
{
label: t`Add a card`,
action: () => openNewCardForm(list.publicId),
icon: (
<HiOutlineSquaresPlus className="h-[18px] w-[18px] text-dark-900" />
),
},
{
label: t`Delete list`,
action: handleOpenDeleteListConfirmation,
icon: (
<HiOutlineTrash className="h-[18px] w-[18px] text-dark-900" />
),
},
]}
>
<HiEllipsisHorizontal className="h-5 w-5 text-dark-900" />
</Dropdown>
</div>
</div>
</div>
{children}
</div>
)}
</Draggable>
);
}