update 7 files

This commit is contained in:
faisolavolut 2025-02-06 07:20:05 +07:00
parent 65b84b16ca
commit f98c4cd871
9 changed files with 212 additions and 78 deletions

View File

@ -154,7 +154,7 @@ export const Field: React.FC<any> = ({
css` css`
height: 2.13rem; height: 2.13rem;
`, `,
is_disable ? "" : "" is_disable ? "bg-gray-200/50 " : "bg-gray-200/50 "
)} )}
> >
{before} {before}

View File

@ -1,7 +1,7 @@
"use client"; "use client";
import { useLocal } from "@/lib/utils/use-local"; import { useLocal } from "@/lib/utils/use-local";
import { AlertTriangle, Check, Loader2 } from "lucide-react"; import { AlertTriangle, Check, Loader2 } from "lucide-react";
import { ReactNode, useEffect, useState } from "react"; import { useEffect } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import { import {
ResizableHandle, ResizableHandle,
@ -71,7 +71,7 @@ export const Form: React.FC<any> = ({
</div> </div>
</div> </div>
); );
}, 1000); }, 100);
} catch (ex: any) { } catch (ex: any) {
const msg = get(ex, "response.data.meta.message") || ex.message; const msg = get(ex, "response.data.meta.message") || ex.message;
toast.error( toast.error(
@ -117,22 +117,26 @@ export const Form: React.FC<any> = ({
); );
local.data = null; local.data = null;
local.render(); local.render();
const res = onLoad(); const res = await onLoad();
if (res instanceof Promise) { local.ready = true;
res.then((data) => { local.data = res;
local.ready = true; local.render();
local.data = data; toast.dismiss();
local.render(); // Panggil render setelah data diperbarui // if (res instanceof Promise) {
// toast.dismiss(); // res.then((data) => {
// toast.success("Data Loaded Successfully!"); // local.ready = true;
}); // local.data = data;
} else { // local.render(); // Panggil render setelah data diperbarui
local.ready = true; // // toast.dismiss();
local.data = res; // // toast.success("Data Loaded Successfully!");
local.render(); // Panggil render untuk memicu re-render // });
toast.dismiss(); // } else {
toast.success("Data Loaded Successfully!"); // local.ready = true;
} // local.data = res;
// local.render(); // Panggil render untuk memicu re-render
// toast.dismiss();
// toast.success("Data Loaded Successfully!");
// }
}, },
fields: {} as any, fields: {} as any,
render: () => {}, render: () => {},
@ -144,48 +148,56 @@ export const Form: React.FC<any> = ({
local.onChange(); local.onChange();
}, [local.data]); }, [local.data]);
useEffect(() => { useEffect(() => {
if (typeof onInit === "function") { const run = async () => {
onInit(local); if (typeof onInit === "function") {
} onInit(local);
local.ready = false; }
local.render(); local.ready = false;
toast.info( local.render();
<> toast.info(
<Loader2 <>
className={cx( <Loader2
"h-4 w-4 animate-spin-important", className={cx(
css` "h-4 w-4 animate-spin-important",
animation: spin 1s linear infinite !important; css`
@keyframes spin { animation: spin 1s linear infinite !important;
0% { @keyframes spin {
transform: rotate(0deg); 0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
} }
100% { `
transform: rotate(360deg); )}
} />
} {"Loading..."}
` </>
)} );
/> const res = await onLoad();
{"Loading..."}
</>
);
const res = onLoad();
if (res instanceof Promise) {
res.then((data) => {
local.ready = true;
local.data = data;
local.render(); // Panggil render setelah data diperbarui
// toast.dismiss();
// toast.success("Data Loaded Successfully!");
});
} else {
local.ready = true; local.ready = true;
local.data = res; local.data = res;
local.render(); // Panggil render untuk memicu re-render local.render(); // Panggil render setelah data diperbarui
toast.dismiss(); toast.dismiss();
toast.success("Data Loaded Successfully!"); // if (res instanceof Promise) {
} // res.then((data) => {
// local.ready = true;
// local.data = data;
// local.render(); // Panggil render setelah data diperbarui
// toast.dismiss();
// // toast.success("Data Loaded Successfully!");
// });
// } else {
// local.ready = true;
// local.data = res;
// local.render(); // Panggil render untuk memicu re-render
// toast.dismiss();
// toast.success("Data Loaded Successfully!");
// }
};
run();
}, []); }, []);
// Tambahkan dependency ke header agar reaktif // Tambahkan dependency ke header agar reaktif

View File

@ -69,9 +69,6 @@ export const TypeInput: React.FC<any> = ({
} else if (type === "time") { } else if (type === "time") {
if (fm.data?.[name]) fm.data[name] = convertToTimeOnly(fm.data[name]); if (fm.data?.[name]) fm.data[name] = convertToTimeOnly(fm.data[name]);
fm.render(); fm.render();
console.log({
data: fm.data,
});
} else { } else {
setRating(value ? value - 1 : value); setRating(value ? value - 1 : value);
} }

View File

@ -139,7 +139,7 @@ export const TableList: React.FC<any> = ({
setData(res); setData(res);
setTimeout(() => { setTimeout(() => {
toast.dismiss(); toast.dismiss();
}, 1000); }, 100);
} }
}, },
}); });

31
components/ui/bar.tsx Normal file
View File

@ -0,0 +1,31 @@
import { FC } from "react";
import { Bar } from "react-chartjs-2";
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend,
ChartOptions,
ChartData,
} from "chart.js";
ChartJS.register(
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend
);
const BarChart: FC<{ data: ChartData<"bar">; option: ChartOptions<"bar"> }> = ({
data,
option,
}) => {
return <Bar data={data} options={option} />;
};
export default BarChart;

View File

@ -1,6 +1,6 @@
import * as React from "react" import * as React from "react";
import { cn } from "@/lib/utils/utils" import { cn } from "@/lib/utils/utils";
const Card = React.forwardRef< const Card = React.forwardRef<
HTMLDivElement, HTMLDivElement,
@ -14,8 +14,8 @@ const Card = React.forwardRef<
)} )}
{...props} {...props}
/> />
)) ));
Card.displayName = "Card" Card.displayName = "Card";
const CardHeader = React.forwardRef< const CardHeader = React.forwardRef<
HTMLDivElement, HTMLDivElement,
@ -26,8 +26,8 @@ const CardHeader = React.forwardRef<
className={cn("flex flex-col space-y-1.5 p-6", className)} className={cn("flex flex-col space-y-1.5 p-6", className)}
{...props} {...props}
/> />
)) ));
CardHeader.displayName = "CardHeader" CardHeader.displayName = "CardHeader";
const CardTitle = React.forwardRef< const CardTitle = React.forwardRef<
HTMLDivElement, HTMLDivElement,
@ -38,8 +38,8 @@ const CardTitle = React.forwardRef<
className={cn("font-semibold leading-none tracking-tight", className)} className={cn("font-semibold leading-none tracking-tight", className)}
{...props} {...props}
/> />
)) ));
CardTitle.displayName = "CardTitle" CardTitle.displayName = "CardTitle";
const CardDescription = React.forwardRef< const CardDescription = React.forwardRef<
HTMLDivElement, HTMLDivElement,
@ -50,16 +50,16 @@ const CardDescription = React.forwardRef<
className={cn("text-sm text-muted-foreground", className)} className={cn("text-sm text-muted-foreground", className)}
{...props} {...props}
/> />
)) ));
CardDescription.displayName = "CardDescription" CardDescription.displayName = "CardDescription";
const CardContent = React.forwardRef< const CardContent = React.forwardRef<
HTMLDivElement, HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} /> <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
)) ));
CardContent.displayName = "CardContent" CardContent.displayName = "CardContent";
const CardFooter = React.forwardRef< const CardFooter = React.forwardRef<
HTMLDivElement, HTMLDivElement,
@ -70,7 +70,25 @@ const CardFooter = React.forwardRef<
className={cn("flex items-center p-6 pt-0", className)} className={cn("flex items-center p-6 pt-0", className)}
{...props} {...props}
/> />
)) ));
CardFooter.displayName = "CardFooter"
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } const CardBetter: React.FC<any> = ({ children, className }) => {
return (
<Card className={className}>
<CardContent className="flex flex-grow flex-col p-0">
{children}
</CardContent>
</Card>
);
};
CardFooter.displayName = "CardFooter";
export {
Card,
CardBetter,
CardHeader,
CardFooter,
CardTitle,
CardDescription,
CardContent,
};

View File

@ -0,0 +1,75 @@
import { FC } from "react";
import { Doughnut } from "react-chartjs-2";
import {
Chart as ChartJS,
ArcElement,
Title,
Tooltip,
Legend,
ChartOptions,
Chart as ChartInstance,
Plugin,
} from "chart.js";
ChartJS.register(ArcElement, Title, Tooltip, Legend);
interface ProgressChartProps {
percentage: number;
color?: string;
backgroundColor?: string;
options: ChartOptions<"doughnut">;
}
const ProgressChart: FC<ProgressChartProps> = ({
percentage,
options,
color = "#6366F1",
backgroundColor = "#E0E7FF",
}) => {
const data = {
datasets: [
{
data: [percentage, 100 - percentage],
backgroundColor: [color, "transparent"],
borderWidth: 0,
borderRadius: [10, 0],
cutout: "70%",
},
],
};
const backgroundCircle: Plugin<"doughnut"> = {
id: "backgroundCircle",
beforeDatasetsDraw(chart: ChartInstance, args: any, pluginOptions: any) {
const { ctx } = chart;
ctx.save();
const meta = chart.getDatasetMeta(0);
if (!meta || meta.data.length === 0) return;
const arc = meta.data[0] as any; // Pastikan ini adalah elemen arc
const xCoor = arc.x;
const yCoor = arc.y;
const innerRadius = arc.innerRadius || 0;
const outerRadius = arc.outerRadius || 0;
const width = outerRadius - innerRadius;
const angle = Math.PI / 180;
ctx.beginPath();
ctx.lineWidth = width;
ctx.strokeStyle = backgroundColor;
ctx.arc(xCoor, yCoor, outerRadius - width / 2, 0, angle * 360, false);
ctx.stroke();
ctx.restore();
},
};
return (
<div className="relative w-24 h-24">
<Doughnut data={data} options={options} plugins={[backgroundCircle]} />
<div className="absolute inset-0 flex items-center justify-center text-black font-bold">
+{percentage}%
</div>
</div>
);
};
export default ProgressChart;

View File

@ -12,8 +12,7 @@ export const userToken = async () => {
`${process.env.NEXT_PUBLIC_API_PORTAL}/api/check-jwt-token` `${process.env.NEXT_PUBLIC_API_PORTAL}/api/check-jwt-token`
); );
const jwt = res.data.data; const jwt = res.data.data;
console.log({ jwt }); if (!jwt) return navigate(`${process.env.NEXT_PUBLIC_API_PORTAL}/login`);
if (!jwt) return;
try { try {
await api.post(process.env.NEXT_PUBLIC_BASE_URL + "/api/cookies", { await api.post(process.env.NEXT_PUBLIC_BASE_URL + "/api/cookies", {
token: jwt, token: jwt,

View File

@ -34,6 +34,7 @@
"@types/lodash.uniqby": "^4.7.9", "@types/lodash.uniqby": "^4.7.9",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"axios": "^1.7.8", "axios": "^1.7.8",
"chart.js": "^4.4.7",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"classnames": "^2.5.1", "classnames": "^2.5.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
@ -52,6 +53,7 @@
"lucide-react": "^0.462.0", "lucide-react": "^0.462.0",
"next": "15.0.3", "next": "15.0.3",
"react-beautiful-dnd": "^13.1.1", "react-beautiful-dnd": "^13.1.1",
"react-chartjs-2": "^5.3.0",
"react-colorful": "^5.6.1", "react-colorful": "^5.6.1",
"react-icons": "^5.3.0", "react-icons": "^5.3.0",
"react-resizable": "^3.0.5", "react-resizable": "^3.0.5",