Refactor code to handle NaN and infinite values in

KpiCard and ProgressCircleChart components
This commit is contained in:
Pattadon 2023-11-26 01:13:32 +07:00
parent 779e45aa89
commit 75f194386f
6 changed files with 72 additions and 16 deletions

View File

@ -1,4 +1,11 @@
import { BadgeDelta, Card, Flex, Metric, ProgressBar, Text } from "@tremor/react";
import {
BadgeDelta,
Card,
Flex,
Metric,
ProgressBar,
Text,
} from "@tremor/react";
import { useEffect, useState } from "react";
import { axiosInstance } from "src/api/AxiosConfig";
@ -46,10 +53,16 @@ export function KpiCard() {
<div>
<Metric>{kpiCardData.completedThisWeek}</Metric>
</div>
<BadgeDelta deltaType={kpiCardData.incOrdec}>{kpiCardData.percentage.toFixed(0)}%</BadgeDelta>
<BadgeDelta deltaType={kpiCardData.incOrdec}>
{isNaN(kpiCardData.percentage) || !isFinite(kpiCardData.percentage)
? "0%"
: `${kpiCardData.percentage.toFixed(0)}%`}
</BadgeDelta>
</Flex>
<Flex className="mt-4">
<Text className="truncate">vs. {kpiCardData.completedLastWeek} (last week)</Text>
<Text className="truncate">
vs. {kpiCardData.completedLastWeek} (last week)
</Text>
</Flex>
<ProgressBar value={kpiCardData.percentage} className="mt-2" />
</Card>

View File

@ -33,9 +33,18 @@ export function ProgressCircleChart() {
return (
<Card className="max-w-lg mx-auto">
<Flex className="flex-col items-center">
<ProgressCircle className="mt-6" value={progressData} size={200} strokeWidth={10} radius={60} color="indigo">
<ProgressCircle
className="mt-6"
value={progressData}
size={200}
strokeWidth={10}
radius={60}
color="indigo"
>
<span className="h-12 w-12 rounded-full bg-indigo-100 flex items-center justify-center text-sm text-indigo-500 font-medium">
{progressData.toFixed(0)} %
{isNaN(progressData) || !isFinite(progressData)
? "0%"
: `${progressData.toFixed(0)}%`}
</span>
</ProgressCircle>
</Flex>

View File

@ -154,7 +154,9 @@ export function Dashboard() {
color="rose"
>
<span className="h-12 w-12 rounded-full bg-rose-100 flex items-center justify-center text-sm text-rose-500 font-medium">
{progressData.toFixed(0)} %
{isNaN(progressData) || !isFinite(progressData)
? "0%"
: `${progressData.toFixed(0)}%`}
</span>
</ProgressCircle>
<br></br>

View File

@ -1,6 +1,12 @@
import { useMemo, useState, useEffect } from "react";
import { ColumnContainerCard } from "./columnContainerWrapper";
import { DndContext, DragOverlay, PointerSensor, useSensor, useSensors } from "@dnd-kit/core";
import {
DndContext,
DragOverlay,
PointerSensor,
useSensor,
useSensors,
} from "@dnd-kit/core";
import { SortableContext, arrayMove } from "@dnd-kit/sortable";
import { createPortal } from "react-dom";
import { TaskCard } from "./taskCard";
@ -26,7 +32,9 @@ export function KanbanBoard() {
// ---------------- Task Handlers ----------------
const handleTaskUpdate = (tasks, updatedTask) => {
const updatedTasks = tasks.map((task) => (task.id === updatedTask.id ? updatedTask : task));
const updatedTasks = tasks.map((task) =>
task.id === updatedTask.id ? updatedTask : task
);
setTasks(updatedTasks);
};
@ -168,8 +176,14 @@ export function KanbanBoard() {
justify-center
overflow-x-auto
overflow-y-hidden
">
<DndContext sensors={sensors} onDragStart={onDragStart} onDragEnd={onDragEnd} onDragOver={onDragOver}>
"
>
<DndContext
sensors={sensors}
onDragStart={onDragStart}
onDragEnd={onDragEnd}
onDragOver={onDragOver}
>
<div className="flex gap-4">
<div className="flex gap-4">
{!isLoading ? (
@ -181,7 +195,9 @@ export function KanbanBoard() {
createTask={createTask}
deleteTask={deleteTask}
updateTask={updateTask}
tasks={(tasks || []).filter((task) => task.columnId === col.id)}
tasks={(tasks || []).filter(
(task) => task.columnId === col.id
)}
/>
))}{" "}
</SortableContext>
@ -194,7 +210,11 @@ export function KanbanBoard() {
{createPortal(
<DragOverlay className="bg-white" dropAnimation={null} zIndex={20}>
{/* Render the active task as a draggable overlay */}
<TaskCard task={activeTask} deleteTask={deleteTask} updateTask={updateTask} />
<TaskCard
task={activeTask}
deleteTask={deleteTask}
updateTask={updateTask}
/>
</DragOverlay>,
document.body
)}
@ -302,7 +322,11 @@ export function KanbanBoard() {
const isOverAColumn = over.data.current?.type === "Column";
// Move the Task to a different column and update columnId
if (isActiveATask && isOverAColumn && tasks.some((task) => task.columnId !== overId)) {
if (
isActiveATask &&
isOverAColumn &&
tasks.some((task) => task.columnId !== overId)
) {
setTasks((tasks) => {
const activeIndex = tasks.findIndex((t) => t.id === activeId);
axiosInstance

View File

@ -1,4 +1,5 @@
import { useState } from "react";
import { useEffect } from "react";
import { BsFillTrashFill } from "react-icons/bs";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
@ -6,6 +7,9 @@ import { TaskDetailModal } from "./taskDetailModal";
export function TaskCard({ task, deleteTask, updateTask }) {
const [mouseIsOver, setMouseIsOver] = useState(false);
// console.log(task.challenge);
// console.log(task.importance);
// console.log(task.difficulty);
const { setNodeRef, attributes, listeners, transform, transition, isDragging } = useSortable({
id: task.id,
@ -14,12 +18,13 @@ export function TaskCard({ task, deleteTask, updateTask }) {
task,
},
});
const style = {
transition,
transform: CSS.Transform.toString(transform),
};
{
/* If card is dragged */
}
@ -60,7 +65,7 @@ export function TaskCard({ task, deleteTask, updateTask }) {
setMouseIsOver(false);
}}>
<p
className="p-2.5 my-auto w-full overflow-y-auto overflow-x-hidden whitespace-pre-wrap rounded-xl shadow bg-white"
className={`p-2.5 my-auto w-full overflow-y-auto overflow-x-hidden whitespace-pre-wrap rounded-xl shadow bg-white`}
onClick={() => document.getElementById(`task_detail_modal_${task.id}`).showModal()}>
{task.content}
</p>

View File

@ -7,6 +7,9 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
const [isChallengeChecked, setChallengeChecked] = useState(challenge);
const [isImportantChecked, setImportantChecked] = useState(importance);
const [currentDifficulty, setCurrentDifficulty] = useState(difficulty);
// console.log(currentDifficulty);
// console.log(isChallengeChecked);
// console.log(isImportantChecked);
const handleChallengeChange = () => {
setChallengeChecked(!isChallengeChecked);