mirror of
https://github.com/TurTaskProject/TurTaskWeb.git
synced 2025-12-19 22:14:07 +01:00
Refactor code to handle NaN and infinite values in
KpiCard and ProgressCircleChart components
This commit is contained in:
parent
779e45aa89
commit
75f194386f
@ -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 { useEffect, useState } from "react";
|
||||||
import { axiosInstance } from "src/api/AxiosConfig";
|
import { axiosInstance } from "src/api/AxiosConfig";
|
||||||
|
|
||||||
@ -46,10 +53,16 @@ export function KpiCard() {
|
|||||||
<div>
|
<div>
|
||||||
<Metric>{kpiCardData.completedThisWeek}</Metric>
|
<Metric>{kpiCardData.completedThisWeek}</Metric>
|
||||||
</div>
|
</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>
|
||||||
<Flex className="mt-4">
|
<Flex className="mt-4">
|
||||||
<Text className="truncate">vs. {kpiCardData.completedLastWeek} (last week)</Text>
|
<Text className="truncate">
|
||||||
|
vs. {kpiCardData.completedLastWeek} (last week)
|
||||||
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<ProgressBar value={kpiCardData.percentage} className="mt-2" />
|
<ProgressBar value={kpiCardData.percentage} className="mt-2" />
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@ -33,9 +33,18 @@ export function ProgressCircleChart() {
|
|||||||
return (
|
return (
|
||||||
<Card className="max-w-lg mx-auto">
|
<Card className="max-w-lg mx-auto">
|
||||||
<Flex className="flex-col items-center">
|
<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">
|
<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>
|
</span>
|
||||||
</ProgressCircle>
|
</ProgressCircle>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@ -154,7 +154,9 @@ export function Dashboard() {
|
|||||||
color="rose"
|
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">
|
<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>
|
</span>
|
||||||
</ProgressCircle>
|
</ProgressCircle>
|
||||||
<br></br>
|
<br></br>
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
import { useMemo, useState, useEffect } from "react";
|
import { useMemo, useState, useEffect } from "react";
|
||||||
import { ColumnContainerCard } from "./columnContainerWrapper";
|
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 { SortableContext, arrayMove } from "@dnd-kit/sortable";
|
||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
import { TaskCard } from "./taskCard";
|
import { TaskCard } from "./taskCard";
|
||||||
@ -26,7 +32,9 @@ export function KanbanBoard() {
|
|||||||
|
|
||||||
// ---------------- Task Handlers ----------------
|
// ---------------- Task Handlers ----------------
|
||||||
const handleTaskUpdate = (tasks, updatedTask) => {
|
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);
|
setTasks(updatedTasks);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -168,8 +176,14 @@ export function KanbanBoard() {
|
|||||||
justify-center
|
justify-center
|
||||||
overflow-x-auto
|
overflow-x-auto
|
||||||
overflow-y-hidden
|
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">
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
{!isLoading ? (
|
{!isLoading ? (
|
||||||
@ -181,7 +195,9 @@ export function KanbanBoard() {
|
|||||||
createTask={createTask}
|
createTask={createTask}
|
||||||
deleteTask={deleteTask}
|
deleteTask={deleteTask}
|
||||||
updateTask={updateTask}
|
updateTask={updateTask}
|
||||||
tasks={(tasks || []).filter((task) => task.columnId === col.id)}
|
tasks={(tasks || []).filter(
|
||||||
|
(task) => task.columnId === col.id
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
))}{" "}
|
))}{" "}
|
||||||
</SortableContext>
|
</SortableContext>
|
||||||
@ -194,7 +210,11 @@ export function KanbanBoard() {
|
|||||||
{createPortal(
|
{createPortal(
|
||||||
<DragOverlay className="bg-white" dropAnimation={null} zIndex={20}>
|
<DragOverlay className="bg-white" dropAnimation={null} zIndex={20}>
|
||||||
{/* Render the active task as a draggable overlay */}
|
{/* Render the active task as a draggable overlay */}
|
||||||
<TaskCard task={activeTask} deleteTask={deleteTask} updateTask={updateTask} />
|
<TaskCard
|
||||||
|
task={activeTask}
|
||||||
|
deleteTask={deleteTask}
|
||||||
|
updateTask={updateTask}
|
||||||
|
/>
|
||||||
</DragOverlay>,
|
</DragOverlay>,
|
||||||
document.body
|
document.body
|
||||||
)}
|
)}
|
||||||
@ -302,7 +322,11 @@ export function KanbanBoard() {
|
|||||||
|
|
||||||
const isOverAColumn = over.data.current?.type === "Column";
|
const isOverAColumn = over.data.current?.type === "Column";
|
||||||
// Move the Task to a different column and update columnId
|
// 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) => {
|
setTasks((tasks) => {
|
||||||
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
||||||
axiosInstance
|
axiosInstance
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { useEffect } from "react";
|
||||||
import { BsFillTrashFill } from "react-icons/bs";
|
import { BsFillTrashFill } from "react-icons/bs";
|
||||||
import { useSortable } from "@dnd-kit/sortable";
|
import { useSortable } from "@dnd-kit/sortable";
|
||||||
import { CSS } from "@dnd-kit/utilities";
|
import { CSS } from "@dnd-kit/utilities";
|
||||||
@ -6,6 +7,9 @@ import { TaskDetailModal } from "./taskDetailModal";
|
|||||||
|
|
||||||
export function TaskCard({ task, deleteTask, updateTask }) {
|
export function TaskCard({ task, deleteTask, updateTask }) {
|
||||||
const [mouseIsOver, setMouseIsOver] = useState(false);
|
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({
|
const { setNodeRef, attributes, listeners, transform, transition, isDragging } = useSortable({
|
||||||
id: task.id,
|
id: task.id,
|
||||||
@ -14,12 +18,13 @@ export function TaskCard({ task, deleteTask, updateTask }) {
|
|||||||
task,
|
task,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const style = {
|
const style = {
|
||||||
transition,
|
transition,
|
||||||
transform: CSS.Transform.toString(transform),
|
transform: CSS.Transform.toString(transform),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
/* If card is dragged */
|
/* If card is dragged */
|
||||||
}
|
}
|
||||||
@ -60,7 +65,7 @@ export function TaskCard({ task, deleteTask, updateTask }) {
|
|||||||
setMouseIsOver(false);
|
setMouseIsOver(false);
|
||||||
}}>
|
}}>
|
||||||
<p
|
<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()}>
|
onClick={() => document.getElementById(`task_detail_modal_${task.id}`).showModal()}>
|
||||||
{task.content}
|
{task.content}
|
||||||
</p>
|
</p>
|
||||||
@ -77,4 +82,4 @@ export function TaskCard({ task, deleteTask, updateTask }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -7,6 +7,9 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
const [isChallengeChecked, setChallengeChecked] = useState(challenge);
|
const [isChallengeChecked, setChallengeChecked] = useState(challenge);
|
||||||
const [isImportantChecked, setImportantChecked] = useState(importance);
|
const [isImportantChecked, setImportantChecked] = useState(importance);
|
||||||
const [currentDifficulty, setCurrentDifficulty] = useState(difficulty);
|
const [currentDifficulty, setCurrentDifficulty] = useState(difficulty);
|
||||||
|
// console.log(currentDifficulty);
|
||||||
|
// console.log(isChallengeChecked);
|
||||||
|
// console.log(isImportantChecked);
|
||||||
|
|
||||||
const handleChallengeChange = () => {
|
const handleChallengeChange = () => {
|
||||||
setChallengeChecked(!isChallengeChecked);
|
setChallengeChecked(!isChallengeChecked);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user