160 lines
4.0 KiB
TypeScript
Executable File
160 lines
4.0 KiB
TypeScript
Executable File
import { useLocal } from "@/utils/use-local";
|
|
import get from "lodash.get";
|
|
import { FC, ReactNode, useEffect, useRef } from "react";
|
|
import { FMLocal } from "../form/Form";
|
|
import { createPortal, render } from "react-dom";
|
|
import { Label } from "@/comps/ui/label";
|
|
import { Input } from "@/comps/ui/input";
|
|
|
|
type FilterPosition = 'regular' | 'inline' | 'popup';
|
|
|
|
type FilterForm = {
|
|
gen_fields: GenField[];
|
|
gen_table: string;
|
|
name: string;
|
|
value: any;
|
|
position: FilterPosition;
|
|
children?: ReactNode;
|
|
onClose?: () => void;
|
|
};
|
|
|
|
type GenField = {
|
|
name: string,
|
|
is_pk: boolean,
|
|
type: string,
|
|
optional: boolean
|
|
};
|
|
|
|
export const MasterFilter: FC<FilterForm> = ({ gen_fields, gen_table, name, value, position, children, onClose }): ReactNode => {
|
|
const local = useLocal({
|
|
data: [] as any[],
|
|
columns: [] as string[],
|
|
fields: [] as GenField[],
|
|
tableName: "",
|
|
isGenerated: false,
|
|
// fm: {} as FMLocal,
|
|
argInit: {} as { fm: FMLocal; submit: any; reload: any },
|
|
argOnLoad: {} as { arg: { fm: FMLocal } },
|
|
argOnSubmit: {} as {
|
|
arg: {
|
|
fm: FMLocal;
|
|
form: any;
|
|
error: any;
|
|
}
|
|
}
|
|
});
|
|
useEffect(() => {
|
|
if (!isEditor) {
|
|
const w = window as any;
|
|
if (typeof w["prasi_filter"] !== "object") w["prasi_filter"] = {};
|
|
if (typeof w["prasi_filter"][name] !== "object")
|
|
w["prasi_filter"][name] = {};
|
|
const val = value();
|
|
w["prasi_filter"][name] = {
|
|
...w["prasi_filter"][name],
|
|
...val
|
|
};
|
|
w.prasiContext.render();
|
|
}
|
|
}, [])
|
|
|
|
const renderContent = (): ReactNode => (
|
|
<div className={`filter-content filter-${position}`}>
|
|
<h3>Filter</h3>
|
|
<form>
|
|
{local.fields.map((field) => (
|
|
<div>
|
|
{field.type === 'varchar' && (
|
|
<div className="grid w-full max-w-sm items-center gap-1.5" >
|
|
<Label htmlFor={field.name}>{field.name}</Label>
|
|
<Input id={field.name} type="text" />
|
|
</div>
|
|
)}
|
|
{field.type === "number" && (
|
|
<div className="grid w-full max-w-sm items-center gap-1.5" >
|
|
<Label htmlFor={field.name}>{field.name}</Label>
|
|
<Input id={field.name} type="number" />
|
|
</div>
|
|
)}
|
|
</div>
|
|
))}
|
|
</form >
|
|
</div >
|
|
);
|
|
|
|
const generateFilter = () => {
|
|
local.isGenerated = true;
|
|
local.tableName = gen_table;
|
|
gen_fields.forEach((data: any) => {
|
|
local.fields.push(JSON.parse(data));
|
|
});
|
|
local.render();
|
|
console.log('tableName', local.tableName);
|
|
console.log('fields', local.fields);
|
|
};
|
|
|
|
if (position === 'popup') {
|
|
let popup = document.querySelector(".main-content-preview > .portal");
|
|
if (!popup) {
|
|
popup = document.createElement("div");
|
|
popup.classList.add("portal");
|
|
|
|
const main = document.querySelector(".main-content-preview");
|
|
if (main) {
|
|
main.appendChild(popup);
|
|
}
|
|
}
|
|
return (
|
|
<>
|
|
{createPortal(
|
|
<div
|
|
onClick={onClose}
|
|
className={cx(
|
|
css`
|
|
position: absolute;
|
|
top: 0;
|
|
bottom: 0;
|
|
right: 0;
|
|
left: 0;
|
|
background: white;
|
|
z-index: 100;
|
|
`,
|
|
"c-flex c-flex-col"
|
|
)}
|
|
>
|
|
{renderContent()}
|
|
</div>,
|
|
popup
|
|
)}
|
|
</>
|
|
);
|
|
}
|
|
|
|
if (local.isGenerated) {
|
|
return renderContent();
|
|
} else {
|
|
return (
|
|
<div>
|
|
<button
|
|
onClick={generateFilter}
|
|
style={{
|
|
backgroundColor: "#4CAF50",
|
|
border: "none",
|
|
color: "white",
|
|
padding: "15px 32px",
|
|
textAlign: "center",
|
|
textDecoration: "none",
|
|
display: "inline-block",
|
|
fontSize: "16px",
|
|
margin: "4px 2px",
|
|
cursor: "pointer",
|
|
borderRadius: "10px",
|
|
}}
|
|
>
|
|
Generate
|
|
</button>
|
|
</div >
|
|
)
|
|
}
|
|
};
|