implement phase 5 และ fix bugs

This commit is contained in:
Suphonchai Phoonsawat 2026-08-19 23:06:57 +07:00
parent f4b1c3e14b
commit 1bb850c6b8
40 changed files with 1507 additions and 429 deletions

View file

@ -0,0 +1,128 @@
import * as React from "react";
import {
Badge,
Button,
MessageBar,
MessageBarBody,
Spinner,
Text,
makeStyles,
tokens,
} from "@fluentui/react-components";
import { ArrowDownload24Regular, History24Regular } from "@fluentui/react-icons";
import { VersionRecord } from "../../models/versionRecord";
interface VersionHistoryPanelProps {
versions: VersionRecord[];
loading: boolean;
error: string | null;
/** versionId ของ version ที่กำลังดาวน์โหลดอยู่ (แสดง spinner ที่ปุ่ม) */
downloadingVersionId: string | null;
onDownload: (version: VersionRecord) => void;
onRetry: () => void;
}
const useStyles = makeStyles({
root: {
display: "flex",
flexDirection: "column",
gap: tokens.spacingVerticalS,
},
header: {
display: "flex",
alignItems: "center",
gap: tokens.spacingHorizontalXS,
marginTop: tokens.spacingVerticalL,
marginBottom: tokens.spacingVerticalXXS,
},
item: {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
gap: tokens.spacingHorizontalS,
padding: `${tokens.spacingVerticalXS} ${tokens.spacingHorizontalS}`,
borderRadius: tokens.borderRadiusMedium,
":hover": {
backgroundColor: tokens.colorNeutralBackground1Hover,
},
},
itemInfo: {
display: "flex",
flexDirection: "column",
minWidth: 0,
},
metaRow: {
color: tokens.colorNeutralForeground3,
fontSize: tokens.fontSizeBase200,
},
});
function formatTimestamp(iso: string): string {
const date = new Date(iso);
return Number.isNaN(date.getTime())
? iso
: date.toLocaleString(undefined, { dateStyle: "medium", timeStyle: "short" });
}
/** FR-4 — แสดง version history (เลข version / เวลา / ผู้สร้าง) + ปุ่มดาวน์โหลด version นั้น */
export const VersionHistoryPanel: React.FC<VersionHistoryPanelProps> = ({
versions,
loading,
error,
downloadingVersionId,
onDownload,
onRetry,
}) => {
const styles = useStyles();
return (
<div className={styles.root}>
<div className={styles.header}>
<History24Regular />
<Text weight="semibold">Version history</Text>
</div>
{loading ? <Spinner size="small" label="กำลังโหลด…" /> : null}
{error ? (
<MessageBar intent="error">
<MessageBarBody>
{error}{" "}
<Button size="small" appearance="subtle" onClick={onRetry}>
ลองใหม่
</Button>
</MessageBarBody>
</MessageBar>
) : null}
{!loading && !error && versions.length === 0 ? (
<Text size={200} style={{ color: tokens.colorNeutralForeground3 }}>
ยังไม่มี version ในระบบ
</Text>
) : null}
{versions.map((version) => (
<div className={styles.item} key={version.versionId}>
<div className={styles.itemInfo}>
<Badge appearance="filled" color="brand">
v{version.versionNumber}
</Badge>
<span className={styles.metaRow}>{formatTimestamp(version.createdAt)}</span>
<span className={styles.metaRow}>โดย {version.createdByUserId}</span>
</div>
<Button
icon={<ArrowDownload24Regular />}
size="small"
appearance="subtle"
disabled={downloadingVersionId !== null}
onClick={() => onDownload(version)}
>
{downloadingVersionId === version.versionId ? "กำลังดาวน์โหลด…" : "ดาวน์โหลด"}
</Button>
</div>
))}
</div>
);
};
export default VersionHistoryPanel;