From 5c0a7a1b5c710754c234a14bedc86bb6daa503bb Mon Sep 17 00:00:00 2001 From: Sergey Elpashev Date: Sun, 27 Apr 2025 14:34:10 +0300 Subject: [PATCH] feat: status-system --- src/components/menu.tsx | 30 ++++++++++++++++++++++++++++-- src/components/task.tsx | 1 - src/index.scss | 2 ++ src/pages/profile_settings.tsx | 29 +++++++++++++++++++++++++++-- src/utils/status-system.ts | 26 ++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 src/utils/status-system.ts diff --git a/src/components/menu.tsx b/src/components/menu.tsx index 377901e..94522be 100644 --- a/src/components/menu.tsx +++ b/src/components/menu.tsx @@ -4,6 +4,8 @@ import { FunctionComponent, h } from "preact"; import { useLocation } from "preact-iso"; import { tv } from "tailwind-variants"; import classes from "./menu.module.scss"; +import { calculatePoints, getCurrentStatus } from "@/utils/status-system"; +import { useEffect, useState } from "preact/hooks"; interface MenuItemProps { title: string; @@ -34,9 +36,33 @@ const MenuItem: FunctionComponent = ({ title, link, icon }: MenuI ); }; + const Avatar: FunctionComponent = () => { + const [status, setStatus] = useState(""); const { route, path } = useLocation(); - //TODO: Move styles to scss module + + useEffect(() => { + const updateStatus = () => { + const tasks = JSON.parse(localStorage.getItem("tasks") || "[]"); + const completedTasks = tasks.filter((task: { checked: boolean }) => task.checked).length; + const points = calculatePoints(completedTasks); + setStatus(getCurrentStatus(points)); + }; + + // Initial update + updateStatus(); + + // Update when tasks change + const handleStorage = (e: StorageEvent) => { + if (e.key === "tasks") { + updateStatus(); + } + }; + + window.addEventListener('storage', handleStorage); + return () => window.removeEventListener('storage', handleStorage); + }, []); + return ( diff --git a/src/components/task.tsx b/src/components/task.tsx index 6f814f7..9e1c25c 100644 --- a/src/components/task.tsx +++ b/src/components/task.tsx @@ -32,7 +32,6 @@ const markStyle = tv({ const Task: FunctionComponent = ({ name, checked = false, onClick = () => {}, onMarkClick = () => {} }) => { return ( - // Временное действие для тестирования
{ const { isLoggedIn } = useAppContext(); const { route } = useLocation(); - const status = 12; + const [status, setStatus] = useState(0); const maxStatus = 100; + + useEffect(() => { + const updateStatus = () => { + const tasks = JSON.parse(localStorage.getItem("tasks") || "[]"); + const completedTasks = tasks.filter((task: { checked: boolean }) => task.checked).length; + const points = calculatePoints(completedTasks); + setStatus(points); + }; + + // Initial update + updateStatus(); + + // Update when tasks change + const handleStorage = (e: StorageEvent) => { + if (e.key === "tasks") { + updateStatus(); + } + }; + + window.addEventListener('storage', handleStorage); + return () => window.removeEventListener('storage', handleStorage); + }, []); + return (
Аватар

Никнейм

-

Статус

+

{getCurrentStatus(status)}

{ + return Math.min(completedTasks * POINTS_PER_TASK, 100); +}; + +export const getCurrentStatus = (points: number): string => { + const status = STATUS_LEVELS + .slice() + .reverse() + .find(level => points >= level.minPoints); + return status?.name || STATUS_LEVELS[0].name; +}; \ No newline at end of file