diff --git a/components/form/field/FilePreview.tsx b/components/form/field/FilePreview.tsx index 7c35603..e64b8a0 100644 --- a/components/form/field/FilePreview.tsx +++ b/components/form/field/FilePreview.tsx @@ -120,9 +120,11 @@ export const ThumbPreview = ({ export const FilePreview = ({ url, disabled, + limit_name, }: { url: any; disabled?: boolean; + limit_name?: number; }) => { let ural = url; if (url instanceof File) { @@ -172,7 +174,8 @@ export const FilePreview = ({ const getFileNameWithoutExtension = (filename: string) => { const parts = filename.split("."); parts.pop(); // Hapus bagian terakhir (ekstensi) - return parts.join("."); // Gabungkan kembali + const result = parts.join("."); // Gabungkan kembali + return limit_name ? result.substring(0, limit_name) : result; }; const ura = ural && ural.startsWith("blob:") ? getFileNameWithoutExtension(ural) : ural; @@ -234,7 +237,6 @@ export const FilePreview = ({ onClick={() => { let _url: any = url && url.startsWith("blob:") ? ura : siteurl(ura || ""); - console.log(_url); window.open(_url, "_blank"); }} > @@ -302,7 +304,6 @@ const getFileName = (url: string) => { } const fileName = url.substring(url.lastIndexOf("/") + 1); - console.log({ fileName }); const dotIndex = fileName.lastIndexOf("."); const fullname = fileName; if (dotIndex === -1) { diff --git a/components/form/field/TypeDropdown.tsx b/components/form/field/TypeDropdown.tsx index 4882f1e..2c42b01 100644 --- a/components/form/field/TypeDropdown.tsx +++ b/components/form/field/TypeDropdown.tsx @@ -1,6 +1,4 @@ -import { useLocal } from "@/lib/utils/use-local"; import { Typeahead } from "./Typeahead"; -import { useEffect } from "react"; export const TypeDropdown: React.FC = ({ required, @@ -45,7 +43,6 @@ export const TypeDropdown: React.FC = ({ if (typeof onChange === "function" && item) { onChange(item); } - console.log(fm.data[name]); return item?.value || search; }} disabled={disabled} diff --git a/components/form/field/TypeInput.tsx b/components/form/field/TypeInput.tsx index 5dba222..638965e 100644 --- a/components/form/field/TypeInput.tsx +++ b/components/form/field/TypeInput.tsx @@ -5,7 +5,7 @@ import { Textarea } from "../../ui/text-area"; import { useEffect, useRef, useState } from "react"; import tinycolor from "tinycolor2"; import { FieldColorPicker } from "../../ui/FieldColorPopover"; -import { FaRegEye, FaRegEyeSlash, FaRegStar, FaStar } from "react-icons/fa6"; +import { FaRegEye, FaRegEyeSlash } from "react-icons/fa6"; import { Rating } from "../../ui/ratings"; import { getNumber } from "@/lib/utils/getNumber"; import MaskedInput from "../../ui/MaskedInput"; @@ -50,6 +50,12 @@ export const TypeInput: React.FC = ({ textarea.style.height = `${textarea.scrollHeight}px`; // Adjust height based on content } }; + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === "Enter") { + event.stopPropagation(); + event.preventDefault(); + } + }; useEffect(() => { if (type === "color") { meta.inputValue = value || ""; @@ -153,40 +159,6 @@ export const TypeInput: React.FC = ({ /> ); - return ( - <> -
- {Array.from({ length: 5 }, (_, index) => index + 1).map( - (number) => ( - - ) - )} -
- - ); break; case "color": return ( @@ -287,6 +259,7 @@ export const TypeInput: React.FC = ({ placeholder={placeholder || ""} value={formatCurrency(input.value)} type={"text"} + onKeyDown={handleKeyDown} onChange={(ev) => { const rawValue = ev.currentTarget.value .replace(/[^0-9,-]/g, "") @@ -328,6 +301,7 @@ export const TypeInput: React.FC = ({ <> )} - -
{ - if (input.ref) { - input.ref.click(); - } - }} - className="items-center flex text-base px-1 outline-none rounded cursor-pointer flex-row justify-center" - > -
- + {!disabled ? ( +
{ + if (input.ref) { + input.ref.click(); + } + }} + className="items-center flex text-base px-1 outline-none rounded cursor-pointer flex-row justify-center" + > +
+ +
+
+ Add File +
-
- Add File -
-
+ ) : ( +
-
+ )}
) : input.fase === "upload" ? ( diff --git a/components/partials/SidebarBetter.tsx b/components/partials/SidebarBetter.tsx index 12e50cd..520e300 100644 --- a/components/partials/SidebarBetter.tsx +++ b/components/partials/SidebarBetter.tsx @@ -128,7 +128,9 @@ const SidebarBetterTree: React.FC = ({ } `, mini - ? isActive + ? isParentActive + ? "bg-linear-sidebar-active text-white font-normal p-1 shadow-md w-[50px]" + : isActive ? !depth ? "bg-linear-sidebar-active text-white font-normal p-1 shadow-md" : " bg-layer text-primary font-bold p-1 " diff --git a/components/tablelist/TableList.tsx b/components/tablelist/TableList.tsx index 4b0bb22..0edeba7 100644 --- a/components/tablelist/TableList.tsx +++ b/components/tablelist/TableList.tsx @@ -80,6 +80,7 @@ export const TableList: React.FC = ({ selection: { all: false, partial: [] as any[], + data: [] as any[], }, renderRow: (row: any) => { setData((prev) => [...prev, row]); @@ -156,7 +157,6 @@ export const TableList: React.FC = ({ local.render(); fm.data[name] = local.data; fm.render(); - console.log(fm.data[name]); }, }; }); @@ -210,14 +210,14 @@ export const TableList: React.FC = ({ paging: 1, }); local.data = res; - cloneListFM(res); + if (mode === "form") cloneListFM(res); local.render(); - setData(res); + setData(local.data); } else { local.data = onLoad; - cloneListFM(onLoad); + if (mode === "form") cloneListFM(onLoad); local.render(); - setData(onLoad); + setData(local.data); } } setTimeout(() => { @@ -237,20 +237,34 @@ export const TableList: React.FC = ({ { id: "select", width: 10, - header: ({ table }) => ( - { - table.getToggleAllRowsSelectedHandler(); - const handler = table.getToggleAllRowsSelectedHandler(); - handler(e); // Pastikan ini memanggil fungsi handler yang benar - local.selection.all = !local.selection.all; - local.render(); - }} - /> - ), + header: ({ table }) => { + return ( + { + table.getToggleAllRowsSelectedHandler(); + const handler = table.getToggleAllRowsSelectedHandler(); + handler(e); // Pastikan ini memanggil fungsi handler yang benar + local.selection.all = !local.selection.all; + local.render(); + setTimeout(() => { + if (!table.getIsAllRowsSelected()) { + local.selection.all = false; + local.selection.partial = []; + local.selection.data = []; + local.render(); + } else { + local.selection.partial = local.data.map((e) => e?.id); + local.selection.data = local.data; + local.render(); + } + }, 25); + }} + /> + ); + }, cell: ({ row }) => { const findCheck = (row: any) => { if (row.getIsSelected()) return true; @@ -262,6 +276,7 @@ export const TableList: React.FC = ({
{ const handler = row.getToggleSelectedHandler(); @@ -272,6 +287,7 @@ export const TableList: React.FC = ({ : local.selection.partial.find((e) => e === data?.id); if (!checked) { local.selection.partial.push(data?.id); + local.selection.data.push(data); } else { if ( local.selection.partial.find((e) => e === data?.id) @@ -280,6 +296,9 @@ export const TableList: React.FC = ({ local.selection.partial.filter( (e: any) => e !== data?.id ); + local.selection.data = local.selection.data.filter( + (e: any) => e?.id !== data?.id + ); } local.selection.all = false; } @@ -674,6 +693,10 @@ export const TableList: React.FC = ({ tbl: local, fm_row: fm_row, onChange, + render: () => { + local.render(); + setData(local.data); + }, }; const head = column.find( (e: any) => diff --git a/components/tablelist/TableUI.tsx b/components/tablelist/TableUI.tsx index f76cb8b..6b43b6c 100644 --- a/components/tablelist/TableUI.tsx +++ b/components/tablelist/TableUI.tsx @@ -5,6 +5,7 @@ import { useLocal } from "@/lib/utils/use-local"; import get from "lodash.get"; import { TabHeaderBetter } from "../tablist/TabHeaderBetter"; import { getNumber } from "@/lib/utils/getNumber"; +import { BreadcrumbBetterLink } from "../ui/breadcrumb-link"; export const TableUI: React.FC = ({ name, column, @@ -27,6 +28,7 @@ export const TableUI: React.FC = ({ title, tab, onTab, + breadcrumb, }) => { const local = useLocal({ tab: get(tab, "[0].id"), @@ -34,8 +36,13 @@ export const TableUI: React.FC = ({ return (
-
- {title} +
+
{title}
+ {breadcrumb?.length ? ( + + ) : ( + <> + )}
diff --git a/components/ui/alert.tsx b/components/ui/alert.tsx index 930342c..00f3212 100644 --- a/components/ui/alert.tsx +++ b/components/ui/alert.tsx @@ -10,7 +10,6 @@ import { AlertDialogTitle, AlertDialogTrigger, } from "./alert-dialog"; -import { X } from "lucide-react"; export const Alert: FC = ({ type, @@ -35,7 +34,9 @@ export const Alert: FC = ({ ) : ( <> - Are you absolutely sure? + + Are you certain you want to continue? + {msg || message?.[type]} diff --git a/components/ui/button-link.tsx b/components/ui/button-link.tsx index d3a031e..8f81fc4 100644 --- a/components/ui/button-link.tsx +++ b/components/ui/button-link.tsx @@ -61,11 +61,12 @@ const ButtonBetter = React.forwardRef( const ButtonLink: FC = ({ className, children, + target, href, variant = "default", }) => { return ( - + {children} diff --git a/components/ui/button.tsx b/components/ui/button.tsx index d0627a9..d25a8d7 100644 --- a/components/ui/button.tsx +++ b/components/ui/button.tsx @@ -10,6 +10,7 @@ import { TooltipProvider, TooltipTrigger, } from "./tooltip"; +import { ButtonLink } from "./button-link"; const btn = cva( " text-white px-4 py-1.5 group active-menu-icon relative flex items-stretch justify-center p-0.5 text-center border border-transparent text-white enabled:hover:bg-cyan-800 rounded-md" @@ -50,6 +51,8 @@ export interface ButtonProps VariantProps { asChild?: boolean; tooltip?: any; + href?: string; + typeButton?: "button" | "container" | "tooltip"; } const ButtonBetter = React.forwardRef( @@ -65,18 +68,49 @@ const ButtonBetter = React.forwardRef( } ); const ButtonBetterTooltip = React.forwardRef( - ({ tooltip, className, variant, size, asChild = false, ...props }, ref) => { + ( + { + typeButton = "button", + tooltip, + href, + className, + variant, + size, + asChild = false, + ...props + }, + ref + ) => { const Comp = asChild ? Slot : "button"; if (tooltip) { return ( - +
+ {href ? ( + + {props.children} + + ) : typeButton === "container" ? ( + + ) : ( + + )} +

{tooltip}

@@ -85,6 +119,27 @@ const ButtonBetterTooltip = React.forwardRef(
); } + if (href) { + return ( + + {props.children} + + ); + } + if (typeButton === "container") { + return ( + + ); + } return ( ( ); } ); + const ButtonContainer: FC = ({ children, className, diff --git a/components/ui/tooltip-better.tsx b/components/ui/tooltip-better.tsx new file mode 100644 index 0000000..f8e6ca7 --- /dev/null +++ b/components/ui/tooltip-better.tsx @@ -0,0 +1,25 @@ +import { FC } from "react"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "./tooltip"; + +export const TooltipBetter: FC = ({ content, children }) => { + if (content) { + return ( + + + +
{children}
+
+ +

{content}

+
+
+
+ ); + } + return children; +}; diff --git a/utils/date.ts b/utils/date.ts index 113a35a..da49f8b 100644 --- a/utils/date.ts +++ b/utils/date.ts @@ -12,7 +12,6 @@ export const longDate = (date: string | Date) => { }; export const dayDate = (date: string | Date) => { - console.log({ date }); if (date instanceof Date || (typeof date === "string" && !empty(date))) { return day(date).format("DD MMMM YYYY"); } diff --git a/utils/getAccess.ts b/utils/getAccess.ts index 1e23f2b..2d99adf 100644 --- a/utils/getAccess.ts +++ b/utils/getAccess.ts @@ -1,5 +1,4 @@ import get from "lodash.get"; -import { get_user } from "./get_user"; import api from "./axios"; export const getAccess = (keys: string, data: any[]) => { @@ -15,6 +14,20 @@ export const getAccess = (keys: string, data: any[]) => { return false; }; +export const access = (keys: string) => { + const data = globalThis.userRole; + if (!Array.isArray(data) || !data?.length) return false; + for (const role of data) { + const permissionExists = role.permissions.some( + (permission: any) => get(permission, "name") === keys + ); + if (permissionExists) { + return true; + } + } + return false; +}; + export const userRoleMe = async (w?: boolean) => { let user = null as any; let data = null as any;