checkpoint
This commit is contained in:
parent
fff47ee40a
commit
61845dc62b
|
|
@ -27,6 +27,7 @@ interface Props {
|
||||||
onClickDay: (day: number) => void;
|
onClickDay: (day: number) => void;
|
||||||
onClickNextDays: (day: number) => void;
|
onClickNextDays: (day: number) => void;
|
||||||
onIcon?: (day: number, date: Date) => any;
|
onIcon?: (day: number, date: Date) => any;
|
||||||
|
style?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Days: React.FC<Props> = ({
|
const Days: React.FC<Props> = ({
|
||||||
|
|
@ -35,6 +36,7 @@ const Days: React.FC<Props> = ({
|
||||||
onClickDay,
|
onClickDay,
|
||||||
onClickNextDays,
|
onClickNextDays,
|
||||||
onIcon,
|
onIcon,
|
||||||
|
style,
|
||||||
}) => {
|
}) => {
|
||||||
// Contexts
|
// Contexts
|
||||||
const {
|
const {
|
||||||
|
|
@ -241,13 +243,18 @@ const Days: React.FC<Props> = ({
|
||||||
|
|
||||||
const buttonClass = useCallback(
|
const buttonClass = useCallback(
|
||||||
(day: number, type: "current" | "next" | "previous") => {
|
(day: number, type: "current" | "next" | "previous") => {
|
||||||
const baseClass =
|
let baseClass = `calender-day c-flex c-items-center c-justify-center ${
|
||||||
"c-flex c-items-center c-justify-center c-w-12 c-h-12 lg:c-w-10 lg:c-h-10 c-relative";
|
style === "google"
|
||||||
|
? " c-w-6 c-h-6 c-m-1"
|
||||||
|
: "c-w-12 c-h-12 lg:c-w-10 lg:c-h-10"
|
||||||
|
} c-relative`;
|
||||||
if (type === "current") {
|
if (type === "current") {
|
||||||
return cn(
|
return cn(
|
||||||
baseClass,
|
baseClass,
|
||||||
!activeDateData(day).active
|
!activeDateData(day).active
|
||||||
? hoverClassByDay(day)
|
? hoverClassByDay(day)
|
||||||
|
: style === "google"
|
||||||
|
? ""
|
||||||
: activeDateData(day).className,
|
: activeDateData(day).className,
|
||||||
isDateDisabled(day, type) && "c-text-gray-400 c-cursor-not-allowed"
|
isDateDisabled(day, type) && "c-text-gray-400 c-cursor-not-allowed"
|
||||||
);
|
);
|
||||||
|
|
@ -403,8 +410,49 @@ const Days: React.FC<Props> = ({
|
||||||
return typeof onIcon === "function" ? onIcon(day, res) : null;
|
return typeof onIcon === "function" ? onIcon(day, res) : null;
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="c-grid c-grid-cols-7 c-gap-y-0.5 c-my-1">
|
<div
|
||||||
|
className={cx(
|
||||||
|
"calender-days c-grid c-grid-cols-7 c-gap-y-0.5 c-my-1",
|
||||||
|
css`
|
||||||
|
grid-template-columns: repeat(
|
||||||
|
auto-fit,
|
||||||
|
minmax(0px, 1fr)
|
||||||
|
); /* Grid fleksibel */
|
||||||
|
|
||||||
|
.calender-grid {
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
>
|
||||||
{calendarData.days.previous.map((item, index) => (
|
{calendarData.days.previous.map((item, index) => (
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
"calender-grid c-flex c-flex-row",
|
||||||
|
style === "google" ? "hover:c-bg-gray-100 c-cursor-pointer" : ""
|
||||||
|
)}
|
||||||
|
onClick={() => {
|
||||||
|
if (style === "google") handleClickDay(item, "previous");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="c-flex c-flex-col c-flex-grow calender-day-wrap">
|
||||||
|
{style === "google" ? (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
key={index}
|
||||||
|
disabled={isDateDisabled(item, "previous")}
|
||||||
|
className={`${buttonClass(item, "previous")}`}
|
||||||
|
onMouseOver={() => {
|
||||||
|
hoverDay(item, "previous");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="c-relative">{item}</span>
|
||||||
|
</button>
|
||||||
|
<div>{load_marker(item, "previous")}</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
key={index}
|
key={index}
|
||||||
|
|
@ -420,17 +468,50 @@ const Days: React.FC<Props> = ({
|
||||||
{load_marker(item, "previous")}
|
{load_marker(item, "previous")}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{calendarData.days.current.map((item, index) => (
|
{calendarData.days.current.map((item, index) => (
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
"calender-grid c-flex c-flex-row",
|
||||||
|
style === "google"
|
||||||
|
? activeDateData(item).active
|
||||||
|
? "c-bg-blue-200/75 c-ring-1 c-cursor-pointer"
|
||||||
|
: "hover:c-bg-gray-100 c-cursor-pointer"
|
||||||
|
: ""
|
||||||
|
)}
|
||||||
|
onClick={() => {
|
||||||
|
if (style === "google") handleClickDay(item, "current");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="c-flex c-flex-col c-flex-grow calender-day-wrap">
|
||||||
|
{style === "google" ? (
|
||||||
|
<>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
key={index}
|
key={index}
|
||||||
disabled={isDateDisabled(item, "current")}
|
disabled={isDateDisabled(item, "current")}
|
||||||
className={cx(
|
className={`${buttonClass(item, "current")}`}
|
||||||
`${buttonClass(item, "current")}`,
|
// onClick={() => handleClickDay(item, "current")}
|
||||||
item === 1 && "highlight"
|
onMouseOver={() => {
|
||||||
)}
|
hoverDay(item, "current");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="c-relative">{item}</span>
|
||||||
|
</button>
|
||||||
|
<div>{load_marker(item, "current")}</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
key={index}
|
||||||
|
disabled={isDateDisabled(item, "current")}
|
||||||
|
className={`${buttonClass(item, "current")}`}
|
||||||
onClick={() => handleClickDay(item, "current")}
|
onClick={() => handleClickDay(item, "current")}
|
||||||
onMouseOver={() => {
|
onMouseOver={() => {
|
||||||
hoverDay(item, "current");
|
hoverDay(item, "current");
|
||||||
|
|
@ -441,9 +522,40 @@ const Days: React.FC<Props> = ({
|
||||||
{load_marker(item, "current")}
|
{load_marker(item, "current")}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{calendarData.days.next.map((item, index) => (
|
{calendarData.days.next.map((item, index) => (
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
"calender-grid c-flex c-flex-row",
|
||||||
|
style === "google" ? "hover:c-bg-gray-100 c-cursor-pointer" : ""
|
||||||
|
)}
|
||||||
|
onClick={() => {
|
||||||
|
if (style === "google") handleClickDay(item, "next");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="c-flex c-flex-col c-flex-grow calender-day-wrap">
|
||||||
|
{style === "google" ? (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
key={index}
|
||||||
|
disabled={isDateDisabled(item, "next")}
|
||||||
|
className={`${buttonClass(item, "next")}`}
|
||||||
|
onMouseOver={() => {
|
||||||
|
hoverDay(item, "next");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="c-relative">{item}</span>
|
||||||
|
</button>
|
||||||
|
<div>{load_marker(item, "next")}</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
key={index}
|
key={index}
|
||||||
|
|
@ -459,6 +571,10 @@ const Days: React.FC<Props> = ({
|
||||||
{load_marker(item, "next")}
|
{load_marker(item, "next")}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,10 @@ import { RoundedButton } from "../utils";
|
||||||
interface Props {
|
interface Props {
|
||||||
currentMonth: number;
|
currentMonth: number;
|
||||||
clickMonth: (month: number) => void;
|
clickMonth: (month: number) => void;
|
||||||
|
style?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const Months: React.FC<Props> = ({ currentMonth, clickMonth }) => {
|
const Months: React.FC<Props> = ({ currentMonth, clickMonth, style }) => {
|
||||||
const { i18n } = useContext(DatepickerContext);
|
const { i18n } = useContext(DatepickerContext);
|
||||||
loadLanguageModule(i18n);
|
loadLanguageModule(i18n);
|
||||||
return (
|
return (
|
||||||
|
|
@ -25,7 +26,7 @@ const Months: React.FC<Props> = ({ currentMonth, clickMonth }) => {
|
||||||
}}
|
}}
|
||||||
active={currentMonth === item}
|
active={currentMonth === item}
|
||||||
>
|
>
|
||||||
<>{dayjs(`2022-${item}-01`).locale(i18n).format("MMM")}</>
|
<>{dayjs(`2022-${item}-01`).locale(i18n).format(style === "google" ? "MMMM" :"MMM")}</>
|
||||||
</RoundedButton>
|
</RoundedButton>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,15 @@ import React, { useContext, useMemo } from "react";
|
||||||
import { DAYS } from "../../constants";
|
import { DAYS } from "../../constants";
|
||||||
import DatepickerContext from "../../contexts/DatepickerContext";
|
import DatepickerContext from "../../contexts/DatepickerContext";
|
||||||
import { loadLanguageModule, shortString, ucFirst } from "../../helpers";
|
import { loadLanguageModule, shortString, ucFirst } from "../../helpers";
|
||||||
|
interface Props {
|
||||||
const Week: React.FC = () => {
|
style?: string
|
||||||
|
}
|
||||||
|
const Week: React.FC<Props> = ({style}) => {
|
||||||
const { i18n, startWeekOn } = useContext(DatepickerContext);
|
const { i18n, startWeekOn } = useContext(DatepickerContext);
|
||||||
loadLanguageModule(i18n);
|
loadLanguageModule(i18n);
|
||||||
const startDateModifier = useMemo(() => {
|
const startDateModifier = useMemo(() => {
|
||||||
|
console.log(startWeekOn);
|
||||||
|
|
||||||
if (startWeekOn) {
|
if (startWeekOn) {
|
||||||
switch (startWeekOn) {
|
switch (startWeekOn) {
|
||||||
case "mon":
|
case "mon":
|
||||||
|
|
@ -33,18 +37,21 @@ const Week: React.FC = () => {
|
||||||
}, [startWeekOn]);
|
}, [startWeekOn]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className=" c-grid c-grid-cols-7 c-border-b c-border-gray-300 dark:c-border-gray-700 c-py-2">
|
<div className="calender-week c-grid c-grid-cols-7 c-border-b c-border-gray-300 dark:c-border-gray-700 c-py-2">
|
||||||
{DAYS.map((item) => (
|
{DAYS.map((item) => (
|
||||||
<div
|
<div
|
||||||
key={item}
|
key={item}
|
||||||
className="c-tracking-wide c-text-gray-500 c-text-center"
|
className="c-tracking-wide c-text-gray-500 c-text-center"
|
||||||
>
|
>
|
||||||
{ucFirst(
|
{style === "google" ? dayjs(`2022-11-${6 + (item + startDateModifier)}`)
|
||||||
|
.locale(i18n)
|
||||||
|
.format("dddd") : ucFirst(
|
||||||
shortString(
|
shortString(
|
||||||
dayjs(`2022-11-${6 + (item + startDateModifier)}`)
|
dayjs(`2022-11-${6 + (item + startDateModifier)}`)
|
||||||
.locale(i18n)
|
.locale(i18n)
|
||||||
.format("ddd")
|
.format("dddd")
|
||||||
)
|
),
|
||||||
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ interface Props {
|
||||||
changeYear: (year: number) => void;
|
changeYear: (year: number) => void;
|
||||||
mode?: "monthly" | "daily";
|
mode?: "monthly" | "daily";
|
||||||
onMark?: (day: number, date: Date) => any;
|
onMark?: (day: number, date: Date) => any;
|
||||||
|
style?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const Calendar: React.FC<Props> = ({
|
const Calendar: React.FC<Props> = ({
|
||||||
|
|
@ -57,6 +58,7 @@ const Calendar: React.FC<Props> = ({
|
||||||
changeYear,
|
changeYear,
|
||||||
onMark,
|
onMark,
|
||||||
mode = "daily",
|
mode = "daily",
|
||||||
|
style = "prasi"
|
||||||
}) => {
|
}) => {
|
||||||
// Contexts
|
// Contexts
|
||||||
const {
|
const {
|
||||||
|
|
@ -266,7 +268,7 @@ const Calendar: React.FC<Props> = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="c-w-full md:c-w-[296px] md:c-min-w-[296px]">
|
<div className="c-w-full md:c-w-[296px] md:c-min-w-[296px] calender">
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
"c-flex c-items-stretch c-space-x-1.5 c-px-2 c-py-1.5",
|
"c-flex c-items-stretch c-space-x-1.5 c-px-2 c-py-1.5",
|
||||||
|
|
@ -304,7 +306,7 @@ const Calendar: React.FC<Props> = ({
|
||||||
hideYears();
|
hideYears();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<>{calendarData.date.locale(i18n).format("MMM")}</>
|
<>{calendarData.date.locale(i18n).format(style === "google" ? "MMMM" :"MMM")}</>
|
||||||
</RoundedButton>
|
</RoundedButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -341,11 +343,12 @@ const Calendar: React.FC<Props> = ({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={cx("c-mt-0.5 c-min-h-[285px]")}>
|
<div className={cx("c-mt-0.5 c-min-h-[285px] calender-body")}>
|
||||||
{showMonths && (
|
{showMonths && (
|
||||||
<Months
|
<Months
|
||||||
currentMonth={calendarData.date.month() + 1}
|
currentMonth={calendarData.date.month() + 1}
|
||||||
clickMonth={clickMonth}
|
clickMonth={clickMonth}
|
||||||
|
style={style}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
@ -361,13 +364,14 @@ const Calendar: React.FC<Props> = ({
|
||||||
|
|
||||||
{!showMonths && !showYears && (
|
{!showMonths && !showYears && (
|
||||||
<>
|
<>
|
||||||
<Week />
|
<Week style={style}/>
|
||||||
|
|
||||||
<Days
|
<Days
|
||||||
calendarData={calendarData}
|
calendarData={calendarData}
|
||||||
onClickPreviousDays={clickPreviousDays}
|
onClickPreviousDays={clickPreviousDays}
|
||||||
onClickDay={clickDay}
|
onClickDay={clickDay}
|
||||||
onClickNextDays={clickNextDays}
|
onClickNextDays={clickNextDays}
|
||||||
|
style={style}
|
||||||
onIcon={(day, date) => {
|
onIcon={(day, date) => {
|
||||||
if(typeof onMark === "function"){
|
if(typeof onMark === "function"){
|
||||||
return onMark(day, date)
|
return onMark(day, date)
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,15 @@ export function getNumberOfDay(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[
|
isMobile ? [
|
||||||
|
"S",
|
||||||
|
"M",
|
||||||
|
"T",
|
||||||
|
"W",
|
||||||
|
"T",
|
||||||
|
"F",
|
||||||
|
"S",
|
||||||
|
]: [
|
||||||
"Sunday",
|
"Sunday",
|
||||||
"Monday",
|
"Monday",
|
||||||
"Tuesday",
|
"Tuesday",
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,8 @@ export interface DatepickerType {
|
||||||
popoverDirection?: PopoverDirectionType;
|
popoverDirection?: PopoverDirectionType;
|
||||||
mode?: "daily" | "monthly";
|
mode?: "daily" | "monthly";
|
||||||
onMark?: (day: number, date: Date) => any;
|
onMark?: (day: number, date: Date) => any;
|
||||||
onLoad?: () => Promise<void>
|
onLoad?: (day: any) => Promise<void>;
|
||||||
|
style?: "google" | "prasi"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ export const QrLabel: FC<{
|
||||||
fgcolor: string,
|
fgcolor: string,
|
||||||
size: number
|
size: number
|
||||||
}> = ({ value, bgcolor, fgcolor, size }) => {
|
}> = ({ value, bgcolor, fgcolor, size }) => {
|
||||||
|
console.log(value);
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<QRCode value={value} size={size}
|
<QRCode value={value} size={size}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
import { FC, useEffect, useRef, useState } from "react";
|
||||||
|
import { default as ScanQr } from "qr-scanner";
|
||||||
|
import { QrReaderType } from "./typings";
|
||||||
|
|
||||||
|
export const QrScanner: FC<{ onSuccess: (result: any) => {} }> = ({ onSuccess }) => {
|
||||||
|
const w = window as any;
|
||||||
|
const scanner = useRef<ScanQr>();
|
||||||
|
const videoEl = useRef<HTMLVideoElement>(null);
|
||||||
|
const qrBoxEl = useRef<HTMLDivElement>(null);
|
||||||
|
const [qrOn, setQrOn] = useState<boolean>(true);
|
||||||
|
const [scannedResult, setScannedResult] = useState<string | undefined>("");
|
||||||
|
const [hasScanned, setHasScanned] = useState<boolean>(false);
|
||||||
|
const onScanSuccess = (result: ScanQr.ScanResult) => {
|
||||||
|
if (!hasScanned) {
|
||||||
|
console.log(result);
|
||||||
|
setScannedResult(result?.data);
|
||||||
|
setHasScanned(true);
|
||||||
|
scanner.current?.stop();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
onSuccess(result?.data);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const onScanFail = (err: string | Error) => {
|
||||||
|
console.log("failed", err);
|
||||||
|
};
|
||||||
|
const openCameraScanner = () => {
|
||||||
|
if (w.AndroidBridge && w.AndroidBridge.openCameraScanner) {
|
||||||
|
w.AndroidBridge.openCameraScanner();
|
||||||
|
} else {
|
||||||
|
console.error("AndroidBridge or openCameraScanner function is not available.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (w.AndroidBridge && w.AndroidBridge.openCameraScanner) {
|
||||||
|
useEffect(() => {
|
||||||
|
openCameraScanner();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
w.onScannerResult = (scannedData: string) => {
|
||||||
|
console.log('Scanned Data:', scannedData);
|
||||||
|
onSuccess(scannedData);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>QR/Barcode Scanner</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.log("Bridge not found");
|
||||||
|
useEffect(() => {
|
||||||
|
if (videoEl?.current && !scanner.current) {
|
||||||
|
scanner.current = new ScanQr(videoEl?.current, onScanSuccess, {
|
||||||
|
onDecodeError: onScanFail,
|
||||||
|
preferredCamera: "environment",
|
||||||
|
highlightScanRegion: true,
|
||||||
|
highlightCodeOutline: true,
|
||||||
|
overlay: qrBoxEl?.current || undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
scanner?.current
|
||||||
|
?.start()
|
||||||
|
.then(() => setQrOn(true))
|
||||||
|
.catch((err) => {
|
||||||
|
if (err) setQrOn(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (!videoEl?.current) {
|
||||||
|
scanner?.current?.stop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!qrOn)
|
||||||
|
alert(
|
||||||
|
"Kamera tidak bisa diakses. Tolong beri izin untuk akses kamera dan silahkan reload."
|
||||||
|
);
|
||||||
|
}, [qrOn]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="qr-reader">
|
||||||
|
<video ref={videoEl}></video>
|
||||||
|
<div ref={qrBoxEl} className="qr-box">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{scannedResult && (
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
zIndex: 99999,
|
||||||
|
color: "white",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Scanned Result: {scannedResult}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -3,6 +3,7 @@ import { Button } from "lib/comps/ui/button";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogOverlay,
|
DialogOverlay,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
|
|
@ -73,6 +74,7 @@ export const Pop: FC<{
|
||||||
</DialogPrimitive.Close>
|
</DialogPrimitive.Close>
|
||||||
<DialogHeader className="c-hidden">
|
<DialogHeader className="c-hidden">
|
||||||
<DialogTitle></DialogTitle>
|
<DialogTitle></DialogTitle>
|
||||||
|
<DialogDescription></DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<PassProp
|
<PassProp
|
||||||
pop={{
|
pop={{
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,13 @@ export const FilterContent: FC<{
|
||||||
} catch (ex) {}
|
} catch (ex) {}
|
||||||
|
|
||||||
if (mode === "raw" && fm) {
|
if (mode === "raw" && fm) {
|
||||||
|
if (form && form.fm) {
|
||||||
|
Object.keys(form.fm.data).map((e) => {
|
||||||
|
if (!form?.fm.data?.[e]) {
|
||||||
|
delete form.fm?.data[e];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
const submit = async (fm: FMLocal) => {
|
const submit = async (fm: FMLocal) => {
|
||||||
fm.render();
|
fm.render();
|
||||||
if (typeof onSubmit === "function") {
|
if (typeof onSubmit === "function") {
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,12 @@ export const MasterFilter: FC<FilterProps> = ({
|
||||||
if (!isEditor) {
|
if (!isEditor) {
|
||||||
const wf = getFilter(name);
|
const wf = getFilter(name);
|
||||||
if (wf) {
|
if (wf) {
|
||||||
if (wf.filter.ref[_item.id]) {
|
if (wf.filter.ref?.[_item.id]) {
|
||||||
filter.data = wf.filter.ref[_item.id].data;
|
filter.data = wf.filter.ref[_item.id].data;
|
||||||
filter.raw_status = "ready";
|
filter.raw_status = "ready";
|
||||||
filter.render();
|
filter.render();
|
||||||
} else {
|
} else {
|
||||||
|
filter.data = {};
|
||||||
if (mode === "raw" && onLoad) {
|
if (mode === "raw" && onLoad) {
|
||||||
if (filter.raw_status === "init") {
|
if (filter.raw_status === "init") {
|
||||||
filter.raw_status = "loading";
|
filter.raw_status = "loading";
|
||||||
|
|
@ -55,8 +56,24 @@ export const MasterFilter: FC<FilterProps> = ({
|
||||||
if (data instanceof Promise) {
|
if (data instanceof Promise) {
|
||||||
data.then((e) => {
|
data.then((e) => {
|
||||||
filter.data = e;
|
filter.data = e;
|
||||||
|
if (typeof onSubmit === "function") {
|
||||||
|
const data = onSubmit({ data: e } as any);
|
||||||
|
|
||||||
|
if (data instanceof Promise) {
|
||||||
|
data.then((ex) => {
|
||||||
|
filter.data = {
|
||||||
|
__status: "submit",
|
||||||
|
...e,
|
||||||
|
_where: ex,
|
||||||
|
};
|
||||||
|
filter.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.log({ data });
|
||||||
|
}
|
||||||
filter.raw_status = "ready";
|
filter.raw_status = "ready";
|
||||||
filter.render();
|
filter.render();
|
||||||
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
filter.raw_status = "ready";
|
filter.raw_status = "ready";
|
||||||
|
|
@ -69,6 +86,9 @@ export const MasterFilter: FC<FilterProps> = ({
|
||||||
wf.filter.ref[_item.id] = filter;
|
wf.filter.ref[_item.id] = filter;
|
||||||
wf.list.render();
|
wf.list.render();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
filter.raw_status = "ready";
|
||||||
|
filter.render();
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,411 @@
|
||||||
export const generateFilter = (
|
export const generateFilter = (data: any, item: PrasiItem, commit: boolean) => {
|
||||||
data: any,
|
console.log("log", { data, item, commit });
|
||||||
item: PrasiItem,
|
};
|
||||||
commit: boolean
|
|
||||||
) => {};
|
const frameFilter = {
|
||||||
|
dim: { h: "full", w: "full", hUnit: "px", wUnit: "px" },
|
||||||
|
name: "Wrapped",
|
||||||
|
type: "item",
|
||||||
|
childs: [
|
||||||
|
{
|
||||||
|
bg: { pos: "center", size: "cover", color: "" },
|
||||||
|
dim: { h: "full", w: "full", hUnit: "px", wUnit: "px" },
|
||||||
|
name: "Wrapped",
|
||||||
|
type: "item",
|
||||||
|
childs: [
|
||||||
|
{
|
||||||
|
id: "r9u5j1gxxbuv73x8magw7smp",
|
||||||
|
adv: {
|
||||||
|
js: '<ScrollArea className={cx(props.className, "")} orientation={orientation}>{child}</ScrollArea>',
|
||||||
|
css: "",
|
||||||
|
jsBuilt:
|
||||||
|
'const _jsxFileName = "[item: scroll-area - ehqmu8gsesbvqyxmiw8l580t]";render (React.createElement(ScrollArea, { className: cx(props.className, ""), orientation: orientation, __self: this, __source: {fileName: _jsxFileName, lineNumber: 1}}, child))',
|
||||||
|
},
|
||||||
|
dim: { h: "full", w: "full" },
|
||||||
|
name: "scroll-area",
|
||||||
|
type: "item",
|
||||||
|
childs: [
|
||||||
|
{
|
||||||
|
name: "jsx:child",
|
||||||
|
id: "c7nakvqt2ih6zbbrnq59omup",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
script: {
|
||||||
|
props: {
|
||||||
|
orientation: { value: '"vertical"', valueBuilt: '"vertical"' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
id: "bb74d83b-5fd5-45a5-902d-f2f2ec8a48a7",
|
||||||
|
props: {
|
||||||
|
child: {
|
||||||
|
idx: 1,
|
||||||
|
meta: { type: "content-element" },
|
||||||
|
name: "new_prop_1",
|
||||||
|
type: "string",
|
||||||
|
value: '"hello"',
|
||||||
|
content: {
|
||||||
|
bg: { pos: "center", size: "cover", color: "" },
|
||||||
|
id: "vpvydv6rjhrtw6j9xkgl2t8f",
|
||||||
|
adv: { js: "", css: "", jsBuilt: "render ()" },
|
||||||
|
dim: { h: "full", w: "full", hUnit: "px", wUnit: "px" },
|
||||||
|
name: "child",
|
||||||
|
type: "item",
|
||||||
|
childs: [
|
||||||
|
{
|
||||||
|
bg: { pos: "center", size: "cover", color: "" },
|
||||||
|
id: "j1jtff4t8hvk4c2zn2spseww",
|
||||||
|
adv: {
|
||||||
|
js: '<div {...props} className={cx(props.className, "")} id="cek">\n {children}\n</div>',
|
||||||
|
jsBuilt:
|
||||||
|
'const _jsxFileName = "[item: absolute - bs6mzs6otarkqrqciv6hd0to]";render (React.createElement(\'div\', { ...props, className: cx(props.className, ""), id: "cek", __self: this, __source: {fileName: _jsxFileName, lineNumber: 1}}\n , children\n))',
|
||||||
|
},
|
||||||
|
dim: { h: "full", w: "full", hUnit: "px", wUnit: "px" },
|
||||||
|
name: "absolute",
|
||||||
|
type: "item",
|
||||||
|
childs: [
|
||||||
|
{
|
||||||
|
id: "tlfpdpv1g6y7f7klumtbecet",
|
||||||
|
dim: {
|
||||||
|
h: "fit",
|
||||||
|
w: "full",
|
||||||
|
hUnit: "px",
|
||||||
|
wUnit: "px",
|
||||||
|
},
|
||||||
|
name: "container",
|
||||||
|
type: "item",
|
||||||
|
childs: [
|
||||||
|
{
|
||||||
|
id: "epmv1gh58uso1iyi747oqlpf",
|
||||||
|
adv: {
|
||||||
|
js: '<div {...props} className={cx(props.className, "form-fields")}>\n {children}\n</div>',
|
||||||
|
jsBuilt:
|
||||||
|
'render(/* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "form-fields") }, children));\n',
|
||||||
|
},
|
||||||
|
dim: {
|
||||||
|
h: "full",
|
||||||
|
w: "full",
|
||||||
|
hUnit: "px",
|
||||||
|
wUnit: "px",
|
||||||
|
},
|
||||||
|
name: "fields-filter",
|
||||||
|
type: "item",
|
||||||
|
childs: [],
|
||||||
|
layout: {
|
||||||
|
dir: "row",
|
||||||
|
gap: 0,
|
||||||
|
wrap: "flex-wrap",
|
||||||
|
align: "top-left",
|
||||||
|
},
|
||||||
|
script: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
hidden: false,
|
||||||
|
script: {},
|
||||||
|
padding: { b: 0, l: 0, r: 5, t: 0 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
script: {},
|
||||||
|
},
|
||||||
|
valueBuilt: '"hello"',
|
||||||
|
jsxCalledBy: [
|
||||||
|
"yych4cm4do7t4jt0d42dasrk",
|
||||||
|
"ehqmu8gsesbvqyxmiw8l580t",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
orientation: {
|
||||||
|
idx: 1,
|
||||||
|
meta: {
|
||||||
|
type: "option",
|
||||||
|
options: '["horizontal", "vertical"]',
|
||||||
|
optionsBuilt: '["horizontal", "vertical"]',
|
||||||
|
},
|
||||||
|
name: "new_prop_1",
|
||||||
|
type: "string",
|
||||||
|
value: '"vertical"',
|
||||||
|
valueBuilt: '"vertical"',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ref_ids: {},
|
||||||
|
useStyle: true,
|
||||||
|
},
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "s9kb580m1bjmpe4xj9dtkgnz",
|
||||||
|
dim: { h: "fit", w: "full", hUnit: "px", wUnit: "px" },
|
||||||
|
name: "Wrapped",
|
||||||
|
type: "item",
|
||||||
|
childs: [
|
||||||
|
{
|
||||||
|
id: "hf0pxf4slu2xqhcuoropnkc6",
|
||||||
|
dim: { h: "fit", w: "full", hUnit: "px", wUnit: "px" },
|
||||||
|
name: "Reset",
|
||||||
|
type: "item",
|
||||||
|
childs: [
|
||||||
|
{
|
||||||
|
id: "jvnbd14f1sgcnmdhy4dcfuo4",
|
||||||
|
adv: {
|
||||||
|
js: '<Button\n {...props}\n onClick={(e) => {\n if (!isEditor) on_click(e);\n }}\n variant={variant !== "primary" ? variant : undefined}\n size={size !== "default" ? size : undefined}\n>\n {label}\n</Button>',
|
||||||
|
css: "& {\n display: flex;\n\n &:hover {\n cursor: pointer;\n\n\n\n\n\n // &.mobile {}\n // &.desktop {}\n // &:hover {}\n }\n}",
|
||||||
|
jsBuilt:
|
||||||
|
'render(/* @__PURE__ */ React.createElement(\n Button,\n {\n ...props,\n onClick: (e) => {\n if (!isEditor)\n on_click(e);\n },\n variant: variant !== "primary" ? variant : void 0,\n size: size !== "default" ? size : void 0\n },\n label\n));\n',
|
||||||
|
},
|
||||||
|
dim: { h: "full", w: "full" },
|
||||||
|
name: "button",
|
||||||
|
type: "item",
|
||||||
|
childs: [
|
||||||
|
{
|
||||||
|
name: "jsx: label",
|
||||||
|
id: "k59ppuxhzf4tnkb4b4enyxxe",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
mobile: { linktag: {} },
|
||||||
|
script: {
|
||||||
|
props: {
|
||||||
|
size: { value: ' "default";\n', valueBuilt: ' "default";\n' },
|
||||||
|
variant: { value: '"ghost"', valueBuilt: '"ghost"' },
|
||||||
|
on_click: {
|
||||||
|
value:
|
||||||
|
'async (e) => {\r\n fm.data = {};\r\n filter.data = {};\r\n filter.render();\r\n fm.render();\r\n await fm.submit();\r\n sheet.close();\r\n // const res = getFilter("root");\r\n // res.list.reload();\r\n}',
|
||||||
|
valueBuilt:
|
||||||
|
'async (e) => {\r\n fm.data = {};\r\n filter.data = {};\r\n filter.render();\r\n fm.render();\r\n await fm.submit();\r\n sheet.close();\r\n // const res = getFilter("root");\r\n // res.list.reload();\r\n}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
id: "a15d152d-0118-408f-89f1-f6b2dfbd2e05",
|
||||||
|
props: {
|
||||||
|
size: {
|
||||||
|
idx: 5,
|
||||||
|
meta: {
|
||||||
|
type: "option",
|
||||||
|
options:
|
||||||
|
'["default", "xs", "sm", "lg", "icon", "nosize"]',
|
||||||
|
optionsBuilt:
|
||||||
|
' ["default", "xs", "sm", "lg", "icon", "nosize"];\n',
|
||||||
|
},
|
||||||
|
name: "prop_5",
|
||||||
|
type: "string",
|
||||||
|
value: '"default"',
|
||||||
|
valueBuilt: ' "default";\n',
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
idx: 1,
|
||||||
|
meta: { type: "content-element" },
|
||||||
|
name: "prop_1",
|
||||||
|
type: "string",
|
||||||
|
value: '"hello"',
|
||||||
|
content: {
|
||||||
|
id: "bb91ryll6mtk827zpibo6k65",
|
||||||
|
adv: {
|
||||||
|
js: '<div {...props} className={cx(props.className, "")}>\n {children}\n</div>',
|
||||||
|
css: "",
|
||||||
|
jsBuilt:
|
||||||
|
'render(/* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "") }, children));\n',
|
||||||
|
},
|
||||||
|
dim: { h: "full", w: "full" },
|
||||||
|
name: "label",
|
||||||
|
type: "item",
|
||||||
|
childs: [
|
||||||
|
{
|
||||||
|
id: "zhmnkaup9uxpou42lyn4splr",
|
||||||
|
adv: {
|
||||||
|
js: '<div {...props} className={cx(props.className, "")}>\n Reset\n</div>',
|
||||||
|
css: "",
|
||||||
|
jsBuilt:
|
||||||
|
'const _jsxFileName = "[item: new_text - feo7cgson0fo2zjjujwqkr8l]";render (React.createElement(\'div\', { ...props, className: cx(props.className, ""), __self: this, __source: {fileName: _jsxFileName, lineNumber: 1}}, "Reset"\n\n))',
|
||||||
|
},
|
||||||
|
dim: { h: "full", w: "full" },
|
||||||
|
html: "submit",
|
||||||
|
name: "new_text",
|
||||||
|
text: "",
|
||||||
|
type: "text",
|
||||||
|
layout: { dir: "col", gap: 0, align: "center" },
|
||||||
|
script: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
script: {},
|
||||||
|
},
|
||||||
|
valueBuilt: '"hello"',
|
||||||
|
jsxCalledBy: [
|
||||||
|
"frq12uxc65i9zn8myzan4huk",
|
||||||
|
"q278u9p4cejubvfwqc72ey73",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
variant: {
|
||||||
|
idx: 3,
|
||||||
|
meta: {
|
||||||
|
type: "option",
|
||||||
|
options:
|
||||||
|
'["primary", "secondary", "outline", "ghost", "link", "destructive","no-style"]',
|
||||||
|
option_mode: "button",
|
||||||
|
optionsBuilt:
|
||||||
|
' ["primary", "secondary", "outline", "ghost", "link", "destructive", "no-style"];\n',
|
||||||
|
},
|
||||||
|
name: "prop_3",
|
||||||
|
type: "string",
|
||||||
|
value: '"ghost"',
|
||||||
|
valueBuilt: '"ghost"',
|
||||||
|
},
|
||||||
|
on_click: {
|
||||||
|
idx: 1,
|
||||||
|
meta: { type: "text" },
|
||||||
|
name: "prop_1",
|
||||||
|
type: "string",
|
||||||
|
value:
|
||||||
|
'async (e: React.MouseEvent<HTMLDivElement>) => {\r\n fm.data = {};\r\n filter.data = {};\r\n filter.render();\r\n fm.render();\r\n await fm.submit();\r\n sheet.close();\r\n // const res = getFilter("root");\r\n // res.list.reload();\r\n}',
|
||||||
|
valueBuilt:
|
||||||
|
'async (e) => {\r\n fm.data = {};\r\n filter.data = {};\r\n filter.render();\r\n fm.render();\r\n await fm.submit();\r\n sheet.close();\r\n // const res = getFilter("root");\r\n // res.list.reload();\r\n}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
originalId: "q278u9p4cejubvfwqc72ey73",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
padding: { b: 10, l: 10, r: 0, t: 10 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "zidglf2tal6pgxe6c1ey7i5x",
|
||||||
|
dim: { h: "fit", w: "full", hUnit: "px", wUnit: "px" },
|
||||||
|
name: "Apply",
|
||||||
|
type: "item",
|
||||||
|
childs: [
|
||||||
|
{
|
||||||
|
id: "hjaeik76bqh3ufszscmzw0bm",
|
||||||
|
adv: {
|
||||||
|
js: '<Button\n {...props}\n onClick={(e) => {\n if (!isEditor) on_click(e);\n }}\n variant={variant !== "primary" ? variant : undefined}\n size={size !== "default" ? size : undefined}\n>\n {label}\n</Button>',
|
||||||
|
css: "& {\n display: flex;\n\n &:hover {\n cursor: pointer;\n\n\n\n\n\n // &.mobile {}\n // &.desktop {}\n // &:hover {}\n }\n}",
|
||||||
|
jsBuilt:
|
||||||
|
'render(/* @__PURE__ */ React.createElement(\n Button,\n {\n ...props,\n onClick: (e) => {\n if (!isEditor)\n on_click(e);\n },\n variant: variant !== "primary" ? variant : void 0,\n size: size !== "default" ? size : void 0\n },\n label\n));\n',
|
||||||
|
},
|
||||||
|
dim: { h: "full", w: "full" },
|
||||||
|
name: "button",
|
||||||
|
type: "item",
|
||||||
|
childs: [
|
||||||
|
{
|
||||||
|
name: "jsx: label",
|
||||||
|
id: "w8i2j4uq3a186ozueanxisx9",
|
||||||
|
originalId: "hglwmigw09h2b8a9vlz2cme5",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
mobile: { linktag: {} },
|
||||||
|
script: {
|
||||||
|
props: {
|
||||||
|
size: { value: ' "default";\n', valueBuilt: ' "default";\n' },
|
||||||
|
variant: {
|
||||||
|
value: ' "primary";\n',
|
||||||
|
valueBuilt: ' "primary";\n',
|
||||||
|
},
|
||||||
|
on_click: {
|
||||||
|
value:
|
||||||
|
'async (e) => {\r\n await fm.submit();\r\n const res = getFilter("root");\r\n res.list.reload();\r\n sheet.close();\r\n}',
|
||||||
|
valueBuilt:
|
||||||
|
'async (e) => {\r\n await fm.submit();\r\n const res = getFilter("root");\r\n res.list.reload();\r\n sheet.close();\r\n}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
id: "a15d152d-0118-408f-89f1-f6b2dfbd2e05",
|
||||||
|
props: {
|
||||||
|
size: {
|
||||||
|
idx: 5,
|
||||||
|
meta: {
|
||||||
|
type: "option",
|
||||||
|
options:
|
||||||
|
'["default", "xs", "sm", "lg", "icon", "nosize"]',
|
||||||
|
optionsBuilt:
|
||||||
|
' ["default", "xs", "sm", "lg", "icon", "nosize"];\n',
|
||||||
|
},
|
||||||
|
name: "prop_5",
|
||||||
|
type: "string",
|
||||||
|
value: '"default"',
|
||||||
|
valueBuilt: ' "default";\n',
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
idx: 1,
|
||||||
|
meta: { type: "content-element" },
|
||||||
|
name: "prop_1",
|
||||||
|
type: "string",
|
||||||
|
value: '"hello"',
|
||||||
|
content: {
|
||||||
|
id: "dlq5kemqyq8d0os6uu34l4wd",
|
||||||
|
adv: {
|
||||||
|
js: '<div {...props} className={cx(props.className, "")}>\n {children}\n</div>',
|
||||||
|
css: "",
|
||||||
|
jsBuilt:
|
||||||
|
'render(/* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "") }, children));\n',
|
||||||
|
},
|
||||||
|
dim: { h: "full", w: "full" },
|
||||||
|
name: "label",
|
||||||
|
type: "item",
|
||||||
|
childs: [
|
||||||
|
{
|
||||||
|
id: "nbho83c6uggcc4mxjn0e2tr9",
|
||||||
|
adv: {
|
||||||
|
js: '<div {...props} className={cx(props.className, "")}>\n Apply\n</div>',
|
||||||
|
css: "",
|
||||||
|
jsBuilt:
|
||||||
|
'const _jsxFileName = "[item: new_text - to0gkiai6fbns9utxj6re1pw]";render (React.createElement(\'div\', { ...props, className: cx(props.className, ""), __self: this, __source: {fileName: _jsxFileName, lineNumber: 1}}, "Apply"\n\n))',
|
||||||
|
},
|
||||||
|
dim: { h: "full", w: "full" },
|
||||||
|
html: "submit",
|
||||||
|
name: "new_text",
|
||||||
|
text: "",
|
||||||
|
type: "text",
|
||||||
|
layout: { dir: "col", gap: 0, align: "center" },
|
||||||
|
script: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
script: {},
|
||||||
|
},
|
||||||
|
valueBuilt: '"hello"',
|
||||||
|
jsxCalledBy: [
|
||||||
|
"frq12uxc65i9zn8myzan4huk",
|
||||||
|
"q278u9p4cejubvfwqc72ey73",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
variant: {
|
||||||
|
idx: 3,
|
||||||
|
meta: {
|
||||||
|
type: "option",
|
||||||
|
options:
|
||||||
|
'["primary", "secondary", "outline", "ghost", "link", "destructive","no-style"]',
|
||||||
|
option_mode: "button",
|
||||||
|
optionsBuilt:
|
||||||
|
' ["primary", "secondary", "outline", "ghost", "link", "destructive", "no-style"];\n',
|
||||||
|
},
|
||||||
|
name: "prop_3",
|
||||||
|
type: "string",
|
||||||
|
value: '"primary"',
|
||||||
|
valueBuilt: ' "primary";\n',
|
||||||
|
},
|
||||||
|
on_click: {
|
||||||
|
idx: 1,
|
||||||
|
meta: { type: "text" },
|
||||||
|
name: "prop_1",
|
||||||
|
type: "string",
|
||||||
|
value:
|
||||||
|
'async (e: React.MouseEvent<HTMLDivElement>) => {\r\n await fm.submit();\r\n const res = getFilter("root");\r\n res.list.reload();\r\n sheet.close();\r\n}',
|
||||||
|
valueBuilt:
|
||||||
|
'async (e) => {\r\n await fm.submit();\r\n const res = getFilter("root");\r\n res.list.reload();\r\n sheet.close();\r\n}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
originalId: "q278u9p4cejubvfwqc72ey73",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
padding: { b: 10, l: 10, r: 0, t: 10 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
layout: { dir: "row", gap: 0, wrap: "flex-nowrap", align: "top-left" },
|
||||||
|
padding: { b: 0, l: 5, r: 5, t: 0 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ export const BaseField = (prop: {
|
||||||
"filled"
|
"filled"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{arg.show_label !== "n" && <Label field={field} fm={fm} />}
|
{arg.show_label !== "n" && <Label field={field} fm={fm} arg={arg}/>}
|
||||||
<div className="field-input c-flex c-flex-1 c-flex-col">
|
<div className="field-input c-flex c-flex-1 c-flex-col">
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,15 @@ export const Field: FC<FieldProp> = (arg) => {
|
||||||
|
|
||||||
const disabled =
|
const disabled =
|
||||||
typeof field.disabled === "function" ? field.disabled() : field.disabled;
|
typeof field.disabled === "function" ? field.disabled() : field.disabled;
|
||||||
if (field.hidden) return <></>;
|
const show =
|
||||||
|
typeof field.hidden === "function"
|
||||||
|
? field.hidden()
|
||||||
|
: typeof field.hidden === "string"
|
||||||
|
? field.hidden === "n"
|
||||||
|
? false
|
||||||
|
: true
|
||||||
|
: typeof field.hidden === "boolean"? field.hidden : true;
|
||||||
|
if (!show) return <></>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LabelDiv
|
<LabelDiv
|
||||||
|
|
@ -145,7 +153,7 @@ export const Field: FC<FieldProp> = (arg) => {
|
||||||
)}
|
)}
|
||||||
ref={typeof arg.field_ref === "function" ? arg.field_ref : undefined}
|
ref={typeof arg.field_ref === "function" ? arg.field_ref : undefined}
|
||||||
>
|
>
|
||||||
{showlabel !== "n" && field.label && <Label field={field} fm={fm} />}
|
{showlabel !== "n" && field.label && <Label field={field} fm={fm} arg={arg}/>}
|
||||||
<div className={cx("field-input c-flex c-flex-1 c-flex-col")}>
|
<div className={cx("field-input c-flex c-flex-1 c-flex-col")}>
|
||||||
<FieldInput
|
<FieldInput
|
||||||
field={field}
|
field={field}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { FieldTypeInput, PropTypeInput } from "./type/TypeInput";
|
||||||
import { FieldLink } from "./type/TypeLink";
|
import { FieldLink } from "./type/TypeLink";
|
||||||
import { MultiOption } from "./type/TypeMultiOption";
|
import { MultiOption } from "./type/TypeMultiOption";
|
||||||
import { SingleOption } from "./type/TypeSingleOption";
|
import { SingleOption } from "./type/TypeSingleOption";
|
||||||
|
import { TableListEdit } from "app/comps/table-list-edit/TableListEdit";
|
||||||
|
|
||||||
export const FieldInput: FC<{
|
export const FieldInput: FC<{
|
||||||
field: FieldLocal;
|
field: FieldLocal;
|
||||||
|
|
@ -58,6 +59,7 @@ export const FieldInput: FC<{
|
||||||
child: get(_item, "edit.props.child.value") as PrasiItem,
|
child: get(_item, "edit.props.child.value") as PrasiItem,
|
||||||
bottom: childsTableEdit.find((e) => e.name === "bottom") as PrasiItem,
|
bottom: childsTableEdit.find((e) => e.name === "bottom") as PrasiItem,
|
||||||
};
|
};
|
||||||
|
console.log({ tableEdit });
|
||||||
table_edit = (
|
table_edit = (
|
||||||
<TableEdit
|
<TableEdit
|
||||||
on_init={() => {
|
on_init={() => {
|
||||||
|
|
@ -74,6 +76,35 @@ export const FieldInput: FC<{
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let table_list_edit = null;
|
||||||
|
if (type_field === "multi-option" && arg.sub_type === "table-list-edit") {
|
||||||
|
const childsTableEdit = get(
|
||||||
|
_item,
|
||||||
|
"edit.props.child.value.childs"
|
||||||
|
) as unknown as Array<PrasiItem>;
|
||||||
|
const tableListEdit = {
|
||||||
|
child: get(_item, "edit.props.child.value") as PrasiItem,
|
||||||
|
bottom: childsTableEdit.find((e) => e.name === "bottom") as PrasiItem,
|
||||||
|
};
|
||||||
|
table_list_edit = (
|
||||||
|
<TableListEdit
|
||||||
|
on_init={() => {
|
||||||
|
return fm;
|
||||||
|
}}
|
||||||
|
field = {field}
|
||||||
|
arg={arg}
|
||||||
|
show_header={arg.tbl_show_header}
|
||||||
|
name={arg.name}
|
||||||
|
child={child}
|
||||||
|
PassProp={PassProp}
|
||||||
|
item={_item}
|
||||||
|
bottom={tableListEdit.bottom}
|
||||||
|
body={tableListEdit.child}
|
||||||
|
fm={fm}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let not_ready: any = false;
|
let not_ready: any = false;
|
||||||
if (
|
if (
|
||||||
arg.type === "multi-option" &&
|
arg.type === "multi-option" &&
|
||||||
|
|
@ -184,6 +215,8 @@ export const FieldInput: FC<{
|
||||||
) : ["multi-option"].includes(type_field) ? (
|
) : ["multi-option"].includes(type_field) ? (
|
||||||
arg.sub_type === "table-edit" ? (
|
arg.sub_type === "table-edit" ? (
|
||||||
table_edit
|
table_edit
|
||||||
|
) : arg.sub_type === "table-list-edit" ? (
|
||||||
|
table_list_edit
|
||||||
) : (
|
) : (
|
||||||
<MultiOption arg={arg} field={field} fm={fm} />
|
<MultiOption arg={arg} field={field} fm={fm} />
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,40 @@
|
||||||
import { FC } from "react";
|
import { FC, useEffect } from "react";
|
||||||
import { FMLocal, FieldLocal } from "../typings";
|
import { FMLocal, FieldLocal, FieldProp } from "../typings";
|
||||||
|
|
||||||
export const Label: FC<{ field: FieldLocal; fm: FMLocal }> = ({
|
export const Label: FC<{ field: FieldLocal; fm: FMLocal; arg: FieldProp }> = ({
|
||||||
field,
|
field,
|
||||||
fm,
|
fm,
|
||||||
|
arg,
|
||||||
}) => {
|
}) => {
|
||||||
const errors = fm.error.get(field.name);
|
const errors = fm.error.get(field.name);
|
||||||
const disabled =
|
const disabled =
|
||||||
typeof field.disabled === "function" ? field.disabled() : field.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"
|
||||||
|
: typeof arg.required === "function"
|
||||||
|
? arg.required()
|
||||||
|
: false;
|
||||||
|
if (typeof required === "boolean" && field.required !== required) {
|
||||||
|
field.required = required;
|
||||||
|
field.render();
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div className={cx("label c-text-sm c-flex c-items-center", "c-mt-3")}>
|
<div
|
||||||
|
className={cx(
|
||||||
|
"label c-text-sm c-flex c-items-center",
|
||||||
|
"c-mt-3 c-w-full c-justify-between"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
<span className={cx(errors.length > 0 && `c-text-red-600`)}>
|
<span className={cx(errors.length > 0 && `c-text-red-600`)}>
|
||||||
{field.label}
|
{field.label}
|
||||||
</span>
|
</span>
|
||||||
{field.required && !disabled && (
|
{required && !disabled && (
|
||||||
<span className="c-text-red-600 c-mb-2 c-ml-1">
|
<span className="c-text-red-600 c-mb-2 c-ml-1">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|
@ -33,5 +54,10 @@ export const Label: FC<{ field: FieldLocal; fm: FMLocal }> = ({
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{field.label_action && (
|
||||||
|
<div className="c-self-end">{field.label_action}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,16 @@ export const TableEdit: FC<{
|
||||||
const label = getProp(child, "title", "");
|
const label = getProp(child, "title", "");
|
||||||
const type = getProp(child, "type", "");
|
const type = getProp(child, "type", "");
|
||||||
const width = parseInt(getProp(child, "width", {}));
|
const width = parseInt(getProp(child, "width", {}));
|
||||||
|
const show = getProp(child, "show", {});
|
||||||
|
let is_show =
|
||||||
|
typeof show === "function"
|
||||||
|
? show({ data: fm.data })
|
||||||
|
: typeof show === "string"
|
||||||
|
? show === "n"
|
||||||
|
? false
|
||||||
|
: true
|
||||||
|
: true;
|
||||||
|
if (is_show)
|
||||||
if (type === "checkbox") {
|
if (type === "checkbox") {
|
||||||
const on_click = getProp(child, "opt__on_click", "");
|
const on_click = getProp(child, "opt__on_click", "");
|
||||||
columns.push({
|
columns.push({
|
||||||
|
|
@ -190,6 +200,7 @@ export const TableEdit: FC<{
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
{/* {JSON.stringify(value.map((e) => e.id))} */}
|
||||||
<table
|
<table
|
||||||
className={cx(
|
className={cx(
|
||||||
"c-table-auto",
|
"c-table-auto",
|
||||||
|
|
@ -255,15 +266,7 @@ export const TableEdit: FC<{
|
||||||
<>
|
<>
|
||||||
{value.map((row: any, idx: number) => {
|
{value.map((row: any, idx: number) => {
|
||||||
return (
|
return (
|
||||||
<BaseForm
|
<BaseForm is_form={false} data={row}>
|
||||||
is_form={false}
|
|
||||||
data={row}
|
|
||||||
on_change={(_fm) => {
|
|
||||||
fm.data[name][idx] = _fm.data;
|
|
||||||
fm.data[name] = [...fm.data[name]];
|
|
||||||
fm.render();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{(form) => {
|
{(form) => {
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -289,7 +292,10 @@ export const TableEdit: FC<{
|
||||||
row: row,
|
row: row,
|
||||||
rowIdx: idx,
|
rowIdx: idx,
|
||||||
column: header,
|
column: header,
|
||||||
fm: form.fm,
|
fm: {
|
||||||
|
...form.fm,
|
||||||
|
data: row,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
tbl: {
|
tbl: {
|
||||||
data: value,
|
data: value,
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,10 @@ export const FieldButton: FC<{
|
||||||
if (arg.type === "multi-option") {
|
if (arg.type === "multi-option") {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={cx("c-flex c-items-center c-w-full c-flex-row")}>
|
<div className={cx("c-flex c-items-center c-w-full c-flex-row c-max-w-full")}>
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
`c-flex`,
|
`c-flex c-flex-wrap`,
|
||||||
css`
|
css`
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
`
|
`
|
||||||
|
|
@ -58,10 +58,11 @@ export const FieldButton: FC<{
|
||||||
} else {
|
} else {
|
||||||
selected.push(item);
|
selected.push(item);
|
||||||
}
|
}
|
||||||
|
if(selected.length) selected = selected.filter((e) => e)
|
||||||
arg.opt_set_value({
|
arg.opt_set_value({
|
||||||
fm,
|
fm,
|
||||||
name: field.name,
|
name: field.name,
|
||||||
selected: selected.map((e) => e.value),
|
selected: selected.length ? selected.map((e) => e.value) : [],
|
||||||
options: local.list,
|
options: local.list,
|
||||||
type: field.type,
|
type: field.type,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ export const TypeDropdown: FC<{
|
||||||
fm: FMLocal;
|
fm: FMLocal;
|
||||||
arg: FieldProp;
|
arg: FieldProp;
|
||||||
}> = ({ field, fm, arg }) => {
|
}> = ({ field, fm, arg }) => {
|
||||||
|
|
||||||
const local = useLocal({
|
const local = useLocal({
|
||||||
loaded: false,
|
loaded: false,
|
||||||
options: [] as { value: string; label: string; data: any }[],
|
options: [] as { value: string; label: string; data: any }[],
|
||||||
|
|
@ -164,7 +165,14 @@ export const TypeDropdown: FC<{
|
||||||
}
|
}
|
||||||
const disabled =
|
const disabled =
|
||||||
typeof field.disabled === "function" ? field.disabled() : field.disabled;
|
typeof field.disabled === "function" ? field.disabled() : field.disabled;
|
||||||
|
const disabled_search =
|
||||||
|
typeof field.disabled_search === "function"
|
||||||
|
? field.disabled_search()
|
||||||
|
: typeof field.disabled_search === "string"
|
||||||
|
? field.disabled_search === "n"
|
||||||
|
? true
|
||||||
|
: false
|
||||||
|
: field.disabled_search;
|
||||||
if (!local.loaded) return <FieldLoading />;
|
if (!local.loaded) return <FieldLoading />;
|
||||||
|
|
||||||
if (field.type === "single-option") {
|
if (field.type === "single-option") {
|
||||||
|
|
@ -179,6 +187,7 @@ export const TypeDropdown: FC<{
|
||||||
<>
|
<>
|
||||||
<Typeahead
|
<Typeahead
|
||||||
value={typeahead_val}
|
value={typeahead_val}
|
||||||
|
disabledSearch={disabled_search ? true : false}
|
||||||
popupClassName={popupClassName}
|
popupClassName={popupClassName}
|
||||||
onSelect={({ search, item }) => {
|
onSelect={({ search, item }) => {
|
||||||
if (item) {
|
if (item) {
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,6 @@ export const FieldTypeInput: FC<{
|
||||||
case "toggle":
|
case "toggle":
|
||||||
return (
|
return (
|
||||||
<div className="c-px-2">
|
<div className="c-px-2">
|
||||||
ad
|
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
"c-relative",
|
"c-relative",
|
||||||
|
|
@ -222,6 +221,10 @@ export const FieldTypeInput: FC<{
|
||||||
? new Date(value?.startDate)
|
? new Date(value?.startDate)
|
||||||
: null;
|
: null;
|
||||||
renderOnChange();
|
renderOnChange();
|
||||||
|
|
||||||
|
if (prop.onChange) {
|
||||||
|
prop.onChange(fm.data[field.name]);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,11 @@ export const FieldLink: FC<{
|
||||||
if (!(await navigateLink(arg.link, field, fm.deps.md))) {
|
if (!(await navigateLink(arg.link, field, fm.deps.md))) {
|
||||||
link_local.navigating = false;
|
link_local.navigating = false;
|
||||||
link_local.render();
|
link_local.render();
|
||||||
|
setTimeout(() => {
|
||||||
|
|
||||||
|
local.init = true;
|
||||||
|
local.render();
|
||||||
|
}, 1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
@ -168,10 +173,11 @@ export type LinkParam = {
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigateLink = async (
|
export const navigateLink = async (
|
||||||
link: FieldProp["link"],
|
link: FieldProp["link"],
|
||||||
field: FieldLocal,
|
field: FieldLocal,
|
||||||
md?: MDLocal
|
md?: MDLocal,
|
||||||
|
prm? :any
|
||||||
) => {
|
) => {
|
||||||
let params = link.params(field) as { where: any; create: any; update: any };
|
let params = link.params(field) as { where: any; create: any; update: any };
|
||||||
|
|
||||||
|
|
@ -217,7 +223,12 @@ const navigateLink = async (
|
||||||
values.hash = vhash;
|
values.hash = vhash;
|
||||||
|
|
||||||
link_cache[vhash] = values;
|
link_cache[vhash] = values;
|
||||||
|
if (typeof link.url === "function") {
|
||||||
|
if (md) {
|
||||||
|
link.url(md.selected[md.pk?.name || ""]);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
if (!link.url) {
|
if (!link.url) {
|
||||||
alert("No URL defined!");
|
alert("No URL defined!");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -231,6 +242,7 @@ const navigateLink = async (
|
||||||
if (prev_link) prev_link = prev_link + "+";
|
if (prev_link) prev_link = prev_link + "+";
|
||||||
}
|
}
|
||||||
|
|
||||||
navigate(`${link.url}#lnk=${prev_link + vhash}`);
|
navigate(`${link.url}#lnk=${prev_link + vhash}${prm}`);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ export const FieldMoney: FC<{
|
||||||
input.render();
|
input.render();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
value={formatCurrency(input.value)}
|
value={formatCurrency(input.value) || 0}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
className={cx(
|
className={cx(
|
||||||
"c-flex-1 c-bg-transparent c-outline-none c-px-2 c-text-sm c-w-full"
|
"c-flex-1 c-bg-transparent c-outline-none c-px-2 c-text-sm c-w-full"
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ type FieldType =
|
||||||
export type FieldProp = {
|
export type FieldProp = {
|
||||||
name: string;
|
name: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
label_action: ReactNode;
|
||||||
desc?: string;
|
desc?: string;
|
||||||
props?: any;
|
props?: any;
|
||||||
mask?: string;
|
mask?: string;
|
||||||
|
|
@ -63,7 +64,7 @@ export type FieldProp = {
|
||||||
field: FieldLocal;
|
field: FieldLocal;
|
||||||
Link: FC<{ children: any }>;
|
Link: FC<{ children: any }>;
|
||||||
}) => Promise<string> | string);
|
}) => Promise<string> | string);
|
||||||
url: string;
|
url: string | ((e?: any) => void);
|
||||||
params: (field: FieldLocal) => { where: any } | Promise<{ where: any }>;
|
params: (field: FieldLocal) => { where: any } | Promise<{ where: any }>;
|
||||||
};
|
};
|
||||||
fm: FMLocal;
|
fm: FMLocal;
|
||||||
|
|
@ -127,6 +128,8 @@ export type FieldProp = {
|
||||||
max_date?: any;
|
max_date?: any;
|
||||||
min_date?: any;
|
min_date?: any;
|
||||||
upload_style?: "inline" | "full";
|
upload_style?: "inline" | "full";
|
||||||
|
disabled_search?: (() => Promise<boolean> | boolean) | boolean | "y" | "n";
|
||||||
|
show?: (() => boolean) | boolean | "y" | "n";
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FMInternal = {
|
export type FMInternal = {
|
||||||
|
|
@ -170,13 +173,14 @@ export type FieldInternal<T extends FieldProp["type"]> = {
|
||||||
name: FieldProp["name"];
|
name: FieldProp["name"];
|
||||||
type: T | (() => T);
|
type: T | (() => T);
|
||||||
label: FieldProp["label"];
|
label: FieldProp["label"];
|
||||||
|
label_action: FieldProp["label_action"];
|
||||||
desc: FieldProp["desc"];
|
desc: FieldProp["desc"];
|
||||||
prefix: FieldProp["prefix"];
|
prefix: FieldProp["prefix"];
|
||||||
suffix: FieldProp["suffix"];
|
suffix: FieldProp["suffix"];
|
||||||
width: FieldProp["width"];
|
width: FieldProp["width"];
|
||||||
required: boolean;
|
required: boolean;
|
||||||
focused: boolean;
|
focused: boolean;
|
||||||
hidden: boolean;
|
hidden: (() => boolean) | boolean | "y" | "n";
|
||||||
disabled: boolean | (() => boolean);
|
disabled: boolean | (() => boolean);
|
||||||
required_msg: FieldProp["required_msg"];
|
required_msg: FieldProp["required_msg"];
|
||||||
col?: GFCol;
|
col?: GFCol;
|
||||||
|
|
@ -200,6 +204,7 @@ export type FieldInternal<T extends FieldProp["type"]> = {
|
||||||
min_date?: FieldProp["min_date"];
|
min_date?: FieldProp["min_date"];
|
||||||
error?: any;
|
error?: any;
|
||||||
table_fields?: any[];
|
table_fields?: any[];
|
||||||
|
disabled_search?: (() => Promise<boolean> | boolean) | boolean | "y" | "n";
|
||||||
};
|
};
|
||||||
export type FieldLocal = FieldInternal<any> & {
|
export type FieldLocal = FieldInternal<any> & {
|
||||||
render: () => void;
|
render: () => void;
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
|
||||||
const toastSuccess = (opt: { addNewText: string }) => {
|
const toastSuccess = (opt: { addNewText: string }) => {
|
||||||
const md = fm.deps.md as MDLocal;
|
const md = fm.deps.md as MDLocal;
|
||||||
fm.save_status = "saved";
|
fm.save_status = "saved";
|
||||||
|
|
||||||
if (md) {
|
if (md) {
|
||||||
toast.success(
|
toast.success(
|
||||||
<div
|
<div
|
||||||
|
|
@ -110,7 +109,7 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
|
||||||
</div>
|
</div>
|
||||||
</div>,
|
</div>,
|
||||||
{
|
{
|
||||||
duration: 60 * 1000,
|
duration:3000,
|
||||||
className: css`
|
className: css`
|
||||||
background: #e4ffed;
|
background: #e4ffed;
|
||||||
border: 2px solid green;
|
border: 2px solid green;
|
||||||
|
|
@ -135,7 +134,7 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
|
||||||
</div>
|
</div>
|
||||||
</div>,
|
</div>,
|
||||||
{
|
{
|
||||||
duration: 60 * 1000,
|
duration:3000,
|
||||||
className: css`
|
className: css`
|
||||||
background: #e4ffed;
|
background: #e4ffed;
|
||||||
border: 2px solid green;
|
border: 2px solid green;
|
||||||
|
|
@ -233,7 +232,6 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const form = JSON.parse(JSON.stringify(fm.data));
|
const form = JSON.parse(JSON.stringify(fm.data));
|
||||||
|
|
||||||
if (fm.deps.md) {
|
if (fm.deps.md) {
|
||||||
|
|
@ -291,6 +289,7 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
toastSuccess({ addNewText: lang.t("Add New") });
|
toastSuccess({ addNewText: lang.t("Add New") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,18 +21,20 @@ export const useField = (
|
||||||
|
|
||||||
const name = typeof arg.name === "string" ? arg.name : arg.name();
|
const name = typeof arg.name === "string" ? arg.name : arg.name();
|
||||||
const label = typeof arg.label === "string" ? arg.label : arg.label();
|
const label = typeof arg.label === "string" ? arg.label : arg.label();
|
||||||
|
|
||||||
const required =
|
const required =
|
||||||
typeof arg.required === "string" ? arg.required : arg.required();
|
typeof arg.required === "string" ? arg.required === "y" : arg.required();
|
||||||
const update_field = {
|
const update_field = {
|
||||||
name: name.replace(/\s*/gi, ""),
|
name: name.replace(/\s*/gi, ""),
|
||||||
label: label,
|
label: label,
|
||||||
|
label_action: arg.label_action,
|
||||||
type: arg.type,
|
type: arg.type,
|
||||||
desc: arg.desc,
|
desc: arg.desc,
|
||||||
prefix: arg.prefix,
|
prefix: arg.prefix,
|
||||||
suffix: arg.suffix,
|
suffix: arg.suffix,
|
||||||
width: arg.width,
|
width: arg.width,
|
||||||
custom: arg.custom,
|
custom: arg.custom,
|
||||||
required: required === "y",
|
required: typeof required === "string" ? required === "y" : required,
|
||||||
required_msg: arg.required_msg,
|
required_msg: arg.required_msg,
|
||||||
disabled:
|
disabled:
|
||||||
typeof arg.disabled === "function" ? arg.disabled : arg.disabled === "y",
|
typeof arg.disabled === "function" ? arg.disabled : arg.disabled === "y",
|
||||||
|
|
@ -40,8 +42,11 @@ export const useField = (
|
||||||
max_date: arg.max_date,
|
max_date: arg.max_date,
|
||||||
min_date: arg.min_date,
|
min_date: arg.min_date,
|
||||||
table_fields: [],
|
table_fields: [],
|
||||||
|
disabled_search: arg.disabled_search,
|
||||||
|
hidden: arg.show
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if (field.status === "init" || isEditor) {
|
if (field.status === "init" || isEditor) {
|
||||||
for (const [k, v] of Object.entries(update_field)) {
|
for (const [k, v] of Object.entries(update_field)) {
|
||||||
(field as any)[k] = v;
|
(field as any)[k] = v;
|
||||||
|
|
@ -49,7 +54,6 @@ export const useField = (
|
||||||
}
|
}
|
||||||
|
|
||||||
const fm = arg.fm;
|
const fm = arg.fm;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (field.status === "init" || !fm.fields[name]) {
|
if (field.status === "init" || !fm.fields[name]) {
|
||||||
field.status = "ready";
|
field.status = "ready";
|
||||||
|
|
@ -60,7 +64,10 @@ export const useField = (
|
||||||
field.render();
|
field.render();
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
field.prop = arg as any;
|
field.prop = arg as any;
|
||||||
|
|
||||||
|
if(field.name === "complete_description") console.log(update_field);
|
||||||
|
if(field.name === "complete_description") console.log(field);
|
||||||
return field;
|
return field;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ export const Import: FC<{
|
||||||
task,
|
task,
|
||||||
}: {
|
}: {
|
||||||
list: any[];
|
list: any[];
|
||||||
task: (e: any) => Promise<void>;
|
task: (e: any, index: number) => Promise<void>;
|
||||||
}) => {
|
}) => {
|
||||||
let n = 0;
|
let n = 0;
|
||||||
while (n < list.length) {
|
while (n < list.length) {
|
||||||
|
|
@ -99,7 +99,7 @@ export const Import: FC<{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await task(list[n]);
|
await task(list[n], n);
|
||||||
await sleep(100);
|
await sleep(100);
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
@ -108,9 +108,9 @@ export const Import: FC<{
|
||||||
if (local.progress <= 0) {
|
if (local.progress <= 0) {
|
||||||
const res = startImport({
|
const res = startImport({
|
||||||
list: local.data,
|
list: local.data,
|
||||||
task: async (e) => {
|
task: async (e, index) => {
|
||||||
if (typeof task === "function") {
|
if (typeof task === "function") {
|
||||||
const result = await task({data: e, excel});
|
const result = await task({data: e, excel, index, list: local.data, render: local.render});
|
||||||
if (typeof result === "boolean") {
|
if (typeof result === "boolean") {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
local.recap.failed.push(e);
|
local.recap.failed.push(e);
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,7 @@ export const TableList: FC<TableListProp> = ({
|
||||||
reloading: null as any,
|
reloading: null as any,
|
||||||
reload: (arg?: { toast: boolean }) => {
|
reload: (arg?: { toast: boolean }) => {
|
||||||
if (local.reloading) return local.reloading;
|
if (local.reloading) return local.reloading;
|
||||||
|
|
||||||
local.reloading = new Promise<void>(async (done) => {
|
local.reloading = new Promise<void>(async (done) => {
|
||||||
let should_toast = true;
|
let should_toast = true;
|
||||||
if (arg?.toast === false) should_toast = false;
|
if (arg?.toast === false) should_toast = false;
|
||||||
|
|
@ -217,7 +218,6 @@ export const TableList: FC<TableListProp> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (md) {
|
if (md) {
|
||||||
if (md.header.loading) {
|
|
||||||
await new Promise<void>((resolve) => {
|
await new Promise<void>((resolve) => {
|
||||||
const ival = setInterval(() => {
|
const ival = setInterval(() => {
|
||||||
if (!md.header.loading) {
|
if (!md.header.loading) {
|
||||||
|
|
@ -226,7 +226,7 @@ export const TableList: FC<TableListProp> = ({
|
||||||
}
|
}
|
||||||
}, 10);
|
}, 10);
|
||||||
});
|
});
|
||||||
}
|
if (Array.isArray(md?.params?.links) && md?.params?.links?.length) {
|
||||||
const last = md.params.links[md.params.links.length - 1];
|
const last = md.params.links[md.params.links.length - 1];
|
||||||
|
|
||||||
if (last && last.where) {
|
if (last && last.where) {
|
||||||
|
|
@ -237,11 +237,9 @@ export const TableList: FC<TableListProp> = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
call_prasi_events("tablelist", "where", [
|
call_prasi_events("tablelist", "where", [__props?.gen__table, where]);
|
||||||
__props?.gen__table,
|
|
||||||
where,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const load_args: any = {
|
const load_args: any = {
|
||||||
async reload() {},
|
async reload() {},
|
||||||
|
|
@ -312,6 +310,7 @@ export const TableList: FC<TableListProp> = ({
|
||||||
})();
|
})();
|
||||||
} else callback(result);
|
} else callback(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return local.reloading;
|
return local.reloading;
|
||||||
|
|
@ -557,7 +556,7 @@ export const TableList: FC<TableListProp> = ({
|
||||||
|
|
||||||
if (typeof local.data === "string") {
|
if (typeof local.data === "string") {
|
||||||
console.error(local.data);
|
console.error(local.data);
|
||||||
local.data = []
|
local.data = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isEditor) {
|
if (isEditor) {
|
||||||
|
|
@ -579,53 +578,22 @@ export const TableList: FC<TableListProp> = ({
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (childs.length && isCheckbox) {
|
|
||||||
columns.push({
|
|
||||||
key: SELECT_COLUMN_KEY,
|
|
||||||
name: "",
|
|
||||||
width: 35,
|
|
||||||
minWidth: 35,
|
|
||||||
maxWidth: 35,
|
|
||||||
resizable: false,
|
|
||||||
sortable: false,
|
|
||||||
frozen: true,
|
|
||||||
renderHeaderCell(props) {
|
|
||||||
return <input type="checkbox" onChange={headerCheckboxClick} />;
|
|
||||||
},
|
|
||||||
renderCell(props) {
|
|
||||||
// digunakan untuk mengecek apakah local selected rows memiliki pk dari props.row.id
|
|
||||||
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={isChecked}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
headerCellClass: selectCellClassname,
|
|
||||||
cellClass: selectCellClassname,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let first = true;
|
let first = true;
|
||||||
for (const child of childs) {
|
for (const child of childs) {
|
||||||
let key = getProp(child, "name", {});
|
let key = getProp(child, "name", {});
|
||||||
const name = getProp(child, "title", "");
|
const name = getProp(child, "title", "");
|
||||||
|
const sort = getProp(child, "sortir", "");
|
||||||
|
let show = getProp(child, "show", "");
|
||||||
|
if (typeof show === "function") {
|
||||||
|
show = show();
|
||||||
|
if (typeof show === "object" && show instanceof Promise) {
|
||||||
|
show.then((e) => {
|
||||||
|
show = e;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
show = show === "n" ? false : show;
|
||||||
|
if (show) {
|
||||||
const type = getProp(child, "type", "");
|
const type = getProp(child, "type", "");
|
||||||
const width = parseInt(getProp(child, "width", {}));
|
const width = parseInt(getProp(child, "width", {}));
|
||||||
if (type === "checkbox") {
|
if (type === "checkbox") {
|
||||||
|
|
@ -635,7 +603,7 @@ export const TableList: FC<TableListProp> = ({
|
||||||
width: 35,
|
width: 35,
|
||||||
minWidth: 45,
|
minWidth: 45,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
sortable: true,
|
sortable: sort === "n" ? false : true,
|
||||||
frozen: true,
|
frozen: true,
|
||||||
renderHeaderCell(props) {
|
renderHeaderCell(props) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -674,7 +642,69 @@ export const TableList: FC<TableListProp> = ({
|
||||||
name,
|
name,
|
||||||
width: width > 0 ? width : undefined,
|
width: width > 0 ? width : undefined,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
sortable: true,
|
sortable: sort === "n" ? false : true,
|
||||||
|
renderHeaderCell(props) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="flex flex-row flex-grow items-center"
|
||||||
|
onClick={() => {
|
||||||
|
const msg = `The ${props?.column?.name} column cannot be sorted!`;
|
||||||
|
if (!props?.column?.sortable) {
|
||||||
|
toast.dismiss();
|
||||||
|
toast.error(
|
||||||
|
<div className="c-flex c-text-red-600 c-items-center">
|
||||||
|
<AlertTriangle className="c-h-4 c-w-4 c-mr-1" />
|
||||||
|
{msg}
|
||||||
|
</div>,
|
||||||
|
{
|
||||||
|
dismissible: true,
|
||||||
|
className: css`
|
||||||
|
background: #ffecec;
|
||||||
|
border: 2px solid red;
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props?.column?.name}
|
||||||
|
{props.sortDirection ? (
|
||||||
|
<>
|
||||||
|
{" "}
|
||||||
|
<div className="px-1">
|
||||||
|
{props.sortDirection === "ASC" ? (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M12.53 7.97a.75.75 0 0 0-1.06 0l-7 7A.75.75 0 0 0 5 16.25h14a.75.75 0 0 0 .53-1.28z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
) : (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M5 7.75a.75.75 0 0 0-.53 1.28l7 7a.75.75 0 0 0 1.06 0l7-7A.75.75 0 0 0 19 7.75z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
renderCell(props) {
|
renderCell(props) {
|
||||||
if (typeof render_col === "function")
|
if (typeof render_col === "function")
|
||||||
return render_col({
|
return render_col({
|
||||||
|
|
@ -727,7 +757,7 @@ export const TableList: FC<TableListProp> = ({
|
||||||
(props.row?.__children || []).length === 0 && (
|
(props.row?.__children || []).length === 0 && (
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
" c-border-l c-border-b c-border-black c-w-[10px] c-h-[15px]",
|
" c-border-l c-border-b c-border-black c-w-[10px] c-h-[15px] rows",
|
||||||
css`
|
css`
|
||||||
margin-top: -10px;
|
margin-top: -10px;
|
||||||
`
|
`
|
||||||
|
|
@ -759,6 +789,7 @@ export const TableList: FC<TableListProp> = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (mode === "list") {
|
if (mode === "list") {
|
||||||
if (columns.length > 1) columns = columns.slice(0, 0 + 1);
|
if (columns.length > 1) columns = columns.slice(0, 0 + 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,12 @@ export const generateTableList = async (
|
||||||
)[];
|
)[];
|
||||||
let pk = "";
|
let pk = "";
|
||||||
let pks: Record<string, string> = {};
|
let pks: Record<string, string> = {};
|
||||||
|
// console.log(raw_fields)
|
||||||
const fields = parseGenField(raw_fields);
|
const fields = parseGenField(raw_fields);
|
||||||
// convert ke bahasa prisma untuk select
|
// convert ke bahasa prisma untuk select
|
||||||
const res = generateSelect(fields);
|
const res = generateSelect(fields);
|
||||||
|
console.log({res})
|
||||||
|
console.log({fields})
|
||||||
pk = res.pk;
|
pk = res.pk;
|
||||||
const select = res.select as any;
|
const select = res.select as any;
|
||||||
if (!pk) {
|
if (!pk) {
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,6 @@ idx: any;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
|
|
||||||
tab_master?.edit.setChilds([
|
tab_master?.edit.setChilds([
|
||||||
{
|
{
|
||||||
type: "item",
|
type: "item",
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,11 @@ export const SheetCn: FC<{
|
||||||
header: string;
|
header: string;
|
||||||
open: string;
|
open: string;
|
||||||
close?: string;
|
close?: string;
|
||||||
mode?: "full" | "normal";
|
mode?: "full" | "normal" | "1/3";
|
||||||
direction?: "left" | "right" | "bottom" | "top";
|
direction?: "left" | "right" | "bottom" | "top";
|
||||||
deps?: any;
|
deps?: any;
|
||||||
|
_item?: PrasiItem;
|
||||||
|
onInit?: (e: any) => void;
|
||||||
}> = ({
|
}> = ({
|
||||||
child,
|
child,
|
||||||
PassProp,
|
PassProp,
|
||||||
|
|
@ -35,10 +37,13 @@ export const SheetCn: FC<{
|
||||||
close,
|
close,
|
||||||
mode,
|
mode,
|
||||||
direction,
|
direction,
|
||||||
deps
|
deps,
|
||||||
|
_item,
|
||||||
|
onInit,
|
||||||
}) => {
|
}) => {
|
||||||
const local = useLocal({
|
const local = useLocal({
|
||||||
open: false,
|
open: false,
|
||||||
|
data: null as any,
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isEditor) {
|
if (isEditor) {
|
||||||
|
|
@ -47,6 +52,25 @@ export const SheetCn: FC<{
|
||||||
local.open = op;
|
local.open = op;
|
||||||
local.render();
|
local.render();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
console.log(typeof onInit)
|
||||||
|
if (typeof onInit === "function") {
|
||||||
|
onInit({
|
||||||
|
data: local,
|
||||||
|
deps,
|
||||||
|
open: () => {
|
||||||
|
local.open = true;
|
||||||
|
local.render();
|
||||||
|
setTimeout(() => {
|
||||||
|
document.body.style.pointerEvents = "auto";
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
close: () => {
|
||||||
|
local.open = false;
|
||||||
|
local.render();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [open]);
|
}, [open]);
|
||||||
return (
|
return (
|
||||||
|
|
@ -55,6 +79,7 @@ export const SheetCn: FC<{
|
||||||
<div {...props} className={cx(props.className, "")}>
|
<div {...props} className={cx(props.className, "")}>
|
||||||
<PassProp
|
<PassProp
|
||||||
sheet={{
|
sheet={{
|
||||||
|
data: local,
|
||||||
deps,
|
deps,
|
||||||
open: () => {
|
open: () => {
|
||||||
local.open = true;
|
local.open = true;
|
||||||
|
|
@ -89,12 +114,19 @@ export const SheetCn: FC<{
|
||||||
<SheetContent
|
<SheetContent
|
||||||
side={direction}
|
side={direction}
|
||||||
className={cx(
|
className={cx(
|
||||||
mode === "full" ? "c-w-screen" : "sm:s-max-w-[425px]",
|
mode === "1/3"
|
||||||
|
? css`
|
||||||
|
max-width: 500px !important;
|
||||||
|
`
|
||||||
|
: mode === "full"
|
||||||
|
? "c-w-screen"
|
||||||
|
: "sm:s-max-w-[425px]",
|
||||||
css`
|
css`
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
<div className="c-relative">
|
||||||
{close !== "n" ? (
|
{close !== "n" ? (
|
||||||
<SheetPrimitive.Close
|
<SheetPrimitive.Close
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
@ -102,10 +134,11 @@ export const SheetCn: FC<{
|
||||||
local.render();
|
local.render();
|
||||||
}}
|
}}
|
||||||
className={cx(
|
className={cx(
|
||||||
"c-absolute c-right-4 c-top-4 c-rounded-sm c-opacity-70 c-ring-offset-background c-transition-opacity hover:c-opacity-100 focus:c-outline-none focus:c-ring-2 focus:c-ring-ring focus:c-ring-offset-2 disabled:c-pointer-events-none data-[state=open]:c-bg-accent data-[state=open]:c-text-muted-foreground",
|
"c-absolute c-right-4 c-rounded-sm c-opacity-70 c-ring-offset-background c-transition-opacity hover:c-opacity-100 focus:c-outline-none focus:c-ring-2 focus:c-ring-ring focus:c-ring-offset-2 disabled:c-pointer-events-none data-[state=open]:c-bg-accent data-[state=open]:c-text-muted-foreground",
|
||||||
css`
|
css`
|
||||||
right: 1rem;
|
right: 1rem;
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
|
transform: translateY(50%);
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -118,12 +151,23 @@ export const SheetCn: FC<{
|
||||||
{header !== "" && header ? (
|
{header !== "" && header ? (
|
||||||
<SheetHeader
|
<SheetHeader
|
||||||
className={cx(
|
className={cx(
|
||||||
|
"c-text-base",
|
||||||
css`
|
css`
|
||||||
padding: 0px 0px 0px 10px;
|
padding: 0px 0px 0px 10px;
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<SheetTitle>{header}</SheetTitle>
|
<SheetTitle
|
||||||
|
className={cx(
|
||||||
|
"c-text-base",
|
||||||
|
css`
|
||||||
|
font-size: 1rem !important;
|
||||||
|
line-height: 1.5rem !important;
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{header}
|
||||||
|
</SheetTitle>
|
||||||
</SheetHeader>
|
</SheetHeader>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
|
@ -135,11 +179,14 @@ export const SheetCn: FC<{
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<SheetTitle></SheetTitle>
|
<SheetTitle></SheetTitle>
|
||||||
</SheetHeader></>
|
</SheetHeader>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<PassProp
|
<PassProp
|
||||||
sheet={{
|
sheet={{
|
||||||
|
data: local,
|
||||||
deps,
|
deps,
|
||||||
open: () => {
|
open: () => {
|
||||||
local.open = true;
|
local.open = true;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { useLocal } from "lib/utils/use-local";
|
||||||
|
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
||||||
|
import { X } from "lucide-react";
|
||||||
|
import { FC, useEffect } from "react";
|
||||||
|
import {
|
||||||
|
Carousel,
|
||||||
|
CarouselContent,
|
||||||
|
CarouselItem,
|
||||||
|
CarouselNext,
|
||||||
|
CarouselPrevious,
|
||||||
|
} from "lib/comps/ui/carousel";
|
||||||
|
|
||||||
|
export const Slide: FC<{
|
||||||
|
child: any;
|
||||||
|
PassProp: any;
|
||||||
|
props: any;
|
||||||
|
mode?: "full" | "normal";
|
||||||
|
direction?: "vertical" | "horizontal";
|
||||||
|
deps?: any;
|
||||||
|
_item?: PrasiItem;
|
||||||
|
data: any;
|
||||||
|
}> = ({ child, PassProp, props, mode, direction, deps, _item, data }) => {
|
||||||
|
return (
|
||||||
|
<Carousel className="c-flex c-flex-row c-flex-grow c-flex-1 ">
|
||||||
|
<CarouselContent>
|
||||||
|
{Array.isArray(data) ? (
|
||||||
|
<>
|
||||||
|
{data.map((e, idx) => {
|
||||||
|
return (
|
||||||
|
<CarouselItem>
|
||||||
|
<PassProp item={e} idx={idx} slide={{ deps }}>
|
||||||
|
{child}
|
||||||
|
</PassProp>
|
||||||
|
</CarouselItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</CarouselContent>
|
||||||
|
</Carousel>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -2,9 +2,10 @@ import { useLocal } from "lib/utils/use-local";
|
||||||
import get from "lodash.get";
|
import get from "lodash.get";
|
||||||
import { FC, ReactNode, useEffect } from "react";
|
import { FC, ReactNode, useEffect } from "react";
|
||||||
import { PTLocalInternal, PTProp } from "../utils/typings";
|
import { PTLocalInternal, PTProp } from "../utils/typings";
|
||||||
export const PanelTab: FC<PTProp> = ({ header, body, tab, PassProp, item }) => {
|
export const PanelTab: FC<PTProp> = ({ header, body, tab, PassProp, item, deps }) => {
|
||||||
const local = useLocal<PTLocalInternal>({
|
const local = useLocal<PTLocalInternal>({
|
||||||
mode: "" as any,
|
mode: "" as any,
|
||||||
|
deps
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
local.mode = tab;
|
local.mode = tab;
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,11 @@ export type PTProp = {
|
||||||
PassProp: any;
|
PassProp: any;
|
||||||
item: PrasiItem;
|
item: PrasiItem;
|
||||||
pt: PTLocalInternal;
|
pt: PTLocalInternal;
|
||||||
|
deps?: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PTLocalInternal = {
|
export type PTLocalInternal = {
|
||||||
mode: string;
|
mode: string;
|
||||||
|
deps?: any
|
||||||
};
|
};
|
||||||
export type PTLocal = PTLocalInternal & { render: (force?: boolean) => void };
|
export type PTLocal = PTLocalInternal & { render: (force?: boolean) => void };
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
"use client"
|
||||||
|
|
||||||
|
import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
|
||||||
|
|
||||||
|
const AspectRatio = AspectRatioPrimitive.Root
|
||||||
|
|
||||||
|
export { AspectRatio }
|
||||||
|
|
@ -155,7 +155,7 @@ const CarouselContent = React.forwardRef<
|
||||||
const { carouselRef, orientation } = useCarousel()
|
const { carouselRef, orientation } = useCarousel()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={carouselRef} className="c-overflow-hidden">
|
<div ref={carouselRef} className="c-overflow-hidden c-w-full c-flex-grow c-flex-1">
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ const SheetContent = React.forwardRef<
|
||||||
<SheetPortal>
|
<SheetPortal>
|
||||||
<SheetPrimitive.Content
|
<SheetPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(sheetVariants({ side }), className)}
|
className={cn(sheetVariants({ side }), className, "sheet-content")}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
@ -102,7 +102,7 @@ const SheetTitle = React.forwardRef<
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<SheetPrimitive.Title
|
<SheetPrimitive.Title
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn("c-text-lg c-font-semibold c-text-foreground", className)}
|
className={cn("c-py-2 c-text-lg c-font-semibold c-text-foreground", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ export const Typeahead: FC<{
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
mode?: "multi" | "single";
|
mode?: "multi" | "single";
|
||||||
note?: string;
|
note?: string;
|
||||||
|
disabledSearch?: boolean;
|
||||||
}> = ({
|
}> = ({
|
||||||
value,
|
value,
|
||||||
note,
|
note,
|
||||||
|
|
@ -41,6 +42,7 @@ export const Typeahead: FC<{
|
||||||
onChange,
|
onChange,
|
||||||
className,
|
className,
|
||||||
popupClassName,
|
popupClassName,
|
||||||
|
disabledSearch
|
||||||
}) => {
|
}) => {
|
||||||
const local = useLocal({
|
const local = useLocal({
|
||||||
value: [] as string[],
|
value: [] as string[],
|
||||||
|
|
@ -440,13 +442,8 @@ export const Typeahead: FC<{
|
||||||
return false;
|
return false;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<input
|
<div
|
||||||
placeholder={
|
className="single c-flex-1 c-flex-grow c-flex c-flex-row c-cursor-pointer c-z-99"
|
||||||
local.mode === "multi" ? placeholder : valueLabel[0]?.label
|
|
||||||
}
|
|
||||||
type="text"
|
|
||||||
ref={input}
|
|
||||||
value={inputval}
|
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
|
|
@ -459,10 +456,18 @@ export const Typeahead: FC<{
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local.mode === "single") {
|
if (local.mode === "single") {
|
||||||
e.currentTarget.select();
|
if (input && input.current) input.current.select();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
placeholder={
|
||||||
|
local.mode === "multi" ? placeholder : valueLabel[0]?.label
|
||||||
|
}
|
||||||
|
type="text"
|
||||||
|
ref={input}
|
||||||
|
value={inputval}
|
||||||
onChange={async (e) => {
|
onChange={async (e) => {
|
||||||
const val = e.currentTarget.value;
|
const val = e.currentTarget.value;
|
||||||
if (!local.open) {
|
if (!local.open) {
|
||||||
|
|
@ -544,14 +549,18 @@ export const Typeahead: FC<{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
disabled={disabled}
|
disabled={!disabled ? disabledSearch : disabled}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
className={cx(
|
className={cx(
|
||||||
"c-flex-1 c-mb-2 c-outline-none c-bg-transparent",
|
"c-flex-1 c-mb-2 c-outline-none c-bg-transparent",
|
||||||
local.mode === "single" ? "c-cursor-pointer" : ""
|
local.mode === "single" ? "c-cursor-pointer" : ""
|
||||||
)}
|
)}
|
||||||
|
style={{
|
||||||
|
pointerEvents: disabledSearch ? "none" : "auto", // Mencegah input menangkap klik saat disabled
|
||||||
|
}}
|
||||||
onKeyDown={keydown}
|
onKeyDown={keydown}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</TypeaheadOptions>
|
</TypeaheadOptions>
|
||||||
{local.mode === "single" && (
|
{local.mode === "single" && (
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
18
exports.tsx
18
exports.tsx
|
|
@ -20,9 +20,9 @@ export const Typeahead = lazify(
|
||||||
);
|
);
|
||||||
|
|
||||||
/** Master - Detail - List - Form */
|
/** Master - Detail - List - Form */
|
||||||
export const MasterDetail = lazify(
|
// export const MasterDetail = lazify(
|
||||||
async () => (await import("lib/comps/md/MasterDetail")).MasterDetail
|
// async () => (await import("lib/comps/md/MasterDetail")).MasterDetail
|
||||||
);
|
// );
|
||||||
export const MDRenderMaster = lazify(
|
export const MDRenderMaster = lazify(
|
||||||
async () => (await import("lib/comps/md/parts/MDMaster")).MDRenderMaster
|
async () => (await import("lib/comps/md/parts/MDMaster")).MDRenderMaster
|
||||||
);
|
);
|
||||||
|
|
@ -107,6 +107,13 @@ export const Pop = lazify(
|
||||||
async () => (await import("lib/comps/dialog/Dialog")).Pop
|
async () => (await import("lib/comps/dialog/Dialog")).Pop
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const Slide = lazify(
|
||||||
|
async () => (await import("lib/comps/slide/Slide")).Slide
|
||||||
|
);
|
||||||
|
|
||||||
|
export const AspectRatio = lazify(
|
||||||
|
async () => (await import("lib/comps/ui/aspect-ratio")).AspectRatio
|
||||||
|
);
|
||||||
export const Import = lazify(
|
export const Import = lazify(
|
||||||
async () => (await import("lib/comps/import/Import")).Import
|
async () => (await import("lib/comps/import/Import")).Import
|
||||||
);
|
);
|
||||||
|
|
@ -134,11 +141,12 @@ export { kvToJSON } from "./utils/kv-to-json";
|
||||||
export { overrideNav } from "./utils/override-nav";
|
export { overrideNav } from "./utils/override-nav";
|
||||||
export { bulk_query } from "./utils/bulk-query";
|
export { bulk_query } from "./utils/bulk-query";
|
||||||
export { get_user } from "./utils/get_user";
|
export { get_user } from "./utils/get_user";
|
||||||
|
export { range_date } from "./utils/ranged_date";
|
||||||
export const _sum = sum;
|
export const _sum = sum;
|
||||||
export const _get = __get;
|
export const _get = __get;
|
||||||
|
|
||||||
/** Generator */
|
/** Generator */
|
||||||
export { generateFilter as genereteFilter } from "lib/comps/filter/gen/gen-filter";
|
export { generateFilter as generateFilter } from "lib/comps/filter/gen/gen-filter";
|
||||||
export { generateRelation } from "lib/comps/form/gen/gen-rel";
|
export { generateRelation } from "lib/comps/form/gen/gen-rel";
|
||||||
export { genTableEdit } from "lib/comps/form/gen/gen-table-edit";
|
export { genTableEdit } from "lib/comps/form/gen/gen-table-edit";
|
||||||
export { generateMasterDetail } from "lib/comps/md/gen/md-gen";
|
export { generateMasterDetail } from "lib/comps/md/gen/md-gen";
|
||||||
|
|
@ -146,7 +154,7 @@ export { parseGenField } from "lib/gen/utils";
|
||||||
|
|
||||||
/** ETC */
|
/** ETC */
|
||||||
export { filterModifier } from "lib/comps/filter/utils/filter-modifier";
|
export { filterModifier } from "lib/comps/filter/utils/filter-modifier";
|
||||||
export { generateField } from "lib/comps/form/gen/gen-field";
|
// export { generateField } from "lib/comps/form/gen/gen-field";
|
||||||
export { generateForm } from "lib/comps/form/gen/gen-form";
|
export { generateForm } from "lib/comps/form/gen/gen-form";
|
||||||
export { validate as validateField } from "lib/comps/form/utils/validate";
|
export { validate as validateField } from "lib/comps/form/utils/validate";
|
||||||
export { sortTree, treePrefix } from "lib/comps/list/utils/sort-tree";
|
export { sortTree, treePrefix } from "lib/comps/list/utils/sort-tree";
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ export const logout = (url_login?: string) => {
|
||||||
if (isEditor) return;
|
if (isEditor) return;
|
||||||
if (typeof get(w, "user") === "object") {
|
if (typeof get(w, "user") === "object") {
|
||||||
w.user = null;
|
w.user = null;
|
||||||
|
localStorage.removeItem("expiry_date");
|
||||||
}
|
}
|
||||||
|
|
||||||
let id_site = "";
|
let id_site = "";
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,10 @@ export const registerSession = (session: RG) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem("user" + id_site, JSON.stringify(data));
|
localStorage.setItem("user" + id_site, JSON.stringify(data));
|
||||||
|
localStorage.setItem(
|
||||||
|
"expiry_date",
|
||||||
|
data.expired ? data.expired?.format("YYYY-MM-DD HH:mm:ss") : ""
|
||||||
|
);
|
||||||
w.user = session.data;
|
w.user = session.data;
|
||||||
w.user.role = session.role;
|
w.user.role = session.role;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ type LYTChild = {
|
||||||
tablet?: ReactNode;
|
tablet?: ReactNode;
|
||||||
child?: ReactNode;
|
child?: ReactNode;
|
||||||
default_layout: ReactNode;
|
default_layout: ReactNode;
|
||||||
exception?: Array<string>;
|
exception?: ((path: string) => boolean) | Array<string>;
|
||||||
blank_layout: ReactNode;
|
blank_layout: ReactNode;
|
||||||
login_url: string;
|
login_url: string;
|
||||||
PassProp: any;
|
PassProp: any;
|
||||||
|
|
@ -66,28 +66,32 @@ export const Layout: FC<LYTChild> = (props) => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
initResponsive();
|
initResponsive();
|
||||||
const path = getPathname();
|
const path = getPathname({ hash: true });
|
||||||
const no_layout = props.exception;
|
const no_layout = props.exception;
|
||||||
|
|
||||||
overrideNav({ local });
|
overrideNav({ local });
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!isEditor &&
|
!isEditor &&
|
||||||
Array.isArray(no_layout) &&
|
(typeof no_layout === "function"
|
||||||
no_layout.find((rule) => wildcardMatch(path, rule))
|
? no_layout!(path)
|
||||||
|
: Array.isArray(no_layout) &&
|
||||||
|
no_layout.find((rule) => wildcardMatch(path, rule)))
|
||||||
) {
|
) {
|
||||||
return <>{props.blank_layout}</>;
|
return <>{props.blank_layout}</>;
|
||||||
} else {
|
} else {
|
||||||
if (!w.user) {
|
if (!w.user) {
|
||||||
local.loading = true;
|
local.loading = true;
|
||||||
loadSession(props.login_url || "/auth/login");
|
isMobile
|
||||||
|
? loadSession("/m/auth/login")
|
||||||
|
: loadSession(props.login_url || "/auth/login");
|
||||||
|
|
||||||
local.loading = false;
|
local.loading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path === props.login_url) return props.blank_layout;
|
if (path === props.login_url) return props.blank_layout;
|
||||||
if (!w.user && !isEditor) {
|
if (!w.user && !isEditor && !isMobile) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
export const range_date = (param: { data: any, name: any }) => {
|
||||||
|
const {data, name} = param;
|
||||||
|
let result = null as any;
|
||||||
|
Object.keys(data).map((e) => {
|
||||||
|
if (["lte", "gte", "gt", "lt"].includes(e)) {
|
||||||
|
if (data?.[e] instanceof Date) {
|
||||||
|
const today = data?.[e];
|
||||||
|
const day = new Date(today);
|
||||||
|
if (["lte", "lt"].includes(e)) {
|
||||||
|
day.setHours(23, 59, 59, 999); // Mengatur waktu ke 23:59:59
|
||||||
|
} else if (["gte", "gt"].includes(e)) {
|
||||||
|
day.setHours(0, 0, 0, 0); // Mengatur waktu ke 00:00:
|
||||||
|
}
|
||||||
|
result = {
|
||||||
|
...result,
|
||||||
|
[e]: day,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (result)
|
||||||
|
return {
|
||||||
|
[name]: result,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue