mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
145 lines
4.6 KiB
React
145 lines
4.6 KiB
React
import { useMemo, useRef, useState, useCallback } from "react";
|
|
import { useNavigate } from "react-router-dom";
|
|
|
|
import { useCourses } from "@/contexts/AdminCoursesContext";
|
|
import { useAuth } from "@/contexts/AuthContext";
|
|
|
|
import DataTable from "@/components/generic/Table/DataTable";
|
|
import { FilterSheet } from "@/components/generic/Sheet/FilterSheet";
|
|
import { ArchiveDialog } from "@/components/generic/Dialogs/ArchiveDialog";
|
|
|
|
import { buildDataColumns, columnPinning } from "../../config/courses/units/columns.config";
|
|
import { buildToolbarActions } from "../../config/courses/units/toolbar.config";
|
|
import { buildSelectionActions } from "../../config/courses/units/selection.config";
|
|
import { buildRowActions } from "../../config/courses/units/rowActions.config";
|
|
|
|
import { getTimestamp } from "@/utils/timestamp.util";
|
|
|
|
export default function UnitsTable({ courseId }) {
|
|
const [archiveTarget, setArchiveTarget] = useState(null);
|
|
const [archiveIds, setArchiveIds] = useState(null);
|
|
|
|
const tableRefsRef = useRef({
|
|
getFilters: () => [],
|
|
getSort: () => [],
|
|
resetSelection: () => { },
|
|
setFilters: () => { },
|
|
});
|
|
|
|
const navigate = useNavigate();
|
|
|
|
const {
|
|
course, units, attributes, pagination, setPagination, loading,
|
|
fetchUnits, archiveUnit, archiveUnits, fetchUnitFieldValues
|
|
} = useCourses();
|
|
|
|
const handleRefsReady = (refs) => {
|
|
tableRefsRef.current = refs;
|
|
};
|
|
|
|
const exportConfig = {
|
|
allData: units,
|
|
attributes,
|
|
filename: `${getTimestamp()}_${course?.title}_Units`,
|
|
sheetName: "Units",
|
|
};
|
|
|
|
const handleFetch = useCallback(
|
|
(params) => fetchUnits(courseId, params),
|
|
[courseId]
|
|
);
|
|
|
|
const rowActions = useMemo(() => buildRowActions({
|
|
onQuiz: (row) => navigate(`/admin/courses/${courseId}/units/${row.unit_id}/quiz`),
|
|
onViewLessons: (row) => navigate(`/admin/courses/${courseId}/units/${row.unit_id}/lessons`),
|
|
onView: (row) => navigate(`/admin/courses/${courseId}/units/${row.unit_id}/view`),
|
|
onEdit: (row) => navigate(`/admin/courses/${courseId}/units/${row.unit_id}/edit`),
|
|
onArchive: (row) => setArchiveTarget(row),
|
|
}), [courseId]);
|
|
|
|
const toolbarActions = buildToolbarActions({
|
|
fetchUnits: (params) => fetchUnits(courseId, params),
|
|
pagination,
|
|
exportConfig,
|
|
navigate,
|
|
courseId,
|
|
getFilters: () => tableRefsRef.current.getFilters(),
|
|
getSort: () => tableRefsRef.current.getSort(),
|
|
getTableInstance: () => tableRefsRef.current.tableInstance,
|
|
});
|
|
|
|
const selectionActions = buildSelectionActions({
|
|
exportConfig,
|
|
onArchive: (row) => setArchiveTarget(row),
|
|
onArchiveMany: (ids) => setArchiveIds(ids),
|
|
getTableInstance: () => tableRefsRef.current.tableInstance,
|
|
});
|
|
|
|
const columns = useMemo(
|
|
() => buildDataColumns(attributes, rowActions),
|
|
[attributes, rowActions]
|
|
);
|
|
|
|
const handleArchiveSuccess = () => {
|
|
setArchiveTarget(null);
|
|
setArchiveIds(null);
|
|
tableRefsRef.current.resetSelection?.();
|
|
fetchUnits(courseId, { page: 1, limit: pagination?.limit ?? 10 });
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<DataTable
|
|
title="Units"
|
|
data={units}
|
|
columns={columns}
|
|
attributes={attributes}
|
|
pagination={pagination}
|
|
setPagination={setPagination}
|
|
loading={loading}
|
|
onFetch={handleFetch}
|
|
onFetchFilterData={(field) => fetchUnitFieldValues(courseId, field)}
|
|
onRefsReady={handleRefsReady}
|
|
renderFilterSheet={({ open, onOpenChange, column, attr, data, loading }) => (
|
|
<FilterSheet
|
|
open={open}
|
|
onOpenChange={onOpenChange}
|
|
column={column}
|
|
attr={attr}
|
|
data={data}
|
|
loading={loading}
|
|
/>
|
|
)}
|
|
columnPinning={columnPinning}
|
|
toolbarActions={toolbarActions}
|
|
selectionActions={selectionActions}
|
|
recordLabel="unit"
|
|
emptyMessage="No units found."
|
|
/>
|
|
|
|
{/* ── Single archive ── */}
|
|
<ArchiveDialog
|
|
open={!!archiveTarget}
|
|
onOpenChange={(v) => !v && setArchiveTarget(null)}
|
|
entity={archiveTarget}
|
|
entityLabel="Unit"
|
|
getName={(c) => c?.title}
|
|
onArchive={(c) => archiveUnit(courseId, c?.unit_id)}
|
|
loading={loading}
|
|
onSuccess={handleArchiveSuccess}
|
|
/>
|
|
|
|
{/* ── Bulk archive ── */}
|
|
<ArchiveDialog
|
|
open={!!archiveIds}
|
|
onOpenChange={(v) => !v && setArchiveIds(null)}
|
|
ids={archiveIds ?? []}
|
|
entityLabel="Unit"
|
|
onArchive={(ids) => archiveUnits(courseId, ids)}
|
|
loading={loading}
|
|
onSuccess={handleArchiveSuccess}
|
|
/>
|
|
</>
|
|
);
|
|
}
|