fix lib
This commit is contained in:
parent
3d810d5d41
commit
2122f74cc3
|
|
@ -1,11 +1,11 @@
|
||||||
import { useLocal } from "@/utils/use-local";
|
import { useLocal } from "@/utils/use-local";
|
||||||
|
import { call_prasi_events } from "lib/exports";
|
||||||
import { FC, useEffect } from "react";
|
import { FC, useEffect } from "react";
|
||||||
import { FieldProp } from "../typings";
|
import { FieldProp } from "../typings";
|
||||||
import { useField } from "../utils/use-field";
|
import { useField } from "../utils/use-field";
|
||||||
|
import { validate } from "../utils/validate";
|
||||||
import { FieldInput } from "./FieldInput";
|
import { FieldInput } from "./FieldInput";
|
||||||
import { Label } from "./Label";
|
import { Label } from "./Label";
|
||||||
import { validate } from "../utils/validate";
|
|
||||||
import { call_prasi_events } from "lib/exports";
|
|
||||||
|
|
||||||
export const Field: FC<FieldProp> = (arg) => {
|
export const Field: FC<FieldProp> = (arg) => {
|
||||||
const showlabel = arg.show_label || "y";
|
const showlabel = arg.show_label || "y";
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ export const FieldTypeInput: FC<{
|
||||||
|
|
||||||
// let value: any = "2024-05-14T05:58:01.376Z" // case untuk date time
|
// let value: any = "2024-05-14T05:58:01.376Z" // case untuk date time
|
||||||
field.input = input;
|
field.input = input;
|
||||||
field.prop = prop;
|
if (!field.prop) field.prop = prop;
|
||||||
if (["date", "datetime", "datetime-local", "time"].includes(type_field)) {
|
if (["date", "datetime", "datetime-local", "time"].includes(type_field)) {
|
||||||
if (typeof value === "string" || value instanceof Date) {
|
if (typeof value === "string" || value instanceof Date) {
|
||||||
let date = parse(value);
|
let date = parse(value);
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,11 @@
|
||||||
import { useLocal } from "@/utils/use-local";
|
import { useLocal } from "@/utils/use-local";
|
||||||
import get from "lodash.get";
|
import get from "lodash.get";
|
||||||
|
import { Loader2, Paperclip, Trash2, Upload } from "lucide-react";
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { FMLocal, FieldLocal, FieldProp } from "../../typings";
|
|
||||||
import { PropTypeInput } from "./TypeInput";
|
|
||||||
import * as XLSX from "xlsx";
|
import * as XLSX from "xlsx";
|
||||||
import {
|
import { FMLocal, FieldLocal, FieldProp } from "../../typings";
|
||||||
ArrowDownToLine,
|
|
||||||
ExternalLink,
|
|
||||||
Loader2,
|
|
||||||
Paperclip,
|
|
||||||
SquareArrowOutUpRight,
|
|
||||||
Trash2,
|
|
||||||
Upload,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { Spinner } from "lib/comps/ui/field-loading";
|
|
||||||
import { FilePreview } from "./FilePreview";
|
import { FilePreview } from "./FilePreview";
|
||||||
|
import { PropTypeInput } from "./TypeInput";
|
||||||
const w = window as unknown as {
|
const w = window as unknown as {
|
||||||
serverurl: string;
|
serverurl: string;
|
||||||
};
|
};
|
||||||
|
|
@ -27,264 +18,6 @@ export const FieldUpload: FC<{
|
||||||
arg: FieldProp;
|
arg: FieldProp;
|
||||||
on_change: (e: any) => void | Promise<void>;
|
on_change: (e: any) => void | Promise<void>;
|
||||||
}> = ({ field, fm, prop, on_change, arg }) => {
|
}> = ({ field, fm, prop, on_change, arg }) => {
|
||||||
const styling = arg.upload_style ? arg.upload_style : "full";
|
console.log(field.prop.upload);
|
||||||
let type_field = prop.sub_type;
|
return <></>;
|
||||||
let value: any = fm.data[field.name];
|
|
||||||
// let type_upload =
|
|
||||||
const input = useLocal({
|
|
||||||
value: 0 as any,
|
|
||||||
display: false as any,
|
|
||||||
ref: null as any,
|
|
||||||
drop: false as boolean,
|
|
||||||
fase: value ? "preview" : ("start" as "start" | "upload" | "preview"),
|
|
||||||
style: "inline" as "inline" | "full",
|
|
||||||
});
|
|
||||||
|
|
||||||
const on_upload = async (event: any) => {
|
|
||||||
let file = null;
|
|
||||||
try {
|
|
||||||
file = event.target.files[0];
|
|
||||||
} catch (ex) {}
|
|
||||||
if (type_field === "import") {
|
|
||||||
const reader = new FileReader();
|
|
||||||
|
|
||||||
reader.onload = (e: any) => {
|
|
||||||
const binaryStr = e.target.result;
|
|
||||||
const workbook = XLSX.read(binaryStr, { type: "binary" });
|
|
||||||
|
|
||||||
const worksheet = workbook.Sheets[workbook.SheetNames[0]];
|
|
||||||
const jsonData = XLSX.utils.sheet_to_json(worksheet);
|
|
||||||
if (typeof on_change === "function") {
|
|
||||||
const res = on_change({
|
|
||||||
value: jsonData,
|
|
||||||
file: file,
|
|
||||||
binnary: e.target.result,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
reader.readAsBinaryString(file);
|
|
||||||
} else {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append("file", file);
|
|
||||||
|
|
||||||
let url = siteurl("/_upload");
|
|
||||||
if (
|
|
||||||
location.hostname === "prasi.avolut.com" ||
|
|
||||||
location.host === "localhost:4550"
|
|
||||||
) {
|
|
||||||
const newurl = new URL(location.href);
|
|
||||||
newurl.pathname = `/_proxy/${url}`;
|
|
||||||
url = newurl.toString();
|
|
||||||
}
|
|
||||||
input.fase = "upload";
|
|
||||||
input.render();
|
|
||||||
try {
|
|
||||||
const response = await fetch(url, {
|
|
||||||
method: "POST",
|
|
||||||
body: formData,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
const contentType: any = response.headers.get("content-type");
|
|
||||||
let result;
|
|
||||||
if (contentType.includes("application/json")) {
|
|
||||||
result = await response.json();
|
|
||||||
} else if (contentType.includes("text/plain")) {
|
|
||||||
result = await response.text();
|
|
||||||
} else {
|
|
||||||
result = await response.blob();
|
|
||||||
}
|
|
||||||
if (Array.isArray(result)) {
|
|
||||||
fm.data[field.name] = `_file${get(result, "[0]")}`;
|
|
||||||
fm.render();
|
|
||||||
setTimeout(() => {
|
|
||||||
input.fase = "preview";
|
|
||||||
input.render();
|
|
||||||
}, 1000);
|
|
||||||
} else {
|
|
||||||
input.fase = "start";
|
|
||||||
input.render();
|
|
||||||
alert("Error upload");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
|
||||||
input.fase = "start";
|
|
||||||
input.render();
|
|
||||||
alert("Error upload");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (input.ref) {
|
|
||||||
input.ref.value = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isEditor) input.fase = "start";
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="c-flex-grow c-flex-row c-flex c-w-full c-h-full c-items-stretch">
|
|
||||||
{input.fase === "start" ? (
|
|
||||||
<>
|
|
||||||
<div
|
|
||||||
className={cx(
|
|
||||||
"c-flex c-flex-row c-relative c-flex-grow c-items-center c-cursor-pointer hover:c-bg-blue-50",
|
|
||||||
css`
|
|
||||||
input[type="file"],
|
|
||||||
input[type="file"]::-webkit-file-upload-button {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{!isEditor && (
|
|
||||||
<input
|
|
||||||
ref={(ref) => (input.ref = ref)}
|
|
||||||
type="file"
|
|
||||||
multiple={false}
|
|
||||||
onChange={on_upload}
|
|
||||||
className={cx(
|
|
||||||
"c-absolute c-w-full c-h-full c-cursor-pointer c-top-0 c-left-0 c-opacity-0"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{styling !== "full" ? (
|
|
||||||
<>
|
|
||||||
<div
|
|
||||||
onClick={() => {
|
|
||||||
if (input.ref) {
|
|
||||||
console.log(input.ref);
|
|
||||||
input.ref.click();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className="c-items-center c-flex c-text-base c-px-3 c-outline-none c-rounded c-cursor-pointer "
|
|
||||||
>
|
|
||||||
<div className="c-flex c-flex-row c-items-center c-px-2">
|
|
||||||
<Upload className="c-h-4 c-w-4" />
|
|
||||||
</div>
|
|
||||||
<div className="c-flex c-flex-row c-items-center">
|
|
||||||
Upload File
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<div
|
|
||||||
onDrop={(e: any) => {
|
|
||||||
e.preventDefault();
|
|
||||||
input.drop = false;
|
|
||||||
input.render();
|
|
||||||
}}
|
|
||||||
onDragOver={(e: any) => {
|
|
||||||
// Prevent default behavior (Prevent file from being opened)
|
|
||||||
e.preventDefault();
|
|
||||||
input.drop = true;
|
|
||||||
input.render();
|
|
||||||
}}
|
|
||||||
className={cx(
|
|
||||||
input.drop ? "c-bg-gray-100" : "",
|
|
||||||
"hover:c-bg-gray-100 c-flex-grow c-m-1 c-relative c-flex-grow c-p-4 c-items-center c-flex c-flex-row c-text-gray-400 c-border c-border-gray-200 c-border-dashed c-rounded c-cursor-pointer"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div className="c-flex-row c-flex c-flex-grow c-space-x-2">
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 14 14"
|
|
||||||
>
|
|
||||||
<g
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
>
|
|
||||||
<path d="M3.5 13.5h-2a1 1 0 0 1-1-1v-8h13v8a1 1 0 0 1-1 1h-2" />
|
|
||||||
<path d="M4.5 10L7 7.5L9.5 10M7 7.5v6M11.29 1a1 1 0 0 0-.84-.5h-6.9a1 1 0 0 0-.84.5L.5 4.5h13zM7 .5v4" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
<div className="c-flex c-flex-col">
|
|
||||||
<span className="c-font-medium">
|
|
||||||
Drop Your File or{" "}
|
|
||||||
<span className="c-underline c-text-blue-500">
|
|
||||||
Browse
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
) : input.fase === "upload" ? (
|
|
||||||
<div className="c-flex c-items-center">
|
|
||||||
<div className="c-px-2">
|
|
||||||
<Loader2 className={cx("c-h-5 c-w-5 c-animate-spin")} />
|
|
||||||
</div>
|
|
||||||
<div className="">Uploading</div>
|
|
||||||
</div>
|
|
||||||
) : input.fase === "preview" ? (
|
|
||||||
<div className="c-flex c-justify-between c-flex-1 c-p-1">
|
|
||||||
<FilePreview url={value || ""} />
|
|
||||||
<div className="c-flex c-flex-row c-items-center c-border c-px-2 c-rounded c-cursor-pointer hover:c-bg-red-100">
|
|
||||||
<Trash2
|
|
||||||
className="c-text-red-500 c-h-4 c-w-4"
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
if (confirm("Clear this file ?")) {
|
|
||||||
input.fase = "start";
|
|
||||||
fm.data[field.name] = null;
|
|
||||||
fm.render();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const IconFile: FC<{ type: string }> = ({ type }) => {
|
|
||||||
if (["xlsx"].includes(type)) {
|
|
||||||
return (
|
|
||||||
<div className="c-flex c-flex-row c-text-[#2a801d]">
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fill="currentColor"
|
|
||||||
d="m2.859 2.877l12.57-1.795a.5.5 0 0 1 .571.494v20.848a.5.5 0 0 1-.57.494L2.858 21.123a1 1 0 0 1-.859-.99V3.867a1 1 0 0 1 .859-.99M17 3h4a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1h-4zm-6.8 9L13 8h-2.4L9 10.286L7.4 8H5l2.8 4L5 16h2.4L9 13.714L10.6 16H13z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<div className="c-flex c-flex-row ">
|
|
||||||
<Paperclip className="c-h-5 c-w-5" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className="c-flex c-flex-row c-p-2">
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fill="currentColor"
|
|
||||||
d="m2.859 2.877l12.57-1.795a.5.5 0 0 1 .571.494v20.848a.5.5 0 0 1-.57.494L2.858 21.123a1 1 0 0 1-.859-.99V3.867a1 1 0 0 1 .859-.99M17 3h4a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1h-4zm-6.8 9L13 8h-2.4L9 10.286L7.4 8H5l2.8 4L5 16h2.4L9 13.714L10.6 16H13z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,281 @@
|
||||||
|
import { useLocal } from "@/utils/use-local";
|
||||||
|
import get from "lodash.get";
|
||||||
|
import { Loader2, Paperclip, Trash2, Upload } from "lucide-react";
|
||||||
|
import { FC } from "react";
|
||||||
|
import * as XLSX from "xlsx";
|
||||||
|
import { FMLocal, FieldLocal, FieldProp } from "../../typings";
|
||||||
|
import { FilePreview } from "./FilePreview";
|
||||||
|
import { PropTypeInput } from "./TypeInput";
|
||||||
|
const w = window as unknown as {
|
||||||
|
serverurl: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FieldUploadSingle: FC<{
|
||||||
|
field: FieldLocal;
|
||||||
|
fm: FMLocal;
|
||||||
|
prop: PropTypeInput;
|
||||||
|
styling?: string;
|
||||||
|
arg: FieldProp;
|
||||||
|
on_change: (e: any) => void | Promise<void>;
|
||||||
|
}> = ({ field, fm, prop, on_change, arg }) => {
|
||||||
|
const styling = arg.upload_style ? arg.upload_style : "full";
|
||||||
|
let type_field = prop.sub_type;
|
||||||
|
let value: any = fm.data[field.name];
|
||||||
|
// let type_upload =
|
||||||
|
const input = useLocal({
|
||||||
|
value: 0 as any,
|
||||||
|
display: false as any,
|
||||||
|
ref: null as any,
|
||||||
|
drop: false as boolean,
|
||||||
|
fase: value ? "preview" : ("start" as "start" | "upload" | "preview"),
|
||||||
|
style: "inline" as "inline" | "full",
|
||||||
|
});
|
||||||
|
|
||||||
|
const on_upload = async (event: any) => {
|
||||||
|
let file = null;
|
||||||
|
try {
|
||||||
|
file = event.target.files[0];
|
||||||
|
} catch (ex) {}
|
||||||
|
if (type_field === "import") {
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onload = (e: any) => {
|
||||||
|
const binaryStr = e.target.result;
|
||||||
|
const workbook = XLSX.read(binaryStr, { type: "binary" });
|
||||||
|
|
||||||
|
const worksheet = workbook.Sheets[workbook.SheetNames[0]];
|
||||||
|
const jsonData = XLSX.utils.sheet_to_json(worksheet);
|
||||||
|
if (typeof on_change === "function") {
|
||||||
|
const res = on_change({
|
||||||
|
value: jsonData,
|
||||||
|
file: file,
|
||||||
|
binnary: e.target.result,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.readAsBinaryString(file);
|
||||||
|
} else {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("file", file);
|
||||||
|
|
||||||
|
let url = siteurl("/_upload");
|
||||||
|
if (
|
||||||
|
location.hostname === "prasi.avolut.com" ||
|
||||||
|
location.host === "localhost:4550"
|
||||||
|
) {
|
||||||
|
const newurl = new URL(location.href);
|
||||||
|
newurl.pathname = `/_proxy/${url}`;
|
||||||
|
url = newurl.toString();
|
||||||
|
}
|
||||||
|
input.fase = "upload";
|
||||||
|
input.render();
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const contentType: any = response.headers.get("content-type");
|
||||||
|
let result;
|
||||||
|
if (contentType.includes("application/json")) {
|
||||||
|
result = await response.json();
|
||||||
|
} else if (contentType.includes("text/plain")) {
|
||||||
|
result = await response.text();
|
||||||
|
} else {
|
||||||
|
result = await response.blob();
|
||||||
|
}
|
||||||
|
if (Array.isArray(result)) {
|
||||||
|
fm.data[field.name] = `_file${get(result, "[0]")}`;
|
||||||
|
fm.render();
|
||||||
|
setTimeout(() => {
|
||||||
|
input.fase = "preview";
|
||||||
|
input.render();
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
input.fase = "start";
|
||||||
|
input.render();
|
||||||
|
alert("Error upload");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
} catch (ex) {
|
||||||
|
input.fase = "start";
|
||||||
|
input.render();
|
||||||
|
alert("Error upload");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (input.ref) {
|
||||||
|
input.ref.value = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isEditor) input.fase = "start";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="c-flex-grow c-flex-row c-flex c-w-full c-h-full c-items-stretch">
|
||||||
|
{input.fase === "start" ? (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
"c-flex c-flex-row c-relative c-flex-grow c-items-center c-cursor-pointer hover:c-bg-blue-50",
|
||||||
|
css`
|
||||||
|
input[type="file"],
|
||||||
|
input[type="file"]::-webkit-file-upload-button {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{!isEditor && (
|
||||||
|
<input
|
||||||
|
ref={(ref) => (input.ref = ref)}
|
||||||
|
type="file"
|
||||||
|
multiple={false}
|
||||||
|
onChange={on_upload}
|
||||||
|
className={cx(
|
||||||
|
"c-absolute c-w-full c-h-full c-cursor-pointer c-top-0 c-left-0 c-opacity-0"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{styling !== "full" ? (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
if (input.ref) {
|
||||||
|
console.log(input.ref);
|
||||||
|
input.ref.click();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="c-items-center c-flex c-text-base c-px-1 c-outline-none c-rounded c-cursor-pointer "
|
||||||
|
>
|
||||||
|
<div className="c-flex c-flex-row c-items-center c-px-2">
|
||||||
|
<Upload className="c-h-4 c-w-4" />
|
||||||
|
</div>
|
||||||
|
<div className="c-flex c-flex-row c-items-center">
|
||||||
|
Upload File
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
onDrop={(e: any) => {
|
||||||
|
e.preventDefault();
|
||||||
|
input.drop = false;
|
||||||
|
input.render();
|
||||||
|
}}
|
||||||
|
onDragOver={(e: any) => {
|
||||||
|
// Prevent default behavior (Prevent file from being opened)
|
||||||
|
e.preventDefault();
|
||||||
|
input.drop = true;
|
||||||
|
input.render();
|
||||||
|
}}
|
||||||
|
className={cx(
|
||||||
|
input.drop ? "c-bg-gray-100" : "",
|
||||||
|
"hover:c-bg-gray-100 c-flex-grow c-m-1 c-relative c-flex-grow c-p-4 c-items-center c-flex c-flex-row c-text-gray-400 c-border c-border-gray-200 c-border-dashed c-rounded c-cursor-pointer"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="c-flex-row c-flex c-flex-grow c-space-x-2">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 14 14"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M3.5 13.5h-2a1 1 0 0 1-1-1v-8h13v8a1 1 0 0 1-1 1h-2" />
|
||||||
|
<path d="M4.5 10L7 7.5L9.5 10M7 7.5v6M11.29 1a1 1 0 0 0-.84-.5h-6.9a1 1 0 0 0-.84.5L.5 4.5h13zM7 .5v4" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<div className="c-flex c-flex-col">
|
||||||
|
<span className="c-font-medium">
|
||||||
|
Drop Your File or{" "}
|
||||||
|
<span className="c-underline c-text-blue-500">
|
||||||
|
Browse
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : input.fase === "upload" ? (
|
||||||
|
<div className="c-flex c-items-center">
|
||||||
|
<div className="c-px-2">
|
||||||
|
<Loader2 className={cx("c-h-5 c-w-5 c-animate-spin")} />
|
||||||
|
</div>
|
||||||
|
<div className="">Uploading</div>
|
||||||
|
</div>
|
||||||
|
) : input.fase === "preview" ? (
|
||||||
|
<div className="c-flex c-justify-between c-flex-1 c-p-1">
|
||||||
|
<FilePreview url={value || ""} />
|
||||||
|
<div className="c-flex c-flex-row c-items-center c-border c-px-2 c-rounded c-cursor-pointer hover:c-bg-red-100">
|
||||||
|
<Trash2
|
||||||
|
className="c-text-red-500 c-h-4 c-w-4"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
if (confirm("Clear this file ?")) {
|
||||||
|
input.fase = "start";
|
||||||
|
fm.data[field.name] = null;
|
||||||
|
fm.render();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const IconFile: FC<{ type: string }> = ({ type }) => {
|
||||||
|
if (["xlsx"].includes(type)) {
|
||||||
|
return (
|
||||||
|
<div className="c-flex c-flex-row c-text-[#2a801d]">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m2.859 2.877l12.57-1.795a.5.5 0 0 1 .571.494v20.848a.5.5 0 0 1-.57.494L2.858 21.123a1 1 0 0 1-.859-.99V3.867a1 1 0 0 1 .859-.99M17 3h4a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1h-4zm-6.8 9L13 8h-2.4L9 10.286L7.4 8H5l2.8 4L5 16h2.4L9 13.714L10.6 16H13z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div className="c-flex c-flex-row ">
|
||||||
|
<Paperclip className="c-h-5 c-w-5" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="c-flex c-flex-row c-p-2">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m2.859 2.877l12.57-1.795a.5.5 0 0 1 .571.494v20.848a.5.5 0 0 1-.57.494L2.858 21.123a1 1 0 0 1-.859-.99V3.867a1 1 0 0 1 .859-.99M17 3h4a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1h-4zm-6.8 9L13 8h-2.4L9 10.286L7.4 8H5l2.8 4L5 16h2.4L9 13.714L10.6 16H13z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -48,6 +48,7 @@ export type FieldProp = {
|
||||||
label: string;
|
label: string;
|
||||||
desc?: string;
|
desc?: string;
|
||||||
props?: any;
|
props?: any;
|
||||||
|
upload?: { mode: "single-file" | "multi-file" };
|
||||||
link: {
|
link: {
|
||||||
text:
|
text:
|
||||||
| string
|
| string
|
||||||
|
|
@ -107,10 +108,7 @@ export type FieldProp = {
|
||||||
current: any;
|
current: any;
|
||||||
options: { value: string; label: string; item?: any }[];
|
options: { value: string; label: string; item?: any }[];
|
||||||
}) => boolean;
|
}) => boolean;
|
||||||
on_init: (arg: {
|
on_init: (arg: { field: any; name: string }) => void;
|
||||||
field: any,
|
|
||||||
name: string
|
|
||||||
}) => void;
|
|
||||||
pk: string;
|
pk: string;
|
||||||
sub_type: string;
|
sub_type: string;
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
|
|
@ -189,11 +187,11 @@ export type FieldInternal<T extends FieldProp["type"]> = {
|
||||||
name: string;
|
name: string;
|
||||||
fm: FMLocal;
|
fm: FMLocal;
|
||||||
}) => void | Promise<void>;
|
}) => void | Promise<void>;
|
||||||
prop?: any;
|
prop?: FieldProp;
|
||||||
max_date?: FieldProp["max_date"];
|
max_date?: FieldProp["max_date"];
|
||||||
min_date?: FieldProp["min_date"];
|
min_date?: FieldProp["min_date"];
|
||||||
error?: any;
|
error?: any;
|
||||||
table_fields?: any[]
|
table_fields?: any[];
|
||||||
};
|
};
|
||||||
export type FieldLocal = FieldInternal<any> & {
|
export type FieldLocal = FieldInternal<any> & {
|
||||||
render: () => void;
|
render: () => void;
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ export const useField = (
|
||||||
input: {},
|
input: {},
|
||||||
ref: null as any,
|
ref: null as any,
|
||||||
} as any);
|
} as any);
|
||||||
const ref = useRef(null as any)
|
const ref = useRef(null as any);
|
||||||
field.ref = ref;
|
field.ref = ref;
|
||||||
|
|
||||||
const name = typeof arg.name === "string" ? arg.name : arg.name();
|
const name = typeof arg.name === "string" ? arg.name : arg.name();
|
||||||
|
|
@ -34,11 +34,12 @@ export const useField = (
|
||||||
custom: arg.custom,
|
custom: arg.custom,
|
||||||
required: required === "y",
|
required: required === "y",
|
||||||
required_msg: arg.required_msg,
|
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,
|
on_change: arg.on_change,
|
||||||
max_date: arg.max_date,
|
max_date: arg.max_date,
|
||||||
min_date: arg.min_date,
|
min_date: arg.min_date,
|
||||||
table_fields: []
|
table_fields: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (field.status === "init" || isEditor) {
|
if (field.status === "init" || isEditor) {
|
||||||
|
|
@ -53,12 +54,13 @@ export const useField = (
|
||||||
if (field.status === "init" || !fm.fields[name]) {
|
if (field.status === "init" || !fm.fields[name]) {
|
||||||
field.status = "ready";
|
field.status = "ready";
|
||||||
if (!fm.fields) {
|
if (!fm.fields) {
|
||||||
fm.fields = {}
|
fm.fields = {};
|
||||||
}
|
}
|
||||||
fm.fields[name] = field;
|
fm.fields[name] = field;
|
||||||
field.render();
|
field.render();
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
field.prop = arg;
|
||||||
|
|
||||||
return field;
|
return field;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ const form = lazifyMany({
|
||||||
Form: async () => (await import("@/comps/form/Form")).Form,
|
Form: async () => (await import("@/comps/form/Form")).Form,
|
||||||
Field: async () => (await import("@/comps/form/field/Field")).Field,
|
Field: async () => (await import("@/comps/form/field/Field")).Field,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const Form = form.Form;
|
export const Form = form.Form;
|
||||||
export const Field = form.Field;
|
export const Field = form.Field;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue