add: ver()

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-07-08 11:31:54 +08:00
parent 6624c0d27f
commit 182bd93d10
46 changed files with 4407 additions and 98 deletions
@@ -3,9 +3,12 @@ import { useNavigate } from "react-router-dom";
import { useCourses } from "@/contexts/AdminCoursesContext";
import api from "@/utils/api.util";
import DataTable from "@/components/generic/Table/DataTable";
import { FilterSheet } from "@/components/generic/Sheet/FilterSheet";
import { ArchiveDialog } from "@/components/generic/Dialogs/ArchiveDialog";
import AttachLessonsDialog from "../library/AttachLessonsDialog";
import { Link2 } from "lucide-react";
import { buildDataColumns, columnPinning } from "../../config/courses/lessons/columns.config";
import { buildToolbarActions } from "../../config/courses/lessons/toolbar.config";
@@ -17,6 +20,7 @@ import { getTimestamp } from "@/utils/timestamp.util";
export default function LessonsTable({ courseId, unitId }) {
const [archiveTarget, setArchiveTarget] = useState(null);
const [archiveIds, setArchiveIds] = useState(null);
const [attachOpen, setAttachOpen] = useState(false);
const tableRefsRef = useRef({
getFilters: () => [],
@@ -55,17 +59,35 @@ export default function LessonsTable({ courseId, unitId }) {
onArchive: (row) => setArchiveTarget(row),
}), [courseId, unitId]);
const toolbarActions = buildToolbarActions({
fetchLessons: (params) => fetchLessons(courseId, unitId, params),
pagination,
exportConfig,
navigate,
courseId,
unitId,
getFilters: () => tableRefsRef.current.getFilters(),
getSort: () => tableRefsRef.current.getSort(),
getTableInstance: () => tableRefsRef.current.tableInstance,
});
const toolbarActions = [
...buildToolbarActions({
fetchLessons: (params) => fetchLessons(courseId, unitId, params),
pagination,
exportConfig,
navigate,
courseId,
unitId,
getFilters: () => tableRefsRef.current.getFilters(),
getSort: () => tableRefsRef.current.getSort(),
getTableInstance: () => tableRefsRef.current.tableInstance,
}),
// Junction revamp — lessons live standalone in the library; attach without re-creating
{
key: "attach-existing",
type: "button",
label: "Attach Existing",
icon: <Link2 className="h-3.5 w-3.5" />,
variant: "outline",
onClick: () => setAttachOpen(true),
},
];
const handleAttachLessons = async (lessonIds) => {
for (const lesson_id of lessonIds) {
await api.post(`/admin/courses/${courseId}/units/${unitId}/lessons`, { lesson_id });
}
fetchLessons(courseId, unitId, { page: 1, limit: pagination?.limit ?? 10 });
};
const selectionActions = buildSelectionActions({
exportConfig,
@@ -138,6 +160,15 @@ export default function LessonsTable({ courseId, unitId }) {
loading={loading}
onSuccess={handleArchiveSuccess}
/>
{/* ── Attach existing library lessons ── */}
<AttachLessonsDialog
open={attachOpen}
onOpenChange={setAttachOpen}
attachedLessonIds={lessons.map((l) => l.lesson_id)}
onAttach={handleAttachLessons}
loading={loading}
/>
</>
);
}
@@ -8,6 +8,8 @@ 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 AttachUnitsDialog from "../library/AttachUnitsDialog";
import { Link2 } from "lucide-react";
import { buildDataColumns, columnPinning } from "../../config/courses/units/columns.config";
import { buildToolbarActions } from "../../config/courses/units/toolbar.config";
@@ -19,6 +21,7 @@ import { getTimestamp } from "@/utils/timestamp.util";
export default function UnitsTable({ courseId }) {
const [archiveTarget, setArchiveTarget] = useState(null);
const [archiveIds, setArchiveIds] = useState(null);
const [attachOpen, setAttachOpen] = useState(false);
const tableRefsRef = useRef({
getFilters: () => [],
@@ -58,16 +61,32 @@ export default function UnitsTable({ courseId }) {
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 toolbarActions = [
...buildToolbarActions({
fetchUnits: (params) => fetchUnits(courseId, params),
pagination,
exportConfig,
navigate,
courseId,
getFilters: () => tableRefsRef.current.getFilters(),
getSort: () => tableRefsRef.current.getSort(),
getTableInstance: () => tableRefsRef.current.tableInstance,
}),
// Junction revamp — units live standalone in the library; attach without re-creating
{
key: "attach-existing",
type: "button",
label: "Attach Existing",
icon: <Link2 className="h-3.5 w-3.5" />,
variant: "outline",
onClick: () => setAttachOpen(true),
},
];
const handleAttachUnits = async (unitIds) => {
await api.post(`/admin/courses/${courseId}/units/attach`, { unit_ids: unitIds });
fetchUnits(courseId, { page: 1, limit: pagination?.limit ?? 10 });
};
const selectionActions = buildSelectionActions({
exportConfig,
@@ -150,6 +169,15 @@ export default function UnitsTable({ courseId }) {
loading={loading}
onSuccess={handleArchiveSuccess}
/>
{/* ── Attach existing library units ── */}
<AttachUnitsDialog
open={attachOpen}
onOpenChange={setAttachOpen}
attachedUnitIds={units.map((u) => u.unit_id)}
onAttach={handleAttachUnits}
loading={loading}
/>
</>
);
}