fix
This commit is contained in:
parent
15e1e983a5
commit
5022096c06
|
|
@ -41,6 +41,7 @@ export const BarChart: FC<{
|
|||
datasetIdKey="id"
|
||||
options={{
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins:
|
||||
legend === "none"
|
||||
? {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ interface Props {
|
|||
onClickNext: () => void;
|
||||
changeMonth: (month: number) => void;
|
||||
changeYear: (year: number) => void;
|
||||
mode?: "monthly" | "daily";
|
||||
}
|
||||
|
||||
const Calendar: React.FC<Props> = ({
|
||||
|
|
@ -53,6 +54,7 @@ const Calendar: React.FC<Props> = ({
|
|||
onClickNext,
|
||||
changeMonth,
|
||||
changeYear,
|
||||
mode = "daily",
|
||||
}) => {
|
||||
// Contexts
|
||||
const {
|
||||
|
|
@ -73,6 +75,12 @@ const Calendar: React.FC<Props> = ({
|
|||
const [showMonths, setShowMonths] = useState(false);
|
||||
const [showYears, setShowYears] = useState(false);
|
||||
const [year, setYear] = useState(date.year());
|
||||
useEffect(() => {
|
||||
if (mode === "monthly") {
|
||||
setShowMonths(true);
|
||||
hideYears();
|
||||
}
|
||||
}, []);
|
||||
// Functions
|
||||
const previous = useCallback(() => {
|
||||
return getLastDaysInMonth(
|
||||
|
|
@ -104,7 +112,12 @@ const Calendar: React.FC<Props> = ({
|
|||
(month: number) => {
|
||||
setTimeout(() => {
|
||||
changeMonth(month);
|
||||
if (mode === "daily") {
|
||||
setShowMonths(!showMonths);
|
||||
} else {
|
||||
hideDatepicker();
|
||||
clickDay(1,month + 1, date.year() );
|
||||
}
|
||||
}, 250);
|
||||
},
|
||||
[changeMonth, showMonths]
|
||||
|
|
@ -115,6 +128,10 @@ const Calendar: React.FC<Props> = ({
|
|||
setTimeout(() => {
|
||||
changeYear(year);
|
||||
setShowYears(!showYears);
|
||||
if (mode === "monthly") {
|
||||
setShowMonths(true);
|
||||
clickDay(1,date.month() + 1, year );
|
||||
}
|
||||
}, 250);
|
||||
},
|
||||
[changeYear, showYears]
|
||||
|
|
@ -125,7 +142,6 @@ const Calendar: React.FC<Props> = ({
|
|||
const fullDay = `${year}-${month}-${day}`;
|
||||
let newStart;
|
||||
let newEnd = null;
|
||||
|
||||
function chosePeriod(start: string, end: string) {
|
||||
const ipt = input?.current;
|
||||
changeDatepickerValue(
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ const Datepicker: React.FC<DatepickerType> = ({
|
|||
startWeekOn = "sun",
|
||||
classNames = undefined,
|
||||
popoverDirection = undefined,
|
||||
mode="daily"
|
||||
}) => {
|
||||
const local = useLocal({ open: false });
|
||||
// Ref
|
||||
|
|
@ -95,6 +96,7 @@ const Datepicker: React.FC<DatepickerType> = ({
|
|||
if (newDate.isSame(reformatDate) || newDate.isAfter(reformatDate)) {
|
||||
setSecondDate(nextMonth(date));
|
||||
}
|
||||
console.log(date)
|
||||
setFirstDate(date);
|
||||
},
|
||||
[secondDate]
|
||||
|
|
@ -110,6 +112,7 @@ const Datepicker: React.FC<DatepickerType> = ({
|
|||
|
||||
const changeFirstMonth = useCallback(
|
||||
(month: number) => {
|
||||
console.log("HALOOO")
|
||||
firstGotoDate(
|
||||
dayjs(`${firstDate.year()}-${month < 10 ? "0" : ""}${month}-01`)
|
||||
);
|
||||
|
|
@ -148,6 +151,7 @@ const Datepicker: React.FC<DatepickerType> = ({
|
|||
|
||||
const changeSecondMonth = useCallback(
|
||||
(month: number) => {
|
||||
console.log("ALOO")
|
||||
secondGotoDate(
|
||||
dayjs(`${secondDate.year()}-${month < 10 ? "0" : ""}${month}-01`)
|
||||
);
|
||||
|
|
@ -339,7 +343,9 @@ const Datepicker: React.FC<DatepickerType> = ({
|
|||
open={local.open}
|
||||
content={
|
||||
<div
|
||||
className={cx("c-text-sm 2xl:c-text-sm")}
|
||||
className={cx(
|
||||
"c-text-sm 2xl:c-text-sm",
|
||||
)}
|
||||
ref={calendarContainerRef}
|
||||
>
|
||||
<div className="c-flex c-flex-col lg:c-flex-row c-py-1">
|
||||
|
|
@ -356,6 +362,7 @@ const Datepicker: React.FC<DatepickerType> = ({
|
|||
onClickNext={nextMonthFirst}
|
||||
changeMonth={changeFirstMonth}
|
||||
changeYear={changeFirstYear}
|
||||
mode={mode}
|
||||
minDate={minDate}
|
||||
maxDate={maxDate}
|
||||
/>
|
||||
|
|
@ -372,6 +379,7 @@ const Datepicker: React.FC<DatepickerType> = ({
|
|||
onClickNext={nextMonthSecond}
|
||||
changeMonth={changeSecondMonth}
|
||||
changeYear={changeSecondYear}
|
||||
mode={mode}
|
||||
minDate={minDate}
|
||||
maxDate={maxDate}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ export interface DatepickerType {
|
|||
disabledDates?: DateRangeType[] | null;
|
||||
startWeekOn?: string | null;
|
||||
popoverDirection?: PopoverDirectionType;
|
||||
mode?: "daily" | "monthly"
|
||||
}
|
||||
|
||||
export type ColorKeys = (typeof COLORS)[number]; // "blue" | "orange"
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ function PopoverArrow() {
|
|||
top: arrowY != null ? `${arrowY}px` : "",
|
||||
[staticSide]: "-4px",
|
||||
transform: "rotate(45deg)",
|
||||
cursor: "pointer"
|
||||
}}
|
||||
className={cx(
|
||||
"arrow",
|
||||
|
|
|
|||
|
|
@ -3,14 +3,16 @@ import { BaseForm } from "../form/base/BaseForm";
|
|||
import { FilterLocal } from "./utils/types";
|
||||
import { useLocal } from "lib/utils/use-local";
|
||||
import { getFilter } from "./utils/get-filter";
|
||||
import { FMLocal } from "lib/exports";
|
||||
|
||||
export const FilterContent: FC<{
|
||||
mode: string;
|
||||
filter: FilterLocal;
|
||||
onSubmit?: (form: FMLocal | null) => Promise<any>;
|
||||
PassProp: any;
|
||||
child: any;
|
||||
_item: PrasiItem;
|
||||
}> = ({ mode, filter, PassProp, child, _item }) => {
|
||||
}> = ({ mode, filter, PassProp, child, _item, onSubmit }) => {
|
||||
const internal = useLocal({});
|
||||
return (
|
||||
<div
|
||||
|
|
@ -97,9 +99,18 @@ export const FilterContent: FC<{
|
|||
>
|
||||
<BaseForm
|
||||
data={filter.data}
|
||||
on_submit={(form) => {
|
||||
const f = getFilter(filter.name);
|
||||
on_submit={async (form) => {
|
||||
if (typeof onSubmit === "function" && mode === "raw") {
|
||||
const data = await onSubmit(form.fm);
|
||||
if(typeof form.fm?.data === "object"){
|
||||
form.fm.data = {
|
||||
...form.fm.data,
|
||||
_where: data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const f = getFilter(filter.name);
|
||||
if (f) {
|
||||
for (const list of Object.values(f.list.ref)) {
|
||||
list.reload();
|
||||
|
|
@ -113,7 +124,9 @@ export const FilterContent: FC<{
|
|||
return (
|
||||
<>
|
||||
{!!(PassProp && child) && (
|
||||
<PassProp filter={filter}>{child}</PassProp>
|
||||
<PassProp filter={filter} fm={form.fm}>
|
||||
{child}
|
||||
</PassProp>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export const FilterField: FC<{
|
|||
internal.render_timeout = setTimeout(() => {
|
||||
filter_window.prasiContext.render();
|
||||
}, 500);
|
||||
}, [filter.form?.data[name]]);
|
||||
}, [filter.form]);
|
||||
|
||||
let show_modifier = filter.mode !== "inline";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useLocal } from "@/utils/use-local";
|
||||
import { FC, ReactNode } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { GenField } from "../form/typings";
|
||||
import { FMLocal, GenField } from "../form/typings";
|
||||
import { FilterContent } from "./FilterContent";
|
||||
import { getFilter } from "./utils/get-filter";
|
||||
import { default_filter_local } from "./utils/types";
|
||||
|
|
@ -16,6 +16,7 @@ type FilterProps = {
|
|||
mode: FilterMode;
|
||||
children?: ReactNode;
|
||||
onClose?: () => void;
|
||||
onSubmit?: (fm: FMLocal | null) => Promise<any>;
|
||||
PassProp: any;
|
||||
child: any;
|
||||
_item: PrasiItem;
|
||||
|
|
@ -31,6 +32,7 @@ export const MasterFilter: FC<FilterProps> = ({
|
|||
child,
|
||||
onClose,
|
||||
_item,
|
||||
onSubmit,
|
||||
}): ReactNode => {
|
||||
const filter = useLocal({ ...default_filter_local });
|
||||
filter.name = name;
|
||||
|
|
@ -74,6 +76,7 @@ export const MasterFilter: FC<FilterProps> = ({
|
|||
)}
|
||||
>
|
||||
<FilterContent
|
||||
onSubmit={onSubmit}
|
||||
PassProp={PassProp}
|
||||
child={child}
|
||||
mode={mode}
|
||||
|
|
@ -90,6 +93,7 @@ export const MasterFilter: FC<FilterProps> = ({
|
|||
return (
|
||||
<>
|
||||
<FilterContent
|
||||
onSubmit={onSubmit}
|
||||
PassProp={PassProp}
|
||||
_item={_item}
|
||||
child={child}
|
||||
|
|
|
|||
|
|
@ -5,20 +5,27 @@ import { softDeleteFilter } from "./soft-delete-filter";
|
|||
|
||||
export const filterWhere = (filter_name: string, p: any) => {
|
||||
const f = getFilter(filter_name);
|
||||
|
||||
let where: any = {};
|
||||
if (f) {
|
||||
let fields: GFCol[] = [];
|
||||
//
|
||||
if (p.gen__fields) {
|
||||
fields = parseGenField(p.gen__fields);
|
||||
}
|
||||
for (const pf of Object.values(f.filter.ref)) {
|
||||
if (pf.mode === "raw") {
|
||||
const data = pf.data?._where ? pf.data?._where : pf.data
|
||||
for (const [k, v] of Object.entries(data)) {
|
||||
where[k] = v;
|
||||
}
|
||||
} else {
|
||||
const w = parseSingleFilter(pf, fields);
|
||||
for (const [k, v] of Object.entries(w)) {
|
||||
where[k] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p && p.opt__feature && p.sft__fields && p.sft__type) {
|
||||
where = softDeleteFilter(where, {
|
||||
|
|
@ -27,6 +34,6 @@ export const filterWhere = (filter_name: string, p: any) => {
|
|||
type: p.sft__type,
|
||||
});
|
||||
}
|
||||
|
||||
console.log({where})
|
||||
return where;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -61,9 +61,9 @@ export const BaseForm = <T extends Record<string, any>>(
|
|||
return prop;
|
||||
};
|
||||
|
||||
form.createFm = () => {
|
||||
form.createFm = useCallback(() => {
|
||||
if (form.fm) {
|
||||
form.fm.data = form.data;
|
||||
form.fm.data = data;
|
||||
return form.fm;
|
||||
}
|
||||
let size = "full";
|
||||
|
|
@ -72,7 +72,7 @@ export const BaseForm = <T extends Record<string, any>>(
|
|||
size = "half";
|
||||
}
|
||||
form.fm = {
|
||||
data: form.data,
|
||||
data: data,
|
||||
props: { label_mode: "vertical" },
|
||||
error: {
|
||||
get: () => {
|
||||
|
|
@ -84,7 +84,7 @@ export const BaseForm = <T extends Record<string, any>>(
|
|||
render: form.render,
|
||||
} as any;
|
||||
return form.fm as any;
|
||||
};
|
||||
}, [data]);
|
||||
|
||||
form.fieldProps = (arg) => {
|
||||
return {
|
||||
|
|
@ -95,8 +95,8 @@ export const BaseForm = <T extends Record<string, any>>(
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
form.data = data;
|
||||
form.render();
|
||||
// form.data = data;
|
||||
// form.render();
|
||||
|
||||
if (form.internal.width === 0) {
|
||||
setTimeout(() => {
|
||||
|
|
@ -142,7 +142,9 @@ export const BaseForm = <T extends Record<string, any>>(
|
|||
form.render();
|
||||
}, 50);
|
||||
}
|
||||
|
||||
if (!form.fm) {
|
||||
form.fm = form.createFm();
|
||||
}
|
||||
return (
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { FMLocal, FieldLocal, FieldProp } from "../typings";
|
|||
|
||||
export const default_base_form_local = {
|
||||
status: "init" as "init" | "submitting" | "ready",
|
||||
data: {} as any,
|
||||
// data: {} as any,
|
||||
internal: {
|
||||
width: 0,
|
||||
init_render: 0,
|
||||
|
|
@ -23,7 +23,7 @@ type CreateFieldArg = {
|
|||
};
|
||||
|
||||
export type BaseFormLocal<T> = Omit<typeof default_base_form_local, "data"> & {
|
||||
data: T;
|
||||
// data: T;
|
||||
createArg: (arg: CreateFieldArg) => FieldProp;
|
||||
createField: (arg: CreateFieldArg) => FieldLocal;
|
||||
createFm: () => FMLocal;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export const Field: FC<FieldProp> = (arg) => {
|
|||
const { fm } = arg;
|
||||
const field = useField(arg);
|
||||
const name = field.name;
|
||||
const local = useLocal({ prev_val: fm.data[name] });
|
||||
const local = useLocal({ prev_val: fm.data?.[name] });
|
||||
|
||||
const w = field.width;
|
||||
|
||||
|
|
@ -29,14 +29,29 @@ export const Field: FC<FieldProp> = (arg) => {
|
|||
if (arg.on_change) {
|
||||
arg.on_change({ value: fm.data[name], name, fm });
|
||||
}
|
||||
if(!fm.events){
|
||||
fm.events = {
|
||||
on_change(name, new_value) {
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fm.events.on_change(name, fm.data[name]);
|
||||
fm.render();
|
||||
}
|
||||
}, [fm.data[name]]);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof arg.on_init === "function") {
|
||||
arg.on_init({ name, field });
|
||||
}
|
||||
}, [field]);
|
||||
if (field.status === "init" && !isEditor) return null;
|
||||
const errors = fm.error.get(name);
|
||||
let errors = fm.error.get(name);
|
||||
if(field.error){
|
||||
errors = [field.error]
|
||||
}
|
||||
const props = { ...arg.props };
|
||||
|
||||
let editorClassName = "";
|
||||
|
|
@ -45,6 +60,8 @@ export const Field: FC<FieldProp> = (arg) => {
|
|||
props.className.split(" ").find((e: string) => e.startsWith("s-")) || "";
|
||||
}
|
||||
|
||||
const disabled =
|
||||
typeof field.disabled === "function" ? field.disabled() : field.disabled;
|
||||
if (field.hidden) return <></>;
|
||||
|
||||
return (
|
||||
|
|
@ -72,7 +89,7 @@ export const Field: FC<FieldProp> = (arg) => {
|
|||
"c-flex-col c-space-y-1",
|
||||
css`
|
||||
.field-outer {
|
||||
border: 1px solid ${field.disabled ? "#ececeb" : "#cecece"};
|
||||
border: 1px solid ${disabled ? "#ececeb" : "#cecece"};
|
||||
|
||||
&.focused {
|
||||
border: 1px solid #1c4ed8;
|
||||
|
|
@ -98,7 +115,7 @@ export const Field: FC<FieldProp> = (arg) => {
|
|||
{field.desc}
|
||||
</div>
|
||||
)}
|
||||
{errors.length > 0 && (
|
||||
{errors.length ? (
|
||||
<div
|
||||
className={cx(
|
||||
"field-error c-p-2 c-text-xs c-text-red-600",
|
||||
|
|
@ -109,7 +126,7 @@ export const Field: FC<FieldProp> = (arg) => {
|
|||
return <div>{err}</div>;
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
) : <></>}
|
||||
</div>
|
||||
</LabelDiv>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -6,13 +6,14 @@ export const Label: FC<{ field: FieldLocal; fm: FMLocal }> = ({
|
|||
fm,
|
||||
}) => {
|
||||
const errors = fm.error.get(field.name);
|
||||
|
||||
const disabled =
|
||||
typeof field.disabled === "function" ? field.disabled() : field.disabled;
|
||||
return (
|
||||
<div className={cx("label c-text-sm c-flex c-items-center", "c-mt-3")}>
|
||||
<span className={cx(errors.length > 0 && `c-text-red-600`)}>
|
||||
{field.label}
|
||||
</span>
|
||||
{field.required && !field.disabled && (
|
||||
{field.required && !disabled && (
|
||||
<span className="c-text-red-600 c-mb-2 c-ml-1">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
|
|||
|
|
@ -154,15 +154,10 @@ export const TableEdit: FC<{
|
|||
}
|
||||
return (
|
||||
<>
|
||||
|
||||
<div
|
||||
className={cx(
|
||||
`c-w-full c-h-full c-flex c-flex-col`,
|
||||
css`
|
||||
.rdg {
|
||||
overflow-y: hidden !important;
|
||||
height: var(--rdg-scroll-height) !important;
|
||||
}
|
||||
.rdg-cell > div {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
|
@ -172,9 +167,6 @@ export const TableEdit: FC<{
|
|||
padding-top: 0px;
|
||||
}
|
||||
}
|
||||
.field-error {
|
||||
display: none;
|
||||
}
|
||||
.rdg-header-row {
|
||||
border-top-right-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
|
|
@ -192,6 +184,7 @@ export const TableEdit: FC<{
|
|||
className={cx(
|
||||
"c-table-auto",
|
||||
css`
|
||||
height: 1px;
|
||||
border-collapse: collapse;
|
||||
table-layout: auto; /* Kolom akan menyesuaikan konten */
|
||||
`
|
||||
|
|
@ -241,7 +234,7 @@ export const TableEdit: FC<{
|
|||
{columns.map((header) => {
|
||||
return (
|
||||
<td>
|
||||
<div className="c-flex c-flex-row c-py-2 c-w-full">
|
||||
<div className="c-flex c-flex-row c-py-2 c-w-full c-h-full">
|
||||
{header.renderCell({
|
||||
props: {
|
||||
row: row,
|
||||
|
|
|
|||
|
|
@ -33,6 +33,24 @@ export const TypeDropdown: FC<{
|
|||
data: e.data,
|
||||
};
|
||||
});
|
||||
let v = typeof arg.opt_get_value === "function"
|
||||
? arg.opt_get_value({
|
||||
fm,
|
||||
name: field.name,
|
||||
options: local.options,
|
||||
type: field.type,
|
||||
})
|
||||
: fm.data[field.name];
|
||||
let f = list.find((ex) => ex.value === v);
|
||||
if(!f){
|
||||
arg.opt_set_value({
|
||||
fm,
|
||||
name: field.name,
|
||||
type: field.type,
|
||||
options: local.options,
|
||||
selected: [],
|
||||
});
|
||||
}
|
||||
local.options = list;
|
||||
} else {
|
||||
local.options = res;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ export type PropTypeInput = {
|
|||
| "file"
|
||||
| "search"
|
||||
| "password"
|
||||
| "import";
|
||||
| "import"
|
||||
| "monthly";
|
||||
placeholder?: string;
|
||||
onFocus?: (e: FocusEvent<HTMLDivElement>) => void;
|
||||
onBlur?: (e: FocusEvent<HTMLDivElement>) => void;
|
||||
|
|
@ -199,11 +200,34 @@ export const FieldTypeInput: FC<{
|
|||
value={{ startDate: value, endDate: value }}
|
||||
disabled={disabled}
|
||||
displayFormat="DD MMM YYYY"
|
||||
mode={"daily"}
|
||||
maxDate={field.max_date instanceof Date ? field.max_date : null}
|
||||
minDate={field.min_date instanceof Date ? field.min_date : null}
|
||||
asSingle={true}
|
||||
useRange={false}
|
||||
onChange={(value) => {
|
||||
console.log({ value });
|
||||
fm.data[field.name] = value?.startDate
|
||||
? new Date(value?.startDate)
|
||||
: null;
|
||||
renderOnChange();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
case "monthly": {
|
||||
return (
|
||||
<Datepicker
|
||||
value={{ startDate: value, endDate: value }}
|
||||
disabled={disabled}
|
||||
displayFormat="MMM YYYY"
|
||||
mode={"monthly"}
|
||||
maxDate={field.max_date instanceof Date ? field.max_date : null}
|
||||
minDate={field.min_date instanceof Date ? field.min_date : null}
|
||||
asSingle={true}
|
||||
useRange={false}
|
||||
onChange={(value) => {
|
||||
console.log({ value });
|
||||
fm.data[field.name] = value?.startDate
|
||||
? new Date(value?.startDate)
|
||||
: null;
|
||||
|
|
|
|||
|
|
@ -107,6 +107,10 @@ export type FieldProp = {
|
|||
current: any;
|
||||
options: { value: string; label: string; item?: any }[];
|
||||
}) => boolean;
|
||||
on_init: (arg: {
|
||||
field: any,
|
||||
name: string
|
||||
}) => void;
|
||||
pk: string;
|
||||
sub_type: string;
|
||||
placeholder: string;
|
||||
|
|
@ -188,6 +192,8 @@ export type FieldInternal<T extends FieldProp["type"]> = {
|
|||
prop?: any;
|
||||
max_date?: FieldProp["max_date"];
|
||||
min_date?: FieldProp["min_date"];
|
||||
error?: any;
|
||||
table_fields?: any[]
|
||||
};
|
||||
export type FieldLocal = FieldInternal<any> & {
|
||||
render: () => void;
|
||||
|
|
|
|||
|
|
@ -16,15 +16,14 @@ export const useField = (
|
|||
input: {},
|
||||
ref: null as any,
|
||||
} as any);
|
||||
const ref = useRef(null as any);
|
||||
const ref = useRef(null as any)
|
||||
field.ref = ref;
|
||||
|
||||
const name = typeof arg.name === "string" ? arg.name : arg.name();
|
||||
const label = typeof arg.label === "string" ? arg.label : arg.label();
|
||||
const required =
|
||||
typeof arg.required === "string" ? arg.required : arg.required();
|
||||
|
||||
if (field.status === "init" || isEditor) {
|
||||
for (const [k, v] of Object.entries({
|
||||
const update_field = {
|
||||
name: name.replace(/\s*/gi, ""),
|
||||
label: label,
|
||||
type: arg.type,
|
||||
|
|
@ -35,16 +34,15 @@ export const useField = (
|
|||
custom: arg.custom,
|
||||
required: required === "y",
|
||||
required_msg: arg.required_msg,
|
||||
disabled:
|
||||
typeof arg.disabled === "function"
|
||||
? arg.disabled
|
||||
: arg.disabled === "y",
|
||||
disabled: typeof arg.disabled === "function" ? arg.disabled : arg.disabled === "y",
|
||||
on_change: arg.on_change,
|
||||
max_date: arg.max_date,
|
||||
min_date: arg.min_date,
|
||||
options: {},
|
||||
reload_options: () => {},
|
||||
})) {
|
||||
table_fields: []
|
||||
};
|
||||
|
||||
if (field.status === "init" || isEditor) {
|
||||
for (const [k, v] of Object.entries(update_field)) {
|
||||
(field as any)[k] = v;
|
||||
}
|
||||
}
|
||||
|
|
@ -54,6 +52,9 @@ export const useField = (
|
|||
useEffect(() => {
|
||||
if (field.status === "init" || !fm.fields[name]) {
|
||||
field.status = "ready";
|
||||
if(!fm.fields){
|
||||
fm.fields = {}
|
||||
}
|
||||
fm.fields[name] = field;
|
||||
field.render();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,7 +183,6 @@ export const TableList: FC<TableListProp> = ({
|
|||
let should_set = true;
|
||||
const gf = JSON.stringify(gen_fields);
|
||||
const fields = fields_map.get(gf);
|
||||
|
||||
if (fields) {
|
||||
const rel = fields?.find((e) => e.name === columnKey);
|
||||
if (rel && rel.checked) {
|
||||
|
|
@ -196,9 +195,7 @@ export const TableList: FC<TableListProp> = ({
|
|||
},
|
||||
};
|
||||
} else {
|
||||
const field = rel.checked.find(
|
||||
(e) => !e.is_pk && !e.relation
|
||||
);
|
||||
const field = rel.checked.find((e) => !e.is_pk);
|
||||
if (field) {
|
||||
local.sort.orderBy = {
|
||||
[columnKey]: {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
|
||||
import { cn } from "@/utils"
|
||||
const ScrollArea = React.forwardRef<
|
||||
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<ScrollAreaPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn("c-relative c-overflow-hidden", className)}
|
||||
{...props}
|
||||
>
|
||||
<ScrollAreaPrimitive.Viewport className="c-h-full c-w-full c-rounded-[inherit]">
|
||||
{children}
|
||||
</ScrollAreaPrimitive.Viewport>
|
||||
<ScrollBar />
|
||||
<ScrollAreaPrimitive.Corner />
|
||||
</ScrollAreaPrimitive.Root>
|
||||
))
|
||||
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
|
||||
|
||||
const ScrollBar = React.forwardRef<
|
||||
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
|
||||
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||
>(({ className, orientation = "vertical", ...props }, ref) => (
|
||||
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
||||
ref={ref}
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"c-flex c-touch-none c-select-none c-transition-colors",
|
||||
orientation === "vertical" &&
|
||||
"c-h-full c-w-2.5 c-border-l c-border-l-transparent c-p-[1px]",
|
||||
orientation === "horizontal" &&
|
||||
"c-h-2.5 c-flex-col c-border-t c-border-t-transparent c-p-[1px]",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<ScrollAreaPrimitive.ScrollAreaThumb className="c-relative c-flex-1 c-rounded-full c-bg-border" />
|
||||
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||
))
|
||||
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
|
||||
|
||||
export { ScrollArea, ScrollBar }
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
|
||||
import { cn } from "@/utils";
|
||||
|
||||
const Sheet = SheetPrimitive.Root;
|
||||
|
||||
const SheetTrigger = SheetPrimitive.Trigger;
|
||||
|
||||
const SheetClose = SheetPrimitive.Close;
|
||||
|
||||
const SheetPortal = SheetPrimitive.Portal;
|
||||
|
||||
const SheetOverlay = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Overlay>,
|
||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Overlay
|
||||
className={cn(
|
||||
"c-fixed c-inset-0 c-z-50 c-bg-black/80 data-[state=open]:c-animate-in data-[state=closed]:c-animate-out data-[state=closed]:c-fade-out-0 data-[state=open]:c-fade-in-0",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
/>
|
||||
));
|
||||
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
||||
|
||||
const sheetVariants = cva(
|
||||
"c-fixed c-z-50 c-gap-4 c-bg-background c-p-6 c-shadow-lg c-transition c-ease-in-out data-[state=closed]:c-duration-300 data-[state=open]:c-duration-500 data-[state=open]:c-animate-in data-[state=closed]:c-animate-out",
|
||||
{
|
||||
variants: {
|
||||
side: {
|
||||
top: "c-inset-x-0 c-top-0 c-border-b data-[state=closed]:c-slide-out-to-top data-[state=open]:c-slide-in-from-top",
|
||||
bottom:
|
||||
"c-inset-x-0 c-bottom-0 c-border-t data-[state=closed]:c-slide-out-to-bottom data-[state=open]:c-slide-in-from-bottom",
|
||||
left: "c-inset-y-0 c-left-0 c-h-full c-w-3/4 c-border-r data-[state=closed]:c-slide-out-to-left data-[state=open]:c-slide-in-from-left sm:c-max-w-sm",
|
||||
right:
|
||||
"c-inset-y-0 c-right-0 c-h-full c-w-3/4 c-border-l data-[state=closed]:c-slide-out-to-right data-[state=open]:c-slide-in-from-right sm:c-max-w-sm",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
side: "right",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
interface SheetContentProps
|
||||
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
||||
VariantProps<typeof sheetVariants> {}
|
||||
|
||||
const SheetContent = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Content>,
|
||||
SheetContentProps
|
||||
>(({ side = "right", className, children, ...props }, ref) => (
|
||||
<SheetPortal>
|
||||
<SheetPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(sheetVariants({ side }), className)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</SheetPrimitive.Content>
|
||||
</SheetPortal>
|
||||
));
|
||||
SheetContent.displayName = SheetPrimitive.Content.displayName;
|
||||
|
||||
const SheetHeader = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"c-flex c-flex-col c-space-y-2 c-text-center sm:c-text-left",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
SheetHeader.displayName = "SheetHeader";
|
||||
|
||||
const SheetFooter = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"c-flex c-flex-col-reverse sm:c-flex-row sm:c-justify-end sm:c-space-x-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
SheetFooter.displayName = "SheetFooter";
|
||||
|
||||
const SheetTitle = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Title>,
|
||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn("c-text-lg c-font-semibold c-text-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
||||
|
||||
const SheetDescription = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Description>,
|
||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("c-text-sm c-text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
||||
|
||||
export {
|
||||
Sheet,
|
||||
SheetPortal,
|
||||
SheetOverlay,
|
||||
SheetTrigger,
|
||||
SheetClose,
|
||||
SheetContent,
|
||||
SheetHeader,
|
||||
SheetFooter,
|
||||
SheetTitle,
|
||||
SheetDescription,
|
||||
};
|
||||
31
exports.tsx
31
exports.tsx
|
|
@ -1,10 +1,10 @@
|
|||
export { FieldLoading } from "@/comps/ui/field-loading";
|
||||
export { fetchLinkParams } from "./comps/form/field/type/TypeLink";
|
||||
export { prasi_gen } from "./gen/prasi_gen";
|
||||
export { guessLabel } from "./utils/guess-label";
|
||||
import { lazify, lazifyMany } from "@/utils/lazify";
|
||||
import __get from "lodash.get";
|
||||
import { sum } from "./utils/sum";
|
||||
export { guessLabel } from "./utils/guess-label";
|
||||
export { fetchLinkParams } from "./comps/form/field/type/TypeLink";
|
||||
export { prasi_gen } from "./gen/prasi_gen";
|
||||
|
||||
export const _sum = sum;
|
||||
export const _get = __get;
|
||||
|
|
@ -80,8 +80,8 @@ export const HeaderProfile = lazify(
|
|||
);
|
||||
|
||||
/** charts */
|
||||
export { PieChart } from "@/comps/charts/pie";
|
||||
export { BarChart } from "@/comps/charts/bar";
|
||||
export { PieChart } from "@/comps/charts/pie";
|
||||
// export { LineChart } from "@/comps/charts/line";
|
||||
|
||||
/** Generator */
|
||||
|
|
@ -98,11 +98,9 @@ export { generateForm } from "@/comps/form/gen/gen-form";
|
|||
export { validate as validateField } from "@/comps/form/utils/validate";
|
||||
export { sortTree, treePrefix } from "@/comps/list/utils/sort-tree";
|
||||
|
||||
export { getFilter } from "@/comps/filter/utils/get-filter";
|
||||
export {
|
||||
FMLocal,
|
||||
FieldTypeCustom,
|
||||
fieldType,
|
||||
formType,
|
||||
fieldType, FieldTypeCustom, FMLocal, formType
|
||||
} from "@/comps/form/typings";
|
||||
export { TableListType } from "@/comps/list/utils/typings";
|
||||
export { generateTableList as generateTableList } from "@/comps/md/gen/gen-table-list";
|
||||
|
|
@ -112,17 +110,15 @@ export { Button, FloatButton } from "@/comps/ui/button";
|
|||
export { FormatValue } from "@/utils/format-value";
|
||||
export { GetValue } from "@/utils/get-value";
|
||||
export { password } from "@/utils/password";
|
||||
export { prasi_events, call_prasi_events } from "lib/utils/prasi-events";
|
||||
export { getFilter } from "@/comps/filter/utils/get-filter";
|
||||
export { call_prasi_events, prasi_events } from "lib/utils/prasi-events";
|
||||
|
||||
/** Session */
|
||||
export { Login } from "@/preset/login/Login";
|
||||
export { generateLogin } from "@/preset/login/utils/generate";
|
||||
export { logout } from "@/preset/login/utils/logout";
|
||||
export {
|
||||
RG,
|
||||
UserSession,
|
||||
registerSession,
|
||||
registerSession, RG,
|
||||
UserSession
|
||||
} from "@/preset/login/utils/register";
|
||||
|
||||
export { Card } from "@/comps/custom/Card";
|
||||
|
|
@ -143,12 +139,15 @@ export { PanelTab } from "@/comps/tab/parts/PanelTab";
|
|||
export { Popup } from "@/comps/popup/PopUp";
|
||||
|
||||
export { Detail } from "@/comps/custom/Detail";
|
||||
export * from "@/comps/ui/input";
|
||||
export { ButtonUpload } from "@/preset/profile/ButtonUpload";
|
||||
export { Profile } from "@/preset/profile/Profile";
|
||||
export { generateProfile } from "@/preset/profile/utils/generate";
|
||||
export { formatTime, longDate, shortDate, timeAgo } from "@/utils/date";
|
||||
export { getPathname, getBasename } from "@/utils/pathname";
|
||||
|
||||
export * from "@/comps/ui/input";
|
||||
export { getBasename, getPathname } from "@/utils/pathname";
|
||||
|
||||
export { Flow } from "@/comps/ui/flow";
|
||||
// format money
|
||||
export { formatMoney } from "@/comps/form/field/type/TypeMoney";
|
||||
|
||||
export { ScrollArea } from "@/comps/ui/scroll-area";
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ export const FormatValue: FC<{
|
|||
|
||||
if (mode === "money") {
|
||||
if (isEmptyString(value)) return "-";
|
||||
return formatMoney(Number(value) || 0);
|
||||
return formatMoney(ceil_comma(Number(value) || 0));
|
||||
} else if (mode === "datetime") {
|
||||
if (!value || isEmptyString(value)) return "-";
|
||||
try {
|
||||
|
|
@ -120,7 +120,7 @@ export const FormatValue: FC<{
|
|||
}
|
||||
} else if (["float"].includes(field?.type as string)) {
|
||||
if (!value || isEmptyString(value)) return "-";
|
||||
return formatMoney(Number(value) || 0);
|
||||
return formatMoney(ceil_comma(Number(value) || 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -169,12 +169,13 @@ const timeAgo = (date: any) => {
|
|||
const daysPast = Math.floor(secondsPast / 86400);
|
||||
return `${daysPast} days ago`;
|
||||
} else {
|
||||
const year = date.getFullYear();
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, "0");
|
||||
const day = date.getDate().toString().padStart(2, "0");
|
||||
return `${day}-${month}-${year}`;
|
||||
return formatDate(dayjs(date), "DD MMMM YYYY");
|
||||
}
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
const ceil_comma = (number: number) => {
|
||||
if (!number) return 0;
|
||||
return Math.ceil(number * 100) / 100;
|
||||
};
|
||||
Loading…
Reference in New Issue