update 13 files

This commit is contained in:
faisolavolut 2025-02-03 10:30:54 +07:00
parent d8404e219f
commit 95652f3f16
13 changed files with 191 additions and 89 deletions

View File

@ -120,9 +120,11 @@ export const ThumbPreview = ({
export const FilePreview = ({ export const FilePreview = ({
url, url,
disabled, disabled,
limit_name,
}: { }: {
url: any; url: any;
disabled?: boolean; disabled?: boolean;
limit_name?: number;
}) => { }) => {
let ural = url; let ural = url;
if (url instanceof File) { if (url instanceof File) {
@ -172,7 +174,8 @@ export const FilePreview = ({
const getFileNameWithoutExtension = (filename: string) => { const getFileNameWithoutExtension = (filename: string) => {
const parts = filename.split("."); const parts = filename.split(".");
parts.pop(); // Hapus bagian terakhir (ekstensi) 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 = const ura =
ural && ural.startsWith("blob:") ? getFileNameWithoutExtension(ural) : ural; ural && ural.startsWith("blob:") ? getFileNameWithoutExtension(ural) : ural;
@ -234,7 +237,6 @@ export const FilePreview = ({
onClick={() => { onClick={() => {
let _url: any = let _url: any =
url && url.startsWith("blob:") ? ura : siteurl(ura || ""); url && url.startsWith("blob:") ? ura : siteurl(ura || "");
console.log(_url);
window.open(_url, "_blank"); window.open(_url, "_blank");
}} }}
> >
@ -302,7 +304,6 @@ const getFileName = (url: string) => {
} }
const fileName = url.substring(url.lastIndexOf("/") + 1); const fileName = url.substring(url.lastIndexOf("/") + 1);
console.log({ fileName });
const dotIndex = fileName.lastIndexOf("."); const dotIndex = fileName.lastIndexOf(".");
const fullname = fileName; const fullname = fileName;
if (dotIndex === -1) { if (dotIndex === -1) {

View File

@ -1,6 +1,4 @@
import { useLocal } from "@/lib/utils/use-local";
import { Typeahead } from "./Typeahead"; import { Typeahead } from "./Typeahead";
import { useEffect } from "react";
export const TypeDropdown: React.FC<any> = ({ export const TypeDropdown: React.FC<any> = ({
required, required,
@ -45,7 +43,6 @@ export const TypeDropdown: React.FC<any> = ({
if (typeof onChange === "function" && item) { if (typeof onChange === "function" && item) {
onChange(item); onChange(item);
} }
console.log(fm.data[name]);
return item?.value || search; return item?.value || search;
}} }}
disabled={disabled} disabled={disabled}

View File

@ -5,7 +5,7 @@ import { Textarea } from "../../ui/text-area";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import tinycolor from "tinycolor2"; import tinycolor from "tinycolor2";
import { FieldColorPicker } from "../../ui/FieldColorPopover"; 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 { Rating } from "../../ui/ratings";
import { getNumber } from "@/lib/utils/getNumber"; import { getNumber } from "@/lib/utils/getNumber";
import MaskedInput from "../../ui/MaskedInput"; import MaskedInput from "../../ui/MaskedInput";
@ -50,6 +50,12 @@ export const TypeInput: React.FC<any> = ({
textarea.style.height = `${textarea.scrollHeight}px`; // Adjust height based on content textarea.style.height = `${textarea.scrollHeight}px`; // Adjust height based on content
} }
}; };
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === "Enter") {
event.stopPropagation();
event.preventDefault();
}
};
useEffect(() => { useEffect(() => {
if (type === "color") { if (type === "color") {
meta.inputValue = value || ""; meta.inputValue = value || "";
@ -153,40 +159,6 @@ export const TypeInput: React.FC<any> = ({
/> />
</div> </div>
); );
return (
<>
<div className="flex">
{Array.from({ length: 5 }, (_, index) => index + 1).map(
(number) => (
<button
key={number}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
handleClick(number);
}}
onMouseEnter={() => setHover(number)} // Set nilai hover saat mouse masuk
onMouseLeave={() => setHover(number)} // Reset nilai hover saat mouse keluar
className={cx(
"focus:outline-none px-0.5",
disabled ? "" : "transition-transform duration-200"
)}
style={{
transform:
hover === number && !disabled ? "scale(1.2)" : "scale(1)",
}}
>
{hover >= number || rating >= number ? (
<FaStar className="text-yellow-400" /> // Star yang diisi (fill)
) : (
<FaRegStar className="text-gray-400" /> // Star yang kosong (outline)
)}
</button>
)
)}
</div>
</>
);
break; break;
case "color": case "color":
return ( return (
@ -287,6 +259,7 @@ export const TypeInput: React.FC<any> = ({
placeholder={placeholder || ""} placeholder={placeholder || ""}
value={formatCurrency(input.value)} value={formatCurrency(input.value)}
type={"text"} type={"text"}
onKeyDown={handleKeyDown}
onChange={(ev) => { onChange={(ev) => {
const rawValue = ev.currentTarget.value const rawValue = ev.currentTarget.value
.replace(/[^0-9,-]/g, "") .replace(/[^0-9,-]/g, "")
@ -328,6 +301,7 @@ export const TypeInput: React.FC<any> = ({
<> <>
<Input <Input
id={name} id={name}
onKeyDown={handleKeyDown}
name={name} name={name}
className={cx( className={cx(
"text-sm", "text-sm",

View File

@ -172,7 +172,7 @@ export const FieldUploadSingle: FC<{
)} )}
/> />
)} )}
{!disabled ? (
<div <div
onClick={() => { onClick={() => {
if (input.ref) { if (input.ref) {
@ -188,6 +188,9 @@ export const FieldUploadSingle: FC<{
Add File Add File
</div> </div>
</div> </div>
) : (
<div className="flex flex-row items-center px-1.5 text-sm">-</div>
)}
</div> </div>
</> </>
) : input.fase === "upload" ? ( ) : input.fase === "upload" ? (

View File

@ -128,7 +128,9 @@ const SidebarBetterTree: React.FC<TreeMenuProps> = ({
} }
`, `,
mini mini
? isActive ? isParentActive
? "bg-linear-sidebar-active text-white font-normal p-1 shadow-md w-[50px]"
: isActive
? !depth ? !depth
? "bg-linear-sidebar-active text-white font-normal p-1 shadow-md" ? "bg-linear-sidebar-active text-white font-normal p-1 shadow-md"
: " bg-layer text-primary font-bold p-1 " : " bg-layer text-primary font-bold p-1 "

View File

@ -80,6 +80,7 @@ export const TableList: React.FC<any> = ({
selection: { selection: {
all: false, all: false,
partial: [] as any[], partial: [] as any[],
data: [] as any[],
}, },
renderRow: (row: any) => { renderRow: (row: any) => {
setData((prev) => [...prev, row]); setData((prev) => [...prev, row]);
@ -156,7 +157,6 @@ export const TableList: React.FC<any> = ({
local.render(); local.render();
fm.data[name] = local.data; fm.data[name] = local.data;
fm.render(); fm.render();
console.log(fm.data[name]);
}, },
}; };
}); });
@ -210,14 +210,14 @@ export const TableList: React.FC<any> = ({
paging: 1, paging: 1,
}); });
local.data = res; local.data = res;
cloneListFM(res); if (mode === "form") cloneListFM(res);
local.render(); local.render();
setData(res); setData(local.data);
} else { } else {
local.data = onLoad; local.data = onLoad;
cloneListFM(onLoad); if (mode === "form") cloneListFM(onLoad);
local.render(); local.render();
setData(onLoad); setData(local.data);
} }
} }
setTimeout(() => { setTimeout(() => {
@ -237,10 +237,11 @@ export const TableList: React.FC<any> = ({
{ {
id: "select", id: "select",
width: 10, width: 10,
header: ({ table }) => ( header: ({ table }) => {
return (
<Checkbox <Checkbox
id="terms" id="terms"
className="text-white" className="text-primary bg-white data-[state=checked]:bg-white data-[state=checked]:text-primary"
checked={table.getIsAllRowsSelected()} checked={table.getIsAllRowsSelected()}
onClick={(e) => { onClick={(e) => {
table.getToggleAllRowsSelectedHandler(); table.getToggleAllRowsSelectedHandler();
@ -248,9 +249,22 @@ export const TableList: React.FC<any> = ({
handler(e); // Pastikan ini memanggil fungsi handler yang benar handler(e); // Pastikan ini memanggil fungsi handler yang benar
local.selection.all = !local.selection.all; local.selection.all = !local.selection.all;
local.render(); 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 }) => { cell: ({ row }) => {
const findCheck = (row: any) => { const findCheck = (row: any) => {
if (row.getIsSelected()) return true; if (row.getIsSelected()) return true;
@ -262,6 +276,7 @@ export const TableList: React.FC<any> = ({
<div className="px-0.5 items-center justify-center flex flex-row"> <div className="px-0.5 items-center justify-center flex flex-row">
<Checkbox <Checkbox
id="terms" id="terms"
className="border border-primary"
checked={findCheck(row)} checked={findCheck(row)}
onClick={(e) => { onClick={(e) => {
const handler = row.getToggleSelectedHandler(); const handler = row.getToggleSelectedHandler();
@ -272,6 +287,7 @@ export const TableList: React.FC<any> = ({
: local.selection.partial.find((e) => e === data?.id); : local.selection.partial.find((e) => e === data?.id);
if (!checked) { if (!checked) {
local.selection.partial.push(data?.id); local.selection.partial.push(data?.id);
local.selection.data.push(data);
} else { } else {
if ( if (
local.selection.partial.find((e) => e === data?.id) local.selection.partial.find((e) => e === data?.id)
@ -280,6 +296,9 @@ export const TableList: React.FC<any> = ({
local.selection.partial.filter( local.selection.partial.filter(
(e: any) => e !== data?.id (e: any) => e !== data?.id
); );
local.selection.data = local.selection.data.filter(
(e: any) => e?.id !== data?.id
);
} }
local.selection.all = false; local.selection.all = false;
} }
@ -674,6 +693,10 @@ export const TableList: React.FC<any> = ({
tbl: local, tbl: local,
fm_row: fm_row, fm_row: fm_row,
onChange, onChange,
render: () => {
local.render();
setData(local.data);
},
}; };
const head = column.find( const head = column.find(
(e: any) => (e: any) =>

View File

@ -5,6 +5,7 @@ import { useLocal } from "@/lib/utils/use-local";
import get from "lodash.get"; import get from "lodash.get";
import { TabHeaderBetter } from "../tablist/TabHeaderBetter"; import { TabHeaderBetter } from "../tablist/TabHeaderBetter";
import { getNumber } from "@/lib/utils/getNumber"; import { getNumber } from "@/lib/utils/getNumber";
import { BreadcrumbBetterLink } from "../ui/breadcrumb-link";
export const TableUI: React.FC<any> = ({ export const TableUI: React.FC<any> = ({
name, name,
column, column,
@ -27,6 +28,7 @@ export const TableUI: React.FC<any> = ({
title, title,
tab, tab,
onTab, onTab,
breadcrumb,
}) => { }) => {
const local = useLocal({ const local = useLocal({
tab: get(tab, "[0].id"), tab: get(tab, "[0].id"),
@ -34,8 +36,13 @@ export const TableUI: React.FC<any> = ({
return ( return (
<div className="flex flex-col flex-grow"> <div className="flex flex-col flex-grow">
<div className="w-full flex flex-row p-4 py-6 pr-6 pl-3 text-2xl font-bold"> <div className="w-full p-4 py-6 pr-6 pl-3 ">
{title} <div className="flex flex-row text-2xl font-bold">{title}</div>
{breadcrumb?.length ? (
<BreadcrumbBetterLink data={breadcrumb} />
) : (
<></>
)}
</div> </div>
<div className="flex flex-col flex-grow bg-card-layer rounded-lg border border-gray-300 shadow-md shadow-gray-300 overflow-hidden"> <div className="flex flex-col flex-grow bg-card-layer rounded-lg border border-gray-300 shadow-md shadow-gray-300 overflow-hidden">
<div className="flex flex-col flex-grow"> <div className="flex flex-col flex-grow">

View File

@ -10,7 +10,6 @@ import {
AlertDialogTitle, AlertDialogTitle,
AlertDialogTrigger, AlertDialogTrigger,
} from "./alert-dialog"; } from "./alert-dialog";
import { X } from "lucide-react";
export const Alert: FC<any> = ({ export const Alert: FC<any> = ({
type, type,
@ -35,7 +34,9 @@ export const Alert: FC<any> = ({
) : ( ) : (
<> <>
<AlertDialogHeader> <AlertDialogHeader>
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle> <AlertDialogTitle>
Are you certain you want to continue?
</AlertDialogTitle>
<AlertDialogDescription> <AlertDialogDescription>
{msg || message?.[type]} {msg || message?.[type]}
</AlertDialogDescription> </AlertDialogDescription>

View File

@ -61,11 +61,12 @@ const ButtonBetter = React.forwardRef<HTMLButtonElement, ButtonProps>(
const ButtonLink: FC<any> = ({ const ButtonLink: FC<any> = ({
className, className,
children, children,
target,
href, href,
variant = "default", variant = "default",
}) => { }) => {
return ( return (
<Link href={href}> <Link href={href} target={target}>
<ButtonBetter className={cx(className)} variant={variant}> <ButtonBetter className={cx(className)} variant={variant}>
{children} {children}
</ButtonBetter> </ButtonBetter>

View File

@ -10,6 +10,7 @@ import {
TooltipProvider, TooltipProvider,
TooltipTrigger, TooltipTrigger,
} from "./tooltip"; } from "./tooltip";
import { ButtonLink } from "./button-link";
const btn = cva( 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" " 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<typeof buttonVariants> { VariantProps<typeof buttonVariants> {
asChild?: boolean; asChild?: boolean;
tooltip?: any; tooltip?: any;
href?: string;
typeButton?: "button" | "container" | "tooltip";
} }
const ButtonBetter = React.forwardRef<HTMLButtonElement, ButtonProps>( const ButtonBetter = React.forwardRef<HTMLButtonElement, ButtonProps>(
@ -65,18 +68,49 @@ const ButtonBetter = React.forwardRef<HTMLButtonElement, ButtonProps>(
} }
); );
const ButtonBetterTooltip = React.forwardRef<HTMLButtonElement, ButtonProps>( const ButtonBetterTooltip = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ tooltip, className, variant, size, asChild = false, ...props }, ref) => { (
{
typeButton = "button",
tooltip,
href,
className,
variant,
size,
asChild = false,
...props
},
ref
) => {
const Comp = asChild ? Slot : "button"; const Comp = asChild ? Slot : "button";
if (tooltip) { if (tooltip) {
return ( return (
<TooltipProvider> <TooltipProvider>
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<div className="flex flex-row items-center">
{href ? (
<ButtonLink
href={href}
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
variant={variant}
>
{props.children}
</ButtonLink>
) : typeButton === "container" ? (
<ButtonContainer
className={className}
variant={variant}
children={props.children}
/>
) : (
<Comp <Comp
className={cn(buttonVariants({ variant, size, className }))} className={cn(buttonVariants({ variant, size, className }))}
ref={ref} ref={ref}
{...props} {...props}
/> />
)}
</div>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent className="bg-linear-sidebar-active text-white border border-primary shadow-md transition-all "> <TooltipContent className="bg-linear-sidebar-active text-white border border-primary shadow-md transition-all ">
<p>{tooltip}</p> <p>{tooltip}</p>
@ -85,6 +119,27 @@ const ButtonBetterTooltip = React.forwardRef<HTMLButtonElement, ButtonProps>(
</TooltipProvider> </TooltipProvider>
); );
} }
if (href) {
return (
<ButtonLink
href={href}
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
variant={variant}
>
{props.children}
</ButtonLink>
);
}
if (typeButton === "container") {
return (
<ButtonContainer
className={className}
variant={variant}
children={props.children}
/>
);
}
return ( return (
<Comp <Comp
className={cn(buttonVariants({ variant, size, className }))} className={cn(buttonVariants({ variant, size, className }))}
@ -94,6 +149,7 @@ const ButtonBetterTooltip = React.forwardRef<HTMLButtonElement, ButtonProps>(
); );
} }
); );
const ButtonContainer: FC<any> = ({ const ButtonContainer: FC<any> = ({
children, children,
className, className,

View File

@ -0,0 +1,25 @@
import { FC } from "react";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "./tooltip";
export const TooltipBetter: FC<any> = ({ content, children }) => {
if (content) {
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<div className="w-full flex flex-grow flex-row">{children}</div>
</TooltipTrigger>
<TooltipContent className="bg-linear-sidebar-active text-white border border-primary shadow-md transition-all ">
<p>{content}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}
return children;
};

View File

@ -12,7 +12,6 @@ export const longDate = (date: string | Date) => {
}; };
export const dayDate = (date: string | Date) => { export const dayDate = (date: string | Date) => {
console.log({ date });
if (date instanceof Date || (typeof date === "string" && !empty(date))) { if (date instanceof Date || (typeof date === "string" && !empty(date))) {
return day(date).format("DD MMMM YYYY"); return day(date).format("DD MMMM YYYY");
} }

View File

@ -1,5 +1,4 @@
import get from "lodash.get"; import get from "lodash.get";
import { get_user } from "./get_user";
import api from "./axios"; import api from "./axios";
export const getAccess = (keys: string, data: any[]) => { export const getAccess = (keys: string, data: any[]) => {
@ -15,6 +14,20 @@ export const getAccess = (keys: string, data: any[]) => {
return false; 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) => { export const userRoleMe = async (w?: boolean) => {
let user = null as any; let user = null as any;
let data = null as any; let data = null as any;