98 lines
3.7 KiB
TypeScript
98 lines
3.7 KiB
TypeScript
import { Box, Divider, Group, Tabs } from "@mantine/core";
|
|
import { IconLink, IconMessage, IconPaperclip } from "@tabler/icons-react";
|
|
import { useState } from "react";
|
|
import type { Card, CardMessage, User } from "../types";
|
|
import { CardChatPanel } from "./CardChatPanel";
|
|
import { CardFilesPanel } from "./CardFilesPanel";
|
|
import { CardLinksPanel } from "./CardLinksPanel";
|
|
import { CardForm, CardFormValues } from "./CardForm";
|
|
|
|
interface Props {
|
|
card: Card;
|
|
users: User[];
|
|
currentUserId?: string;
|
|
requesterOptions: string[];
|
|
tagOptions: string[];
|
|
onSubmit: (v: CardFormValues) => Promise<void> | void;
|
|
onCancel: () => void;
|
|
// When set, the chat panel auto-scrolls to this message id and pulses
|
|
// it briefly. Used when opening a card from a notification click.
|
|
highlightMessageId?: string;
|
|
}
|
|
|
|
export function CardEditPanel({
|
|
card,
|
|
users,
|
|
currentUserId,
|
|
requesterOptions,
|
|
tagOptions,
|
|
onSubmit,
|
|
onCancel,
|
|
highlightMessageId,
|
|
}: Props) {
|
|
const [messages, setMessages] = useState<CardMessage[]>([]);
|
|
const [liveCard, setLiveCard] = useState(card);
|
|
const [filesRefreshKey, setFilesRefreshKey] = useState(0);
|
|
|
|
const wrappedSubmit = async (v: CardFormValues) => {
|
|
setLiveCard((c) => ({ ...c, title: v.title, description: v.description, requester: v.requester, tags: v.tags, assignee_id: v.assignee_id }));
|
|
await onSubmit(v);
|
|
};
|
|
|
|
const bumpFiles = () => setFilesRefreshKey((k) => k + 1);
|
|
|
|
return (
|
|
<Group align="stretch" gap="md" wrap="nowrap" style={{ minHeight: 460 }}>
|
|
<Box style={{ flex: "1 1 0", minWidth: 320 }}>
|
|
<CardForm
|
|
users={users}
|
|
requesterOptions={requesterOptions}
|
|
tagOptions={tagOptions}
|
|
initial={{
|
|
requester: liveCard.requester,
|
|
title: liveCard.title,
|
|
description: liveCard.description,
|
|
assignee_id: liveCard.assignee_id,
|
|
tags: liveCard.tags || [],
|
|
}}
|
|
submitLabel="Guardar"
|
|
cardId={liveCard.id}
|
|
onFileUploaded={bumpFiles}
|
|
onSubmit={wrappedSubmit}
|
|
onCancel={onCancel}
|
|
/>
|
|
</Box>
|
|
<Divider orientation="vertical" />
|
|
<Box style={{ flex: "1 1 0", minWidth: 320, display: "flex", flexDirection: "column" }}>
|
|
<Tabs defaultValue="chat" keepMounted={false} style={{ display: "flex", flexDirection: "column", flex: 1, minHeight: 0 }}>
|
|
<Tabs.List>
|
|
<Tabs.Tab value="chat" leftSection={<IconMessage size={14} />}>Chat</Tabs.Tab>
|
|
<Tabs.Tab value="links" leftSection={<IconLink size={14} />}>Enlaces</Tabs.Tab>
|
|
<Tabs.Tab value="files" leftSection={<IconPaperclip size={14} />}>Archivos</Tabs.Tab>
|
|
</Tabs.List>
|
|
<Box pt="xs" style={{ flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }}>
|
|
<Tabs.Panel value="chat" style={{ flex: 1, minHeight: 0, display: "flex" }}>
|
|
<Box style={{ flex: 1, minHeight: 0, display: "flex", flexDirection: "column", width: "100%" }}>
|
|
<CardChatPanel
|
|
cardId={liveCard.id}
|
|
users={users}
|
|
currentUserId={currentUserId}
|
|
onMessagesChange={setMessages}
|
|
onFileUploaded={bumpFiles}
|
|
highlightMessageId={highlightMessageId}
|
|
/>
|
|
</Box>
|
|
</Tabs.Panel>
|
|
<Tabs.Panel value="links">
|
|
<CardLinksPanel card={liveCard} messages={messages} />
|
|
</Tabs.Panel>
|
|
<Tabs.Panel value="files">
|
|
<CardFilesPanel cardId={liveCard.id} refreshKey={filesRefreshKey} />
|
|
</Tabs.Panel>
|
|
</Box>
|
|
</Tabs>
|
|
</Box>
|
|
</Group>
|
|
);
|
|
}
|