update 7 files
This commit is contained in:
parent
56388ed38a
commit
34fdaa0cf5
|
|
@ -9,6 +9,7 @@ import { TypeTag } from "./field/TypeTag";
|
||||||
import get from "lodash.get";
|
import get from "lodash.get";
|
||||||
import { getNumber } from "@/lib/utils/getNumber";
|
import { getNumber } from "@/lib/utils/getNumber";
|
||||||
import { useLocal } from "@/lib/utils/use-local";
|
import { useLocal } from "@/lib/utils/use-local";
|
||||||
|
import { FieldRadio } from "./field/TypeRadio";
|
||||||
|
|
||||||
export const Field: React.FC<any> = ({
|
export const Field: React.FC<any> = ({
|
||||||
fm,
|
fm,
|
||||||
|
|
@ -80,6 +81,17 @@ export const Field: React.FC<any> = ({
|
||||||
border: 0px !important;
|
border: 0px !important;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
`,
|
||||||
|
style === "gform" &&
|
||||||
|
css`
|
||||||
|
.field input {
|
||||||
|
padding-left: 0px !important;
|
||||||
|
padding-right: 0px !important;
|
||||||
|
}
|
||||||
|
.field textarea {
|
||||||
|
padding-left: 0px !important;
|
||||||
|
padding-right: 0px !important;
|
||||||
|
}
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -105,17 +117,26 @@ export const Field: React.FC<any> = ({
|
||||||
: "border border-gray-300 ",
|
: "border border-gray-300 ",
|
||||||
"relative field",
|
"relative field",
|
||||||
!is_disable
|
!is_disable
|
||||||
? style === "underline"
|
? style === "underline" || style === "gform"
|
||||||
? "focus-within:border-b focus-within:border-b-gray-500"
|
? "focus-within:border-b focus-within:border-b-primary"
|
||||||
: "focus-within:border focus-within:border-gray-500"
|
: "focus-within:border focus-within:border-primary"
|
||||||
: "",
|
: "",
|
||||||
|
style === "underline" || style === "gform"
|
||||||
style === "underline"
|
|
||||||
? "rounded-none border-transparent border-b-gray-300"
|
? "rounded-none border-transparent border-b-gray-300"
|
||||||
: "",
|
: "",
|
||||||
["rating", "color", "single-checkbox", "checkbox"].includes(type) &&
|
[
|
||||||
|
"rating",
|
||||||
|
"color",
|
||||||
|
"single-checkbox",
|
||||||
|
"radio",
|
||||||
|
"checkbox",
|
||||||
|
].includes(type) &&
|
||||||
css`
|
css`
|
||||||
border: 0px !important;
|
border: 0px !important;
|
||||||
|
`,
|
||||||
|
["upload"].includes(type) &&
|
||||||
|
css`
|
||||||
|
padding: 0px !important;
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -192,6 +213,18 @@ export const Field: React.FC<any> = ({
|
||||||
className={className}
|
className={className}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
) : ["radio"].includes(type) ? (
|
||||||
|
<>
|
||||||
|
<FieldRadio
|
||||||
|
fm={fm}
|
||||||
|
name={name}
|
||||||
|
onLoad={onLoad}
|
||||||
|
placeholder={placeholder}
|
||||||
|
disabled={is_disable}
|
||||||
|
onChange={onChange}
|
||||||
|
className={className}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
) : ["single-checkbox"].includes(type) ? (
|
) : ["single-checkbox"].includes(type) ? (
|
||||||
<>
|
<>
|
||||||
<FieldCheckbox
|
<FieldCheckbox
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ export const FieldCheckbox: FC<any> = ({
|
||||||
isChecked && "active"
|
isChecked && "active"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
<div className="text-primary">
|
||||||
{isChecked ? (
|
{isChecked ? (
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|
@ -140,6 +141,8 @@ export const FieldCheckbox: FC<any> = ({
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="">{item.label}</div>
|
<div className="">{item.label}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { useLocal } from "@/lib/utils/use-local";
|
||||||
import Datepicker from "../../ui/Datepicker";
|
import Datepicker from "../../ui/Datepicker";
|
||||||
import { Input } from "../../ui/input";
|
import { Input } from "../../ui/input";
|
||||||
import { Textarea } from "../../ui/text-area";
|
import { Textarea } from "../../ui/text-area";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import tinycolor from "tinycolor2";
|
import tinycolor from "tinycolor2";
|
||||||
import { FieldColorPicker } from "../../ui/FieldColorPopover";
|
import { FieldColorPicker } from "../../ui/FieldColorPopover";
|
||||||
import { FaRegStar, FaStar } from "react-icons/fa6";
|
import { FaRegStar, FaStar } from "react-icons/fa6";
|
||||||
|
|
@ -22,6 +22,7 @@ export const TypeInput: React.FC<any> = ({
|
||||||
className,
|
className,
|
||||||
}) => {
|
}) => {
|
||||||
const [hover, setHover] = useState(0); // State untuk menyimpan nilai hover
|
const [hover, setHover] = useState(0); // State untuk menyimpan nilai hover
|
||||||
|
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
|
||||||
|
|
||||||
let value: any = fm.data?.[name] || "";
|
let value: any = fm.data?.[name] || "";
|
||||||
const [rating, setRating] = useState(value); // State untuk menyimpan nilai rating
|
const [rating, setRating] = useState(value); // State untuk menyimpan nilai rating
|
||||||
|
|
@ -41,6 +42,13 @@ export const TypeInput: React.FC<any> = ({
|
||||||
rgbValue: "",
|
rgbValue: "",
|
||||||
selectedEd: "" as string,
|
selectedEd: "" as string,
|
||||||
});
|
});
|
||||||
|
const handleInput = () => {
|
||||||
|
const textarea = textareaRef.current;
|
||||||
|
if (textarea) {
|
||||||
|
textarea.style.height = "auto"; // Reset height to calculate new height
|
||||||
|
textarea.style.height = `${textarea.scrollHeight}px`; // Adjust height based on content
|
||||||
|
}
|
||||||
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (type === "color") {
|
if (type === "color") {
|
||||||
meta.inputValue = value || "";
|
meta.inputValue = value || "";
|
||||||
|
|
@ -66,7 +74,9 @@ export const TypeInput: React.FC<any> = ({
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Textarea
|
<Textarea
|
||||||
|
ref={textareaRef}
|
||||||
id={name}
|
id={name}
|
||||||
|
onInput={handleInput}
|
||||||
name={name}
|
name={name}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
required={required}
|
required={required}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
import { useLocal } from "@/lib/utils/use-local";
|
||||||
|
import { FC, useEffect } from "react";
|
||||||
|
import { ButtonBetter } from "../../ui/button";
|
||||||
|
import { IoRadioButtonOff, IoRadioButtonOn } from "react-icons/io5";
|
||||||
|
|
||||||
|
export const FieldRadio: FC<any> = ({
|
||||||
|
fm,
|
||||||
|
name,
|
||||||
|
onLoad,
|
||||||
|
onChange,
|
||||||
|
placeholder,
|
||||||
|
disabled,
|
||||||
|
className,
|
||||||
|
mode = "single",
|
||||||
|
}) => {
|
||||||
|
const local = useLocal({
|
||||||
|
list: [] as any[],
|
||||||
|
reload: async () => {
|
||||||
|
fm.fields[name] = { ...fm.fields?.[name], ...local };
|
||||||
|
fm.render();
|
||||||
|
const callback = (res: any[]) => {
|
||||||
|
if (Array.isArray(res)) {
|
||||||
|
local.list = res;
|
||||||
|
} else {
|
||||||
|
local.list = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
local.render();
|
||||||
|
};
|
||||||
|
const res = onLoad();
|
||||||
|
if (res instanceof Promise) res.then(callback);
|
||||||
|
else callback(res);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
useEffect(() => {
|
||||||
|
fm.fields[name] = { ...fm.fields?.[name], ...local };
|
||||||
|
const callback = (res: any[]) => {
|
||||||
|
if (Array.isArray(res)) {
|
||||||
|
local.list = res;
|
||||||
|
} else {
|
||||||
|
local.list = [];
|
||||||
|
}
|
||||||
|
local.render();
|
||||||
|
};
|
||||||
|
const res = onLoad();
|
||||||
|
if (res instanceof Promise) res.then(callback);
|
||||||
|
else callback(res);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
let value =
|
||||||
|
mode === "single" && typeof fm.data?.[name] === "string"
|
||||||
|
? [fm.data?.[name]]
|
||||||
|
: fm.data?.[name];
|
||||||
|
|
||||||
|
let is_tree = false;
|
||||||
|
const applyChanges = (selected: any[]) => {
|
||||||
|
selected = selected.filter((e) => e);
|
||||||
|
const val = selected.map((e) => e.value);
|
||||||
|
if (mode === "single") {
|
||||||
|
selected = val?.[0];
|
||||||
|
|
||||||
|
fm.data[name] = selected;
|
||||||
|
} else {
|
||||||
|
fm.data[name] = val;
|
||||||
|
}
|
||||||
|
fm.render();
|
||||||
|
|
||||||
|
if (typeof onChange === "function") {
|
||||||
|
onChange(fm.data[name]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={cx("flex items-center w-full flex-row")}>
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
`flex flex-col p-0.5 flex-1`,
|
||||||
|
!is_tree && "space-y-1 ",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{local.list.map((item, idx) => {
|
||||||
|
let isChecked = false;
|
||||||
|
try {
|
||||||
|
isChecked = value.some((e: any) => e === item.value);
|
||||||
|
} catch (ex) {}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={idx + "_checkbox"}
|
||||||
|
onClick={() => {
|
||||||
|
if (!disabled) {
|
||||||
|
let selected = Array.isArray(value)
|
||||||
|
? value.map((row) => {
|
||||||
|
return local.list.find((e) => e.value === row);
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
|
||||||
|
if (isChecked) {
|
||||||
|
selected = selected.filter(
|
||||||
|
(e: any) => e.value !== item.value
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (mode === "single") {
|
||||||
|
selected = [item];
|
||||||
|
} else {
|
||||||
|
selected.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
applyChanges(selected);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className={cx(
|
||||||
|
"text-sm opt-item flex flex-row gap-x-1 cursor-pointer items-center rounded-full p-0.5 ",
|
||||||
|
isChecked && "active"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{isChecked ? (
|
||||||
|
<IoRadioButtonOn className="text-primary" />
|
||||||
|
) : (
|
||||||
|
<IoRadioButtonOff className="text-primary" />
|
||||||
|
)}
|
||||||
|
<div className="">{item.label}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -179,13 +179,13 @@ export const FieldUploadSingle: FC<{
|
||||||
input.ref.click();
|
input.ref.click();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className="items-center flex text-base px-1 outline-none rounded cursor-pointer "
|
className="items-center flex text-base px-1 outline-none rounded cursor-pointer flex-row justify-center"
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center px-2">
|
<div className="flex flex-row items-center px-2">
|
||||||
<Upload className="h-4 w-4" />
|
<Upload className="h-4 w-4" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center text-md">
|
<div className="flex flex-row items-center text-sm">
|
||||||
Upload File
|
Add File
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -577,7 +577,9 @@ export const Typeahead: FC<{
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
placeholder={
|
placeholder={
|
||||||
local.mode === "multi" ? placeholder : valueLabel[0]?.label
|
local.mode === "multi"
|
||||||
|
? placeholder
|
||||||
|
: valueLabel[0]?.label || placeholder
|
||||||
}
|
}
|
||||||
type="text"
|
type="text"
|
||||||
ref={input}
|
ref={input}
|
||||||
|
|
|
||||||
|
|
@ -84,12 +84,7 @@ export const TableEditBetter: React.FC<any> = ({
|
||||||
local.render();
|
local.render();
|
||||||
},
|
},
|
||||||
removeRow: (row: any) => {
|
removeRow: (row: any) => {
|
||||||
// setData((prev) => prev.filter((item) => item !== row)); // Update state lokal
|
|
||||||
// local.data = local.data.filter((item: any) => item !== row); // Hapus row dari local.data
|
|
||||||
// local.render(); // Panggil render untuk memperbarui UI
|
|
||||||
console.log("HALOO");
|
|
||||||
const data = fm.data?.[name] || [];
|
const data = fm.data?.[name] || [];
|
||||||
// data.push(row);
|
|
||||||
if (delete_name) {
|
if (delete_name) {
|
||||||
const ids: any[] = Array.isArray(fm.data?.[delete_name])
|
const ids: any[] = Array.isArray(fm.data?.[delete_name])
|
||||||
? fm.data?.deleted_line_ids
|
? fm.data?.deleted_line_ids
|
||||||
|
|
@ -103,9 +98,6 @@ export const TableEditBetter: React.FC<any> = ({
|
||||||
fm.render();
|
fm.render();
|
||||||
local.data = fm.data[name];
|
local.data = fm.data[name];
|
||||||
local.render();
|
local.render();
|
||||||
console.log({ fm });
|
|
||||||
// local.data = fm.data[name];
|
|
||||||
// local.render();
|
|
||||||
},
|
},
|
||||||
reload: async () => {
|
reload: async () => {
|
||||||
toast.info(
|
toast.info(
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,17 @@ const MaskedInput: React.FC<MaskedInputProps> = ({
|
||||||
if (input.length > 5) {
|
if (input.length > 5) {
|
||||||
input = input.substring(0, 5);
|
input = input.substring(0, 5);
|
||||||
}
|
}
|
||||||
|
// Validasi batas maksimal jam
|
||||||
|
if (input.length === 5 && !input.includes("_")) {
|
||||||
|
const [hours, minutes] = input.split(":").map(Number);
|
||||||
|
|
||||||
|
// Koreksi jika jam atau menit melebihi batas
|
||||||
|
const correctedHours = Math.min(hours, 23);
|
||||||
|
const correctedMinutes = Math.min(minutes, 59);
|
||||||
|
input = `${String(correctedHours).padStart(2, "0")}:${String(
|
||||||
|
correctedMinutes
|
||||||
|
).padStart(2, "0")}`;
|
||||||
|
}
|
||||||
// Update state lokal
|
// Update state lokal
|
||||||
setLocalValue(input);
|
setLocalValue(input);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue