This commit is contained in:
rizky 2024-11-28 00:27:23 -07:00
parent d1174741b4
commit 913f1dc942
23 changed files with 192 additions and 75 deletions

View File

@ -43,11 +43,11 @@ const Week: React.FC<Props> = ({style}) => {
>
{style === "google" ? dayjs(`2022-11-${6 + (item + startDateModifier)}`)
.locale(i18n)
.format("dddd") : ucFirst(
.format(isMobile ? "dd" :"dddd") : ucFirst(
shortString(
dayjs(`2022-11-${6 + (item + startDateModifier)}`)
.locale(i18n)
.format("dddd")
.format(isMobile ? "dd" :"dddd")
),
)}

View File

@ -377,15 +377,6 @@ const Calendar: React.FC<Props> = ({
return onMark(day, date)
}
return <></>
if (new Date().getDate() === day)
return (
<div className="c-absolute c-inset-y-0 c-left-0 -c-translate-y-1/2 -c-translate-x-1/2">
<div className="c-w-full c-h-full c-flex c-flex-row c-items-center c-justif-center c-px-0.5">
!
</div>
</div>
);
return <></>
}}
/>
</>

View File

@ -145,7 +145,6 @@ export function getNumberOfDay(
let number = 0;
let startDateModifier = 0;
if (startWeekOn) {
switch (startWeekOn) {
case "mon":
@ -173,16 +172,7 @@ export function getNumberOfDay(
break;
}
}
isMobile ? [
"S",
"M",
"T",
"W",
"T",
"F",
"S",
]: [
const days = [
"Sunday",
"Monday",
"Tuesday",
@ -190,7 +180,8 @@ export function getNumberOfDay(
"Thursday",
"Friday",
"Saturday",
].forEach((item, index) => {
]
days.forEach((item, index) => {
if (item.includes(dayString)) {
number = (index + startDateModifier) % 7;
}

View File

@ -1,10 +1,10 @@
import { Toaster } from "lib/exports";
import { ReactNode, useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { editorFormWidth } from "../Form";
import { FMLocal } from "../typings";
import { createFm } from "./utils/create-fm";
import { DivForm } from "./utils/DivForm";
import { Toaster } from "lib/exports";
import { editorFormWidth } from "../Form";
export type BaseFormProps<T> = {
name: string;

View File

@ -60,7 +60,6 @@ export const FieldInput: FC<{
child: get(_item, "edit.props.child.value") as PrasiItem,
bottom: childsTableEdit.find((e) => e.name === "bottom") as PrasiItem,
};
console.log({ tableEdit });
table_edit = (
<TableEdit
on_init={() => {

View File

@ -9,10 +9,6 @@ export const Label: FC<{ field: FieldLocal; fm: FMLocal; arg: FieldProp }> = ({
const errors = fm.error.get(field.name);
const disabled =
typeof field.disabled === "function" ? field.disabled() : field.disabled;
useEffect(() => {
if (field.name === "complete_description")
console.log("log", field.required);
}, []);
const required =
typeof arg.required === "string"
? arg.required === "y"
@ -30,12 +26,12 @@ export const Label: FC<{ field: FieldLocal; fm: FMLocal; arg: FieldProp }> = ({
"c-mt-3 c-w-full c-justify-between"
)}
>
<div className="c-flex c-items-center">
<div className="c-flex c-flex-row c-items-center">
<span className={cx(errors.length > 0 && `c-text-red-600`)}>
{field.label}
</span>
{required && !disabled && (
<span className="c-text-red-600 c-mb-2 c-ml-1">
<span className="c-text-red-600 c-ml-1">
<svg
xmlns="http://www.w3.org/2000/svg"
width="12"

View File

@ -269,7 +269,7 @@ export const TableEdit: FC<{
<BaseForm is_form={false} data={row}>
{(form) => {
return (
<tr>
<tr className={cx("c-border-b ", idx !== value.length -1 ? "c-border-gray-300" : "" )}>
{columns.map((header) => {
return (
<td
@ -322,10 +322,11 @@ export const TableEdit: FC<{
ext_fm={{
add: (e: any) => {
if (Array.isArray(fm.data[name])) {
fm.data[name].push({});
fm.data[name].push({...e});
} else {
fm.data[name] = [{}];
fm.data[name] = [{...e}];
}
console.log("CEKK")
fm.render();
setTimeout(() => {
const last = Array.from(

View File

@ -0,0 +1,36 @@
import { FC } from "react"
import { FilePreview } from "./FilePreview";
import { Trash2 } from "lucide-react";
import { FMLocal } from "lib/exports";
export const PreviewAfterUpload: FC<{
fm: FMLocal, fieldName: string, local: any
}> = ({ fm, fieldName, local }) => {
return (
<div className="c-flex-grow c-flex-row c-flex c-w-full c-h-full c-items-stretch">
<div className="c-flex c-justify-between c-flex-1 c-p-1">
<FilePreview url={fm.data[fieldName] || ""} />
<div
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
if (confirm("Clear this file ?")) {
fm.data[fieldName] = null;
local.attachment = "";
local.render();
fm.render();
}
}}
className={cx(
"c-flex c-flex-row c-items-center c-border c-px-2 c-rounded c-cursor-pointer hover:c-bg-red-100"
)}
>
<Trash2 className="c-text-red-500 c-h-4 c-w-4" />
</div>
</div>
</div>
)
}

View File

@ -242,7 +242,7 @@ export const navigateLink = async (
if (prev_link) prev_link = prev_link + "+";
}
navigate(`${link.url}#lnk=${prev_link + vhash}${prm}`);
navigate(`${link.url}#lnk=${prev_link + vhash}${prm ? prm : ""}`);
return true;
}
};

View File

@ -12,6 +12,8 @@ export const FieldRadio: FC<{
list: [] as any[],
value: [] as any[],
});
const disabled =
typeof field.disabled === "function" ? field.disabled() : field.disabled;
useEffect(() => {
const callback = (res: any[]) => {
local.list = res;
@ -40,6 +42,7 @@ export const FieldRadio: FC<{
<div
className="flex items-center mb-4"
onClick={() => {
if(!disabled)
arg.opt_set_value({
fm,
name: field.name,

View File

@ -147,10 +147,10 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
fm.reload = async () => {
fm.status = isEditor ? "ready" : "loading";
fm.render();
let toastId = null as any;
if (sonar === "on" && !isEditor) {
toast.dismiss();
toast.loading(
toastId = toast.loading(
<>
<Loader2 className="c-h-4 c-w-4 c-animate-spin" />
Loading data...
@ -158,7 +158,6 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
{ dismissible: true }
);
}
let should_load = true;
if (isEditor) {
const item_id = props.item.id;
@ -204,7 +203,6 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
}
}
}
toast.dismiss();
if (fm.is_newly_created) {
@ -214,6 +212,11 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
fm.status = "ready";
fm.render();
setTimeout(() => {
toast.dismiss();
}, 2000)
};
fm.submit = async () => {
@ -289,7 +292,6 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
}
);
} else {
toastSuccess({ addNewText: lang.t("Add New") });
}
}

View File

@ -67,6 +67,5 @@ export const useField = (
}, []);
field.prop = arg as any;
return field;
};

View File

@ -95,12 +95,12 @@ export const Import: FC<{
clearInterval(interval);
resolve([]);
}
}, 100);
}, 50);
});
}
await task(list[n], n);
await sleep(100);
await sleep(50);
n++;
}
};

View File

@ -35,7 +35,7 @@ export const TLList: FC<{
) : (
<div
className={cx(
"c-absolute c-inset-0",
"list-inner c-absolute c-inset-0",
!isEditor &&
css`
@keyframes flasher {

View File

@ -40,7 +40,13 @@ import { OnRowClick } from "./utils/type";
let EMPTY_SET = new Set() as ReadonlySet<any>;
type SelectedRow = (arg: { row: any; rows: any[]; idx: any }) => boolean;
type SelectedRow = (arg: {
row: any;
rows: any[];
idx: any;
select?: boolean;
data?: any[];
}) => boolean;
type TableListProp = {
child: any;
PassProp: any;
@ -137,6 +143,7 @@ export const TableList: FC<TableListProp> = ({
el: null as null | HTMLDivElement,
width: 0,
height: 0,
selectedAllRows: false as boolean,
selectedRowIds: [] as (string | number)[],
pk: null as null | GFCol,
scrolled: false,
@ -468,9 +475,11 @@ export const TableList: FC<TableListProp> = ({
rows: data,
});
});
local.selectedAllRows = true;
local.render();
} else {
// jika tidak, maka local selected rows akan dikosongkan
local.selectedAllRows = false;
local.selectedRows = [];
local.render();
}
@ -494,6 +503,7 @@ export const TableList: FC<TableListProp> = ({
local.selectedRows = local.selectedRows.filter(
(data) => data.pk !== rowId
);
local.selectedAllRows = false;
local.render();
}
};
@ -610,8 +620,24 @@ export const TableList: FC<TableListProp> = ({
frozen: true,
renderHeaderCell(props) {
return (
<div>
{/* <CheckboxList value={false} on_click={on_click} /> */}
<div
className={cx(
css`
width: 100%;
height: 100%;
`,
"c-flex c-items-center c-justify-center"
)}
>
{isCheckbox ? (
<input
type="checkbox"
checked={local.selectedAllRows}
onChange={headerCheckboxClick}
/>
) : (
<></>
)}
</div>
);
},
@ -622,7 +648,29 @@ export const TableList: FC<TableListProp> = ({
tbl: local,
child,
});
if (isCheckbox) {
const isChecked = local.selectedRows.some(
(checked) => checked.pk === props.row.id
);
return (
<div
onClick={checkboxClick(props.row.id)}
className={cx(
css`
width: 100%;
height: 100%;
`,
"c-flex c-items-center c-justify-center"
)}
>
<input
className="c-pointer-events-none"
type="checkbox"
checked={local.selectedAllRows ? true : isChecked}
/>
</div>
);
}
return (
<PassProp
idx={props.rowIdx}
@ -908,10 +956,20 @@ export const TableList: FC<TableListProp> = ({
) {
return local.cached_row.get(props.row);
}
const isSelect = selected({
const isSelect = local.selectedAllRows
? true
: selected({
idx: props.rowIdx,
row: props.row,
rows: local.data,
select: local.selectedAllRows
? true
: local.selectedRows.some(
(checked) => checked.pk === props.row.id
),
data: local.selectedAllRows
? local.data
: local.selectedRows,
});
const child_row = (
<Row
@ -1008,23 +1066,29 @@ export const TableList: FC<TableListProp> = ({
};
const CheckboxList: FC<{
on_click: (e: any) => void;
checked?: boolean;
value?: boolean;
}> = ({ value, on_click }) => {
}> = ({ value, checked, on_click }) => {
const local = useLocal({
checked: false as any,
value: false as boolean,
});
useEffect(() => {
local.checked = checked;
local.render();
}, []);
return (
<div className={cx("c-flex c-items-center c-w-full c-flex-row")}>
<div className={cx(`c-flex c-flex-col c-space-y-1 c-p-0.5`)}>
<div
onClick={() => {
local.value = !local.value;
on_click(local.value);
local.checked = !local.checked;
on_click(typeof value === "boolean" ? !local.checked : value);
local.render();
}}
className="c-flex c-flex-row c-space-x-1 cursor-pointer c-items-center rounded-full p-0.5"
>
{local.value ? (
{local.checked ? (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"

View File

@ -17,6 +17,7 @@ export const toast = {
sonner.dismiss(t.id);
}
}
sonner.dismiss()
} else {
clearTimeout(timer.timeout);
timer.timeout = null;

View File

@ -144,7 +144,6 @@ export { get_user } from "./utils/get_user";
export { range_date } from "./utils/ranged_date";
export const _sum = sum;
export const _get = __get;
/** Generator */
export { generateFilter as generateFilter } from "lib/comps/filter/gen/gen-filter";
export { generateRelation } from "lib/comps/form/gen/gen-rel";
@ -197,7 +196,7 @@ export * from "lib/comps/ui/input";
export { ButtonUpload } from "lib/preset/profile/ButtonUpload";
export { Profile } from "lib/preset/profile/Profile";
export { generateProfile } from "lib/preset/profile/utils/generate";
export { formatTime, longDate, shortDate, timeAgo } from "lib/utils/date";
export { formatTime, longDate, shortDate, timeAgo, formatDay } from "lib/utils/date";
export { getBasename, getPathname } from "lib/utils/pathname";
export { formatMoney } from "lib/comps/form/field/type/TypeMoney";

View File

@ -3,6 +3,8 @@ import { useLocal } from "lib/utils/use-local";
import get from "lodash.get";
import { FC, useEffect, useRef } from "react";
import { IMenu, MenuProp } from "./utils/type-menu";
import { icons } from "app/icons";
import { FieldLoading } from "lib/exports";
// import { icon } from "../../..";
const local_default = {
@ -14,19 +16,19 @@ const local_default = {
pathname: "",
loading: false,
init: false,
ready: false,
menu: [] as any[],
};
type MLocal = typeof local_default & { render: () => void };
export const Menu: FC<MenuProp> = (props) => {
const imenu = props.menu;
let role = props.role;
role = props.on_init();
let menu = get(imenu, role) || [];
const ref = useRef<HTMLDivElement>(null);
const local = useLocal({ ...local_default }, ({ setDelayedRender }) => {
setDelayedRender(true);
});
const imenu = props.menu;
// useEffect(() => {
// }, []);
if (local.pathname !== getPathname()) {
local.pathname = getPathname();
}
@ -37,9 +39,30 @@ export const Menu: FC<MenuProp> = (props) => {
useEffect(() => {
local.mode = props.mode;
local.ready = false;
local.render();
if (typeof imenu === "function") {
const res = imenu();
if (res instanceof Promise) {
res.then((e) => {
local.menu = e;
local.render();
})
}else{
local.menu = res;
local.render();
}
} else {
let role = props.role;
role = props.on_init();
let menu = get(imenu, role) || [];
local.menu = menu;
}
local.ready = true;
local.render();
}, [props.mode]);
if (!local.ready) return <FieldLoading />;
return (
<div
className={cx("c-overflow-y-auto c-relative c-h-full c-w-full c-flex-1")}
@ -47,7 +70,7 @@ export const Menu: FC<MenuProp> = (props) => {
>
<div className="sidebar-menu c-absolute c-inset-0 c-flex c-flex-col c-flex-grow c-px-3 c-py-4 ">
<SideBar
data={menu}
data={local.menu}
local={local}
pm={props}
depth={0}
@ -88,6 +111,9 @@ export const SideBar: FC<{
pm,
};
const data: IMenu[] = (typeof _data[0] === "string" ? [_data] : _data) as any;
if (!data.length) {
return <></>;
}
useEffect(() => {
data.map((item) => {
const menu = {

View File

@ -4,7 +4,7 @@ export type IMenu = [string, any, string | IMenu[]];
export type MenuProp = {
role: string;
on_init: () => string;
menu: Array<Record<string, IMenu[]>>;
menu: Array<Record<string, IMenu[]>> | (() => Promise<any>);
PassProp: any;
child: ReactNode;
mode: "full" | "mini";
@ -12,7 +12,9 @@ export type MenuProp = {
style: "navbar" | "sidebar";
layout?: { current_menu: string; render: () => void };
on_load?: (on_done: (exec: () => void) => void) => void;
get_menu?: (mn: Array<Record<string, IMenu[]>>) => Array<Record<string, IMenu[]>>
get_menu?: (
mn: Array<Record<string, IMenu[]>>
) => Array<Record<string, IMenu[]>>;
};
export type MenuActive = {
data: any;

View File

@ -73,7 +73,6 @@ export const useServerRouter = <T extends ReturnType<typeof newServerRouter>>(
async handle(arg: ServerContext | SessionContext<any>) {
const { url, req, handle } = arg;
const found = findRoute(rou, undefined, url.pathname);
if (found) {
const route = found.data;

View File

@ -3,6 +3,13 @@ import relative from "dayjs/plugin/relativeTime";
day.extend(relative);
export const formatDay = (date: string | Date, mode: string) => {
if (date instanceof Date || typeof date === "string") {
return day(date).format(mode);
}
return "-";
};
export const longDate = (date: string | Date) => {
if (date instanceof Date || typeof date === "string") {
return day(date).format("DD MMM YYYY - hh:mm");
@ -23,6 +30,7 @@ export const timeAgo = (date: string | Date) => {
}
return "-";
};
export const formatTime = (date: string | Date) => {
if (date instanceof Date || typeof date === "string") {
return day(date).format("hh:mm");