lms/bootstrap/ssr/assets/section-DPFpz4mP.js
2025-12-15 12:26:23 +01:00

1108 lines
45 KiB
JavaScript

import { jsx, jsxs } from "react/jsx-runtime";
import { D as Dialog, a as DialogTrigger, b as DialogContent, c as DialogHeader, d as DialogTitle } from "./dialog-DGP_3dPQ.js";
import { u as useLang } from "./use-lang-44ndmTOc.js";
import * as React from "react";
import { useState, createContext, useContext, useEffect, useRef } from "react";
import { C as ChunkedUploaderInput } from "./chunked-uploader-input-CZfv7yqS.js";
import { L as LoadingButton } from "./loading-button-CCIxhJrY.js";
import { I as Input } from "./input-BsvJqbcd.js";
import { L as Label } from "./label-0rIIfpX0.js";
import { T as Textarea } from "./textarea-Z0d4V-ti.js";
import { o as onHandleChange } from "./inertia-BtwbgBI3.js";
import { usePage, router, useForm } from "@inertiajs/react";
import { C as Card, b as CardContent } from "./card-B-gBwpxd.js";
import { I as IconPickerDialog } from "./icon-picker-dialog-Bc1iwzL6.js";
import { B as Button } from "./button-CdJZJLGw.js";
import { c as cn } from "./utils-DLCPGU0v.js";
import { X, Plus, ArrowUpDown, Search, Star, Pencil } from "lucide-react";
import { T as TableHeader } from "./table-header-CdEXSV6s.js";
import { T as Table, a as TableBody, b as TableRow, c as TableCell } from "./table-BMWNGY4o.js";
import { useReactTable, getFilteredRowModel, getSortedRowModel, getCoreRowModel, flexRender } from "@tanstack/react-table";
import { T as TablePageSize } from "./table-page-size-CF314lUl.js";
import { d as debounce } from "./debounce-ZFxqVthq.js";
import { g as getQueryParams } from "./route-DlE7FdTW.js";
import { D as DropdownMenu, a as DropdownMenuTrigger, b as DropdownMenuContent, c as DropdownMenuItem } from "./dropdown-menu-msun3TP8.js";
import { S as ScrollArea } from "./scroll-area-CDdrLubh.js";
import { A as Avatar, a as AvatarImage, b as AvatarFallback } from "./avatar-C8iCpF5R.js";
const getPageSection = (page, slug) => {
return page.sections.find((section2) => section2.slug === slug);
};
const formatLabel = (key) => {
return key.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase());
};
const generateFieldByType = (key, value) => {
if (typeof value === "string") {
if (key === "image" || key.includes("image") || key === "avatar" || typeof value === "string" && value.match(/\.(jpeg|jpg|gif|png)$/i)) {
return {
type: "file",
label: formatLabel(key),
name: key,
value: null
};
} else if (key === "description" || key.includes("description") || key === "bio" || key === "content") {
return {
type: "textarea",
label: formatLabel(key),
name: key,
value: value || ""
};
} else if (key === "url" || key.includes("_url") || key.includes("link")) {
return {
type: "url",
label: formatLabel(key),
name: key,
value: value || ""
};
} else if (key === "icon") {
return {
type: "icon",
label: formatLabel(key),
name: key,
value: value || ""
};
} else {
return {
type: "text",
label: formatLabel(key),
name: key,
value: value || ""
};
}
} else if (typeof value === "number") {
return {
type: "number",
label: formatLabel(key),
name: key,
value: value || 0
};
} else if (typeof value === "boolean") {
return {
type: "boolean",
label: formatLabel(key),
name: key,
value: value || false
};
} else {
return {
type: "text",
label: formatLabel(key),
name: key,
value: (value == null ? void 0 : value.toString()) || ""
};
}
};
const generatePropertyFields = (properties) => {
if ("contents" in properties) {
const fields = [
{
type: "contents",
label: "Contents",
name: "contents",
value: properties.contents || []
}
];
Object.entries(properties).forEach(([key, value]) => {
if (key === "array") {
return;
}
if (key === "contents") {
return;
}
const field = generateFieldByType(key, value);
fields.unshift(field);
});
return fields;
}
if ("array" in properties) {
const sampleItem = Array.isArray(properties.array) && properties.array.length > 0 ? properties.array[0] : {};
let itemFields = [];
if (Object.keys(sampleItem).length > 0) {
Object.keys(sampleItem).forEach((key) => {
if (typeof sampleItem[key] === "string" || typeof sampleItem[key] === "number" || typeof sampleItem[key] === "boolean") {
itemFields.push(generateFieldByType(key, sampleItem[key]));
}
});
} else {
itemFields = [
{ type: "text", label: "Title", name: "title", value: "" },
{ type: "text", label: "Value", name: "value", value: "" }
];
}
const fields = [
{
type: "array",
label: "Items",
name: "array",
value: (properties.array || []).map((item) => {
const processedItem = { ...item };
Object.keys(processedItem).forEach((key) => {
if (key === "image" || key.includes("image")) {
processedItem[`new_image`] = null;
}
});
return processedItem;
}),
fields: itemFields
}
];
Object.entries(properties).forEach(([key, value]) => {
if (key === "array") {
return;
}
if (key === "contents") {
return;
}
const field = generateFieldByType(key, value);
fields.unshift(field);
});
return fields;
}
return Object.entries(properties).map(([key, value]) => {
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
return {
type: "object",
label: formatLabel(key),
name: key,
value,
fields: generatePropertyFields(value)
};
} else {
return generateFieldByType(key, value);
}
});
};
const isEmptyArrayItem = (array) => {
let flag = true;
Object.entries(array).forEach(([key, value]) => {
switch (typeof value) {
case "string":
if (value.length > 0) {
flag = false;
}
break;
case "number":
if (value > 0) {
flag = false;
}
break;
}
});
return flag;
};
const removeEmptyArrayItems = (array) => {
return array.filter((item) => {
let flag = false;
Object.entries(item).forEach(([key, value]) => {
switch (typeof value) {
case "string":
if (value.trim().length > 0) {
flag = true;
}
break;
case "number":
if (value > 0) {
flag = true;
}
break;
case "boolean":
if (value) {
flag = true;
}
break;
}
});
return flag;
});
};
const getPropertyArray = (section2) => {
var _a;
const array = (_a = section2 == null ? void 0 : section2.properties) == null ? void 0 : _a.array;
return array ? removeEmptyArrayItems(array) : [];
};
const SectionEditorContext = createContext(void 0);
const SectionEditorProvider = ({ children, section: section2, onSuccess, onError }) => {
const [open2, setOpen] = useState(false);
const [isSubmit, setIsSubmit] = useState(false);
const contextValue = {
section: section2,
// Dialog state
open: open2,
setOpen,
// Form submission state
isSubmit,
setIsSubmit
};
return /* @__PURE__ */ jsx(SectionEditorContext.Provider, { value: contextValue, children });
};
const useSectionEditor = () => {
const context = useContext(SectionEditorContext);
if (context === void 0) {
throw new Error("useSectionEditor must be used within a SectionEditorProvider");
}
return context;
};
const ArrayFields = ({ field, onChange }) => {
const { button } = useLang();
const [imagePreviews, setImagePreviews] = useState({});
const [arrayItems, setArrayItems] = useState(Array.isArray(field.value) ? field.value : []);
useEffect(() => {
if (Array.isArray(field.value)) {
setArrayItems(field.value);
}
}, [field.value, field.type]);
const handleArrayFileChange = (index, key, file) => {
handleArrayItemChange(index, "new_image", file);
const previewKey = `${index}-${key}`;
if (file && file.type.startsWith("image/")) {
if (imagePreviews[previewKey]) {
URL.revokeObjectURL(imagePreviews[previewKey]);
}
const previewUrl = URL.createObjectURL(file);
setImagePreviews((prev) => ({
...prev,
[previewKey]: previewUrl
}));
} else {
setImagePreviews((prev) => {
const updated = { ...prev };
if (updated[previewKey]) {
URL.revokeObjectURL(updated[previewKey]);
delete updated[previewKey];
}
return updated;
});
if (file === null) {
handleArrayItemChange(index, "new_image", null);
}
}
};
const handleArrayItemChange = (index, key, value) => {
const updatedItems = [...arrayItems];
if (!updatedItems[index]) {
updatedItems[index] = {};
}
updatedItems[index][key] = value;
setArrayItems(updatedItems);
onChange(updatedItems);
};
const addArrayItem = () => {
var _a;
const emptyItem = (_a = field.fields) == null ? void 0 : _a.reduce((acc, fieldDef) => {
acc[fieldDef.name] = fieldDef.value;
return acc;
}, {});
const newItems = [...arrayItems, emptyItem];
setArrayItems(newItems);
onChange(newItems);
};
const removeArrayItem = (index) => {
const newItems = arrayItems.filter((_, i) => i !== index);
setArrayItems(newItems);
onChange(newItems);
};
return /* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx("div", { className: "space-y-4", children: arrayItems.map((item, index) => {
var _a;
const isFirstItemEmpty = index === 0 && isEmptyArrayItem(item);
return /* @__PURE__ */ jsx(Card, { className: cn("relative", isFirstItemEmpty && "hidden"), children: /* @__PURE__ */ jsxs(CardContent, { className: "p-4 pt-6", children: [
/* @__PURE__ */ jsx(
Button,
{
size: "icon",
type: "button",
variant: "ghost",
onClick: () => removeArrayItem(index),
className: "absolute top-2 right-2 text-red-600 hover:text-red-800",
children: /* @__PURE__ */ jsx(X, { className: "h-5 w-5" })
}
),
(_a = field.fields) == null ? void 0 : _a.map((subField, fieldIdx) => {
const prevImage = subField.type === "file" ? item.image : null;
return /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
/* @__PURE__ */ jsx(Label, { htmlFor: `${field.name}-${index}-${subField.name}`, className: "mb-2 block", children: subField.label }),
/* @__PURE__ */ jsx("div", { className: "mt-1", children: subField.type === "textarea" ? /* @__PURE__ */ jsx(
Textarea,
{
id: `${field.name}-${index}-${subField.name}`,
value: item[subField.name] || "",
onChange: (e) => handleArrayItemChange(index, subField.name, e.target.value),
rows: 3
}
) : subField.type === "file" ? /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
/* @__PURE__ */ jsx(
Input,
{
type: "file",
id: `${field.name}-${index}-${subField.name}`,
accept: "image/*",
onChange: (e) => {
var _a2;
return handleArrayFileChange(index, subField.name, ((_a2 = e.target.files) == null ? void 0 : _a2[0]) || null);
},
className: "cursor-pointer"
}
),
(imagePreviews[`${index}-${subField.name}`] || prevImage) && /* @__PURE__ */ jsx("div", { className: "relative inline-block", children: /* @__PURE__ */ jsx(
"img",
{
alt: "Preview",
src: imagePreviews[`${index}-${subField.name}`] || prevImage,
className: "h-20 w-auto rounded-lg border object-cover shadow-sm"
}
) })
] }) : subField.type === "icon" ? /* @__PURE__ */ jsx(
IconPickerDialog,
{
name: subField.name,
value: item[subField.name] || "",
placeholder: "Pick your category icon",
onSelect: (icon) => handleArrayItemChange(index, subField.name, icon)
}
) : /* @__PURE__ */ jsx(
Input,
{
type: subField.type === "number" ? "number" : "text",
id: `${field.name}-${index}-${subField.name}`,
value: item[subField.name] || "",
onChange: (e) => handleArrayItemChange(index, subField.name, e.target.value)
}
) })
] }, fieldIdx);
})
] }) }, index);
}) }),
/* @__PURE__ */ jsx("div", { className: "mt-4", children: /* @__PURE__ */ jsxs(Button, { type: "button", onClick: addArrayItem, variant: "outline", size: "sm", className: "flex items-center", children: [
/* @__PURE__ */ jsx(Plus, { className: "mr-1 h-4 w-4" }),
button.add_item
] }) })
] });
};
const CategoriesTableColumn = (translate) => [
{
accessorKey: "title",
header: ({ column }) => /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), children: [
translate.table.category_name,
/* @__PURE__ */ jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })
] }),
cell: ({ row }) => /* @__PURE__ */ jsx("div", { className: "capitalize", children: row.getValue("title") })
},
{
accessorKey: "courses_count",
header: ({ column }) => /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), children: [
translate.table.courses,
/* @__PURE__ */ jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })
] }) }),
cell: ({ row }) => /* @__PURE__ */ jsx("div", { className: "text-center", children: /* @__PURE__ */ jsx("p", { children: row.original.courses_count }) })
}
];
const TableFilter = (props) => {
const { Icon, data, title, component, globalSearch, tablePageSizes, routeName, className, searchKey = "search" } = props;
const page = usePage();
const urlParams = getQueryParams(page.url);
const searchRef = useRef(null);
const searchHandler = debounce(async (e) => {
const query = e.target.value;
router.get(
route(routeName || "", {
...urlParams,
[searchKey]: query
}),
{},
{ preserveState: true }
// This preserves component state across navigation
);
}, 300);
useEffect(() => {
if (urlParams[searchKey] && searchRef.current) {
searchRef.current.focus();
}
}, [props]);
return /* @__PURE__ */ jsxs("div", { className: cn("items-center justify-between p-6 md:flex", className), children: [
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-5", children: [
Icon && /* @__PURE__ */ jsx("div", { className: "bg-primary-25 flex h-10 w-10 items-center justify-center rounded-md", children: Icon }),
title && /* @__PURE__ */ jsx("p", { className: "mb-4 text-lg font-semibold md:mb-0", children: title })
] }),
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end", children: [
globalSearch && /* @__PURE__ */ jsxs("div", { className: "relative w-full md:max-w-[260px]", children: [
/* @__PURE__ */ jsx(
"input",
{
type: "text",
ref: searchRef,
placeholder: "Search",
onChange: searchHandler,
className: "focus:border-primary border-border h-10 w-full rounded-md border py-[15px] pr-4 pl-12 text-sm font-normal focus:ring-0 focus:outline-0",
defaultValue: urlParams[searchKey] ?? ""
}
),
/* @__PURE__ */ jsx(Search, { className: "absolute top-3 left-4 z-10 h-4 w-4" })
] }),
routeName && /* @__PURE__ */ jsx(
TablePageSize,
{
routeName,
pageData: data,
dropdownList: tablePageSizes,
pageSizeKey: `${searchKey}_per_page`,
className: "ml-3"
}
),
component && component
] })
] });
};
const TableFooter = (props) => {
const { paginationInfo, paginationKey = "page" } = props;
const { current_page, last_page, first_page_url, last_page_url, next_page_url, prev_page_url } = paginationInfo;
const page = usePage();
const urlParams = getQueryParams(page.url);
const dropdownList = [];
if (last_page > 0) {
for (let i = 1; i <= last_page; i++) {
dropdownList.push({
key: `${i}`,
value: i
});
}
} else {
dropdownList.push({
key: "1",
value: 1
});
}
const gotoPage = (pageNumber) => {
router.get(
route(props.routeName, {
...props.routeParams || {},
...urlParams,
[paginationKey]: pageNumber
}),
{},
{ preserveState: true }
);
};
const gotoRoute = (path) => {
const pathParams = getQueryParams(path);
router.get(
route(props.routeName, {
...props.routeParams || {},
...urlParams,
[paginationKey]: pathParams.page
}),
{},
{ preserveState: true }
);
};
const menuItem = (e) => {
return `text-center py-1 ${current_page === e && "bg-primary-50"}`;
};
return /* @__PURE__ */ jsxs("div", { className: `space-y-4 ${props.className}`, children: [
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center", children: [
/* @__PURE__ */ jsx("span", { className: "mr-1", children: /* @__PURE__ */ jsxs("strong", { children: [
current_page,
" of ",
last_page
] }) }),
/* @__PURE__ */ jsx("span", { className: "mr-3", children: "| Go to page:" }),
/* @__PURE__ */ jsxs(DropdownMenu, { children: [
/* @__PURE__ */ jsx(DropdownMenuTrigger, { children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", className: "h-8 w-[60px] rounded-md border", children: current_page }) }),
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "end", className: "min-w-[60px]", children: /* @__PURE__ */ jsx(ScrollArea, { className: "", children: dropdownList.map((item) => /* @__PURE__ */ jsx(DropdownMenuItem, { onClick: () => gotoPage(item.value), className: menuItem(item.value), children: item.value }, item.key)) }) })
] })
] }),
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center", children: [
/* @__PURE__ */ jsx(
Button,
{
type: "button",
variant: "ghost",
disabled: !prev_page_url,
onClick: () => gotoRoute(first_page_url),
className: "bg-muted border-border h-8 border px-2 text-xs sm:px-3",
children: "<<First"
}
),
/* @__PURE__ */ jsx(
Button,
{
type: "button",
variant: "ghost",
disabled: !prev_page_url,
onClick: () => gotoRoute(prev_page_url),
className: "bg-muted border-border mx-3 h-8 border px-2 text-xs sm:px-3",
children: "Prev"
}
),
/* @__PURE__ */ jsx(
Button,
{
type: "button",
variant: "ghost",
disabled: !next_page_url,
onClick: () => gotoRoute(next_page_url),
className: "bg-muted border-border mx-3 h-8 border px-2 text-xs sm:px-3",
children: "Next"
}
),
/* @__PURE__ */ jsx(
Button,
{
type: "button",
variant: "ghost",
disabled: !next_page_url,
onClick: () => gotoRoute(last_page_url),
className: "bg-muted border-border h-8 border px-2 text-xs sm:px-3",
children: "Last>>"
}
)
] })
] });
};
const Categories = ({ categories, selectedIds = [], onCourseSelect }) => {
var _a;
const page = usePage();
const routeName = page.props.type === "demo" ? "home.demo" : "home";
const [sorting, setSorting] = React.useState([]);
const table = useReactTable({
data: categories.data,
columns: CategoriesTableColumn(page.props.translate),
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
state: { sorting }
});
return /* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx(
TableFilter,
{
data: categories,
title: "Categories",
globalSearch: true,
searchKey: "category",
tablePageSizes: [10, 15, 20, 25],
routeName
}
),
/* @__PURE__ */ jsxs(Table, { className: "border-border border-y", children: [
/* @__PURE__ */ jsx(TableHeader, { table }),
/* @__PURE__ */ jsx(TableBody, { children: ((_a = table.getRowModel().rows) == null ? void 0 : _a.length) ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(
TableRow,
{
"data-state": row.getIsSelected() && "selected",
className: cn("hover:bg-muted cursor-pointer", (selectedIds == null ? void 0 : selectedIds.includes(Number(row.original.id))) && "bg-secondary-light"),
onClick: () => onCourseSelect && onCourseSelect(Number(row.original.id)),
children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(TableCell, { children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))
},
row.id
)) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { className: "h-24 text-center", children: page.props.translate.common.no_results_found }) }) })
] }),
/* @__PURE__ */ jsx(TableFooter, { className: "p-4", routeName, paginationInfo: categories, paginationKey: "category" })
] });
};
const CoursesTableColumn = (translate) => [
{
accessorKey: "title",
header: "Title",
cell: ({ row }) => /* @__PURE__ */ jsx("div", { className: "capitalize", children: row.getValue("title") })
},
{
accessorKey: "enrollments_count",
header: ({ column }) => /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), children: [
translate.table.enrollments,
/* @__PURE__ */ jsx(ArrowUpDown, {})
] }) }),
cell: ({ row }) => /* @__PURE__ */ jsx("div", { className: "text-center", children: /* @__PURE__ */ jsx("p", { children: row.original.enrollments_count }) })
},
{
accessorKey: "average_rating",
header: ({ column }) => /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), children: [
"Rating",
/* @__PURE__ */ jsx(ArrowUpDown, {})
] }) }),
cell: ({ row }) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1 text-center", children: [
/* @__PURE__ */ jsx("p", { children: Number(row.original.average_rating).toFixed(1) }),
/* @__PURE__ */ jsx("span", { className: "text-yellow-500", children: /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", stroke: "currentColor", children: /* @__PURE__ */ jsx("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" }) }) }),
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground text-sm", children: [
"(",
row.original.reviews_count,
")"
] })
] })
}
];
const Courses = ({ courses, selectedIds = [], onCourseSelect }) => {
var _a;
const page = usePage();
const routeName = page.props.type === "demo" ? "home.demo" : "home";
const [sorting, setSorting] = React.useState([]);
const table = useReactTable({
data: courses.data,
columns: CoursesTableColumn(page.props.translate),
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
state: { sorting }
});
return /* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx(
TableFilter,
{
data: courses,
title: "Courses",
globalSearch: true,
searchKey: "course",
tablePageSizes: [10, 15, 20, 25],
routeName
}
),
/* @__PURE__ */ jsxs(Table, { className: "border-border border-y", children: [
/* @__PURE__ */ jsx(TableHeader, { table }),
/* @__PURE__ */ jsx(TableBody, { children: ((_a = table.getRowModel().rows) == null ? void 0 : _a.length) ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(
TableRow,
{
"data-state": row.getIsSelected() && "selected",
className: cn("hover:bg-muted cursor-pointer", (selectedIds == null ? void 0 : selectedIds.includes(Number(row.original.id))) && "bg-secondary-light"),
onClick: () => onCourseSelect && onCourseSelect(Number(row.original.id)),
children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(TableCell, { children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))
},
row.id
)) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { className: "h-24 text-center", children: page.props.translate.common.no_results_found }) }) })
] }),
/* @__PURE__ */ jsx(TableFooter, { className: "p-4", routeName, paginationInfo: courses })
] });
};
const InstructorsTableColumn = (translate) => [
{
accessorKey: "user.name",
header: ({ column }) => /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), children: [
translate.table.instructor,
/* @__PURE__ */ jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })
] }),
cell: ({ row }) => /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
/* @__PURE__ */ jsxs(Avatar, { className: "h-8 w-8", children: [
/* @__PURE__ */ jsx(AvatarImage, { src: row.original.user.photo || "", alt: row.original.user.name, className: "object-cover" }),
/* @__PURE__ */ jsx(AvatarFallback, { children: row.original.user.name.charAt(0) })
] }),
/* @__PURE__ */ jsx("span", { className: "capitalize", children: row.original.user.name })
] })
},
{
accessorKey: "total_enrollments",
header: ({ column }) => /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), children: [
translate.table.enrollments,
/* @__PURE__ */ jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })
] }) }),
cell: ({ row }) => /* @__PURE__ */ jsx("div", { className: "text-center", children: /* @__PURE__ */ jsx("p", { children: row.original.total_enrollments_count }) })
},
{
accessorKey: "average_rating",
header: ({ column }) => /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), children: [
translate.table.rating,
/* @__PURE__ */ jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })
] }) }),
cell: ({ row }) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1 text-center", children: [
/* @__PURE__ */ jsx("p", { children: Number(row.original.total_average_rating).toFixed(1) }),
/* @__PURE__ */ jsx(Star, { className: "h-4 w-4 fill-yellow-400 text-yellow-400" }),
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground text-sm", children: [
"(",
row.original.total_reviews_count,
")"
] })
] })
}
];
const Instructors = ({ instructors, selectedIds = [], onCourseSelect }) => {
var _a;
const page = usePage();
const routeName = page.props.type === "demo" ? "home.demo" : "home";
const [sorting, setSorting] = React.useState([]);
const table = useReactTable({
data: instructors.data,
columns: InstructorsTableColumn(page.props.translate),
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
state: { sorting }
});
return /* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx(
TableFilter,
{
data: instructors,
title: "Instructors",
globalSearch: true,
searchKey: "instructor",
tablePageSizes: [10, 15, 20, 25],
routeName
}
),
/* @__PURE__ */ jsxs(Table, { className: "border-border border-y", children: [
/* @__PURE__ */ jsx(TableHeader, { table }),
/* @__PURE__ */ jsx(TableBody, { children: ((_a = table.getRowModel().rows) == null ? void 0 : _a.length) ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(
TableRow,
{
"data-state": row.getIsSelected() && "selected",
className: cn("hover:bg-muted cursor-pointer", (selectedIds == null ? void 0 : selectedIds.includes(Number(row.original.id))) && "bg-secondary-light"),
onClick: () => onCourseSelect && onCourseSelect(Number(row.original.id)),
children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(TableCell, { children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))
},
row.id
)) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { className: "h-24 text-center", children: page.props.translate.common.no_results_found }) }) })
] }),
/* @__PURE__ */ jsx(TableFooter, { className: "p-4", routeName, paginationInfo: instructors, paginationKey: "instructor" })
] });
};
const Contents = ({ field, section_slug, onChange }) => {
var _a, _b;
const { props } = usePage();
const { courses, categories, instructors } = props;
const { section: section2 } = useSectionEditor();
const [contentList, setContentList] = useState(((_a = section2.properties) == null ? void 0 : _a.contents) ? (_b = section2.properties) == null ? void 0 : _b.contents : []);
useEffect(() => {
if (field.type === "contents" && Array.isArray(field.value)) {
setContentList(field.value);
}
}, [field.value, field.type]);
const onSelectChange = (id) => {
let updatedContents;
if (contentList.includes(id)) {
updatedContents = contentList.filter((item) => item !== id);
} else {
updatedContents = [...contentList, id];
}
setContentList(updatedContents);
onChange == null ? void 0 : onChange(updatedContents);
};
const renderField = () => {
switch (section_slug) {
case "hero":
case "top_course":
case "top_courses":
case "new_courses":
return /* @__PURE__ */ jsx(Courses, { courses, selectedIds: contentList, onCourseSelect: onSelectChange });
case "top_categories":
case "category_courses":
return /* @__PURE__ */ jsx(Categories, { categories, selectedIds: contentList, onCourseSelect: onSelectChange });
case "top_instructors":
return /* @__PURE__ */ jsx(Instructors, { instructors, selectedIds: contentList, onCourseSelect: onSelectChange });
case "blogs":
return /* @__PURE__ */ jsx("h1", { children: "Blogs" });
default:
return null;
}
};
return /* @__PURE__ */ jsx("div", { className: "rounded-md border", children: renderField() });
};
const Fields = ({ field, onChange }) => {
const { section: section2 } = useSectionEditor();
const [localValue, setLocalValue] = useState(field.value || "");
useEffect(() => {
setLocalValue(field.value || "");
}, [field.value, field.type]);
const handleInputChange = (e) => {
const { value, type } = e.target;
if (type === "checkbox") {
const checked = e.target.checked;
setLocalValue(checked);
onChange(checked);
return;
}
setLocalValue(value);
onChange(value);
};
const handleFileChange = (e) => {
var _a;
const file = ((_a = e.target.files) == null ? void 0 : _a[0]) || null;
setLocalValue(file);
onChange(file);
};
const renderField = () => {
var _a;
switch (field.type) {
case "contents":
return /* @__PURE__ */ jsx(Contents, { field, section_slug: section2.slug, onChange });
case "text":
case "url":
return /* @__PURE__ */ jsx(Input, { type: "text", id: field.name, name: field.name, value: localValue, onChange: handleInputChange });
case "textarea":
return /* @__PURE__ */ jsx(Textarea, { id: field.name, name: field.name, rows: 3, value: localValue, onChange: handleInputChange });
case "number":
return /* @__PURE__ */ jsx(Input, { type: "number", id: field.name, name: field.name, value: localValue, onChange: handleInputChange });
case "image":
case "file":
return /* @__PURE__ */ jsx(Input, { type: "file", id: field.name, name: field.name, onChange: handleFileChange });
case "boolean":
return /* @__PURE__ */ jsx(
Input,
{
type: "checkbox",
id: field.name,
name: field.name,
checked: localValue || false,
onChange: handleInputChange,
className: "h-4 w-4"
}
);
case "array":
return /* @__PURE__ */ jsx(ArrayFields, { field, onChange });
case "object":
return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(CardContent, { className: "p-4", children: (_a = field.fields) == null ? void 0 : _a.map((subField, index) => /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
/* @__PURE__ */ jsx(Label, { htmlFor: `${field.name}-${subField.name}`, className: "mb-2 block", children: subField.label }),
/* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(
Fields,
{
field: {
...subField,
name: `${field.name}-${subField.name}`,
value: field.value && field.value[subField.name] !== void 0 ? field.value[subField.name] : subField.value
},
onChange: (value) => {
const newValue = { ...field.value || {}, [subField.name]: value };
onChange(newValue);
}
}
) })
] }, index)) }) });
default:
return null;
}
};
return /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
field.type !== "boolean" && field.type !== "contents" && /* @__PURE__ */ jsx(Label, { htmlFor: field.name, className: "mb-2 block", children: field.label }),
renderField(),
field.type === "boolean" && /* @__PURE__ */ jsx(Label, { htmlFor: field.name, className: "ml-2 inline-block", children: field.label })
] });
};
const EditForm = () => {
const { input, button, frontend } = useLang();
const { section: section2, setOpen, isSubmit, setIsSubmit } = useSectionEditor();
const [isFileSelected, setIsFileSelected] = useState(false);
const [isFileUploaded, setIsFileUploaded] = useState(false);
const [thumbnailPreview, setThumbnailPreview] = useState(section2.thumbnail || null);
const [backgroundPreview, setBackgroundPreview] = useState(section2.background_image || null);
const { data, setData, post, reset, processing, errors } = useForm({
title: section2.title,
sub_title: section2.sub_title,
description: section2.description || "",
thumbnail: null,
video_url: section2.video_url,
background_image: null,
background_color: section2.background_color,
properties: section2.properties,
active: section2.active,
sort: section2.sort
});
const properties = generatePropertyFields(data.properties);
const [propertyFields, setPropertyFields] = useState(properties);
useEffect(() => {
setPropertyFields(generatePropertyFields(section2.properties));
}, [section2]);
const handleSubmit = (e) => {
e.preventDefault();
if (isFileSelected) {
setIsSubmit(true);
return;
}
submitForm();
};
const submitForm = () => {
post(route("page.section.update", section2.id), {
onSuccess: () => {
reset();
setOpen(false);
setIsSubmit(false);
}
});
};
useEffect(() => {
if (data.video_url && isFileUploaded) {
submitForm();
reset("video_url");
setIsFileUploaded(false);
}
}, [data.video_url]);
const handlePropertyChange = (name, value) => {
setData((data2) => ({
...data2,
properties: {
...data2.properties,
[name]: value
}
}));
};
useEffect(() => {
if (!open) {
reset();
}
}, [open]);
return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
/* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
section2.flags.title && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
/* @__PURE__ */ jsx(Label, { htmlFor: "title", children: input.title }),
/* @__PURE__ */ jsx(
Input,
{
type: "text",
id: "title",
name: "title",
value: data.title,
onChange: (e) => onHandleChange(e, setData),
placeholder: input.title_placeholder
}
),
errors.title && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-red-600", children: errors.title })
] }),
section2.flags.sub_title && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
/* @__PURE__ */ jsx(Label, { htmlFor: "sub_title", children: input.sub_title }),
/* @__PURE__ */ jsx(
Input,
{
type: "text",
id: "sub_title",
name: "sub_title",
value: data.sub_title,
onChange: (e) => onHandleChange(e, setData),
placeholder: input.title_placeholder
}
),
errors.sub_title && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-red-600", children: errors.sub_title })
] }),
section2.flags.description && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
/* @__PURE__ */ jsx(Label, { htmlFor: "description", children: input.description }),
/* @__PURE__ */ jsx(
Textarea,
{
id: "description",
name: "description",
value: data.description || "",
onChange: (e) => onHandleChange(e, setData),
placeholder: input.description_placeholder,
rows: 3
}
),
errors.description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-red-600", children: errors.description })
] }),
section2.flags.thumbnail && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
/* @__PURE__ */ jsx(Label, { htmlFor: "thumbnail", children: input.thumbnail }),
/* @__PURE__ */ jsx(
Input,
{
type: "file",
id: "thumbnail",
name: "thumbnail",
accept: "image/*",
onChange: (e) => onHandleChange(e, setData, setThumbnailPreview),
className: "cursor-pointer"
}
),
errors.thumbnail && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-red-600", children: errors.thumbnail }),
thumbnailPreview && /* @__PURE__ */ jsx("img", { src: thumbnailPreview, alt: "Thumbnail Preview", className: "h-32 w-auto rounded-lg border object-cover shadow-sm" })
] }),
section2.flags.video_url && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
/* @__PURE__ */ jsx(Label, { htmlFor: "video_url", children: input.preview_video }),
/* @__PURE__ */ jsx(
ChunkedUploaderInput,
{
isSubmit,
filetype: "video",
delayUpload: false,
onFileSelected: (file) => {
setIsFileSelected(true);
},
onFileUploaded: (fileData) => {
setIsFileUploaded(true);
setData("video_url", fileData.file_url);
},
onError: (errors2) => {
setIsSubmit(false);
},
onCancelUpload: () => {
setIsSubmit(false);
}
}
),
errors.video_url && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-red-600", children: errors.video_url })
] }),
section2.flags.background_image && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
/* @__PURE__ */ jsx(Label, { htmlFor: "background_image", children: input.background_image }),
/* @__PURE__ */ jsx(
Input,
{
type: "file",
id: "background_image",
name: "background_image",
onChange: (e) => onHandleChange(e, setData, setBackgroundPreview)
}
),
errors.background_image && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-red-600", children: errors.background_image }),
backgroundPreview && /* @__PURE__ */ jsx("img", { src: backgroundPreview, alt: "Background Image Preview", className: "h-32 w-auto rounded-lg border object-cover shadow-sm" })
] }),
section2.flags.background_color && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
/* @__PURE__ */ jsx(Label, { htmlFor: "background_color", children: input.background_color }),
/* @__PURE__ */ jsx(
Input,
{
type: "color",
id: "background_color",
name: "background_color",
value: data.background_color,
onChange: (e) => onHandleChange(e, setData)
}
),
errors.background_color && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-red-600", children: errors.background_color })
] }),
propertyFields.length > 0 && /* @__PURE__ */ jsxs("div", { className: "", children: [
/* @__PURE__ */ jsx("h3", { className: "text-lg font-medium", children: frontend.section_properties }),
/* @__PURE__ */ jsx("div", { className: "mt-4 space-y-6", children: propertyFields.map((field, index) => {
return /* @__PURE__ */ jsx(Fields, { field, onChange: (value) => handlePropertyChange(field.name, value) }, `${field.name}-${index}`);
}) })
] })
] }),
/* @__PURE__ */ jsx("div", { className: "mt-8 flex justify-end", children: /* @__PURE__ */ jsx(LoadingButton, { loading: processing || isSubmit, disabled: processing || isSubmit, children: button.save }) })
] });
};
const SectionEditor = ({ section: section2, actionComponent }) => {
return /* @__PURE__ */ jsx(SectionEditorProvider, { section: section2, children: /* @__PURE__ */ jsx(SectionEditorContent, { actionComponent }) });
};
const SectionEditorContent = ({ actionComponent }) => {
const { button, frontend } = useLang();
const { open: open2, setOpen, isSubmit, section: section2 } = useSectionEditor();
return /* @__PURE__ */ jsxs(Dialog, { open: open2, onOpenChange: (value) => !isSubmit && setOpen(value), children: [
/* @__PURE__ */ jsx(DialogTrigger, { asChild: true, children: actionComponent }),
/* @__PURE__ */ jsxs(DialogContent, { className: "max-h-[90vh] overflow-y-auto", children: [
/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsxs(DialogTitle, { className: "text-lg font-medium", children: [
button.update,
" ",
section2.name,
" ",
frontend.section
] }) }),
/* @__PURE__ */ jsx(EditForm, {})
] })
] });
};
const Section = ({ containerClass, contentClass, children, pageSection, customize, containerStyle, contentStyle, ...props }) => {
return /* @__PURE__ */ jsx("section", { className: cn("container", containerClass), ...props, style: containerStyle, children: /* @__PURE__ */ jsxs("div", { className: cn(contentClass, customize && "section-edit"), style: contentStyle, children: [
customize && pageSection && /* @__PURE__ */ jsx(
SectionEditor,
{
section: pageSection,
actionComponent: /* @__PURE__ */ jsx(Button, { size: "icon", variant: "secondary", className: "absolute top-3 right-3 z-20", children: /* @__PURE__ */ jsx(Pencil, { className: "h-7 w-7" }) })
}
),
children
] }) });
};
const section = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
default: Section
}, Symbol.toStringTag, { value: "Module" }));
export {
Section as S,
getPropertyArray as a,
getPageSection as g,
section as s
};