From 61a3273e46a711848d153049334a81d54148cdde Mon Sep 17 00:00:00 2001 From: danielchen3 Date: Wed, 30 Apr 2025 14:18:30 +0800 Subject: [PATCH] add important task choice and sorted by ddl --- git | 0 src/components/tasks/EditTask.tsx | 24 +++++++++++++++++++++++- src/components/tasks/TaskItem.tsx | 1 + src/components/tasks/TasksList.tsx | 13 ++++++++++--- src/components/tasks/tasks.styled.tsx | 14 +++++++++++--- src/pages/AddTask.tsx | 22 ++++++++++++++++++++-- src/styles/addTask.styled.tsx | 13 ++++++++++++- src/styles/index.ts | 1 + src/styles/keyframes.styled.tsx | 15 +++++++++++++++ src/types/user.ts | 1 + 10 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 git diff --git a/git b/git new file mode 100644 index 00000000..e69de29b diff --git a/src/components/tasks/EditTask.tsx b/src/components/tasks/EditTask.tsx index 009e8c06..e41588a9 100644 --- a/src/components/tasks/EditTask.tsx +++ b/src/components/tasks/EditTask.tsx @@ -9,12 +9,13 @@ import { TextField, TextFieldProps, Tooltip, + FormControlLabel, } from "@mui/material"; import { useContext, useEffect, useMemo, useState } from "react"; import { ColorPicker, CustomDialogTitle, CustomEmojiPicker } from ".."; import { DESCRIPTION_MAX_LENGTH, TASK_NAME_MAX_LENGTH } from "../../constants"; import { UserContext } from "../../contexts/UserContext"; -import { DialogBtn } from "../../styles"; +import { DialogBtn, CustomSwitch } from "../../styles"; import { Category, Task } from "../../types/user"; import { showToast } from "../../utils"; import { useTheme } from "@emotion/react"; @@ -70,17 +71,28 @@ export const EditTask = ({ open, task, onClose }: EditTaskProps) => { [name]: value, })); }; + + // Event handler for changing the importance of the task. + const setisimportant = (value: boolean) => { + setEditedTask((prevTask) => ({ + ...(prevTask as Task), + isimportant: value, + })); + }; + // Event handler for saving the edited task. const handleSave = () => { document.body.style.overflow = "auto"; if (editedTask && !nameError && !descriptionError) { const updatedTasks = user.tasks.map((task) => { if (task.id === editedTask.id) { + console.log("Task updated: ", editedTask); return { ...task, name: editedTask.name, color: editedTask.color, emoji: editedTask.emoji || undefined, + isimportant: editedTask.isimportant, description: editedTask.description || undefined, deadline: editedTask.deadline || undefined, category: editedTask.category || undefined, @@ -241,6 +253,16 @@ export const EditTask = ({ open, task, onClose }: EditTaskProps) => { }, }} /> + setisimportant(e.target.checked)} + customcolor={editedTask?.color ?? "#fbc02d"} + /> + } + label="Important" + /> {settings.enableCategories !== undefined && settings.enableCategories && ( {enableSelection && selectedIds.length > 0 && ( diff --git a/src/components/tasks/TasksList.tsx b/src/components/tasks/TasksList.tsx index 009a1fc5..29178230 100644 --- a/src/components/tasks/TasksList.tsx +++ b/src/components/tasks/TasksList.tsx @@ -146,14 +146,21 @@ export const TasksList: React.FC = () => { unpinnedTasks = unpinnedTasks.filter(searchFilter); pinnedTasks = pinnedTasks.filter(searchFilter); + const sortByDeadline = (a: Task, b: Task) => { + if (!a.deadline) return 1; + if (!b.deadline) return -1; + return new Date(a.deadline).getTime() - new Date(b.deadline).getTime(); + }; + // Move done tasks to bottom if the setting is enabled + if (user.settings?.doneToBottom) { const doneTasks = unpinnedTasks.filter((task) => task.done); - const notDoneTasks = unpinnedTasks.filter((task) => !task.done); - return [...pinnedTasks, ...notDoneTasks, ...doneTasks]; + const notDoneTasks = unpinnedTasks.filter((task) => !task.done).sort(sortByDeadline); + return [...pinnedTasks.sort(sortByDeadline), ...notDoneTasks, ...doneTasks]; } - return [...pinnedTasks, ...unpinnedTasks]; + return [...pinnedTasks.sort(sortByDeadline), ...unpinnedTasks.sort(sortByDeadline)]; }, [search, selectedCatId, user.settings], ); diff --git a/src/components/tasks/tasks.styled.tsx b/src/components/tasks/tasks.styled.tsx index 69327cb4..ae95db8e 100644 --- a/src/components/tasks/tasks.styled.tsx +++ b/src/components/tasks/tasks.styled.tsx @@ -1,7 +1,7 @@ import styled from "@emotion/styled"; import { Alarm, RadioButtonChecked, RadioButtonUnchecked } from "@mui/icons-material"; import { Button, Checkbox, IconButton, TextField, css } from "@mui/material"; -import { fadeIn, ring, scale } from "../../styles/keyframes.styled"; +import { fadeIn, ring, scale, glowBorder } from "../../styles/keyframes.styled"; import { ColorPalette } from "../../theme/themeConfig"; import { getFontColor, isDark, systemInfo } from "../../utils"; @@ -12,6 +12,7 @@ interface TaskComponentProps { done: boolean; glow?: boolean; blur?: boolean; + isimportant?: boolean; } export const TaskContainer = styled.div` @@ -31,8 +32,6 @@ export const TaskContainer = styled.div` glow && !done ? `0 0 2px ${getFontColor(backgroundColor)}78` : "none"}; */ filter: ${({ blur }) => (blur ? "blur(2px) opacity(75%)" : "none")}; - animation: ${fadeIn} 0.5s ease-in; - /* If the theme color and task color are the same, it changes the selection color to be different. */ *::selection { background-color: ${({ theme, backgroundColor }) => @@ -40,6 +39,15 @@ export const TaskContainer = styled.div` color: ${({ theme, backgroundColor }) => theme.primary === backgroundColor ? "#000000" : getFontColor(theme.primary)} !important; } + border: ${({ isimportant, done }) => (isimportant && !done ? "2px solid red" : undefined)}; + box-shadow: ${(props) => + props.isimportant + ? `0 0 12px 2px red` + : props.glow && !props.blur + ? `0 0 128px -20px ${props.backgroundColor}` + : "none"}; + animation: ${({ isimportant, done }) => (isimportant && !done ? glowBorder : "none")} 1.5s + infinite; @media (max-width: 768px) { padding: 14px 14px 14px 18px; diff --git a/src/pages/AddTask.tsx b/src/pages/AddTask.tsx index d3dd64e8..ff22982a 100644 --- a/src/pages/AddTask.tsx +++ b/src/pages/AddTask.tsx @@ -1,9 +1,9 @@ import { Category, Task } from "../types/user"; import { useState, useEffect, useContext } from "react"; import { useNavigate } from "react-router-dom"; -import { AddTaskButton, Container, StyledInput } from "../styles"; +import { AddTaskButton, Container, StyledInput, CustomSwitch } from "../styles"; import { AddTaskRounded, CancelRounded } from "@mui/icons-material"; -import { IconButton, InputAdornment, Tooltip } from "@mui/material"; +import { IconButton, InputAdornment, Tooltip, FormControlLabel } from "@mui/material"; import { DESCRIPTION_MAX_LENGTH, TASK_NAME_MAX_LENGTH } from "../constants"; import { CategorySelect, ColorPicker, TopBar, CustomEmojiPicker } from "../components"; import { UserContext } from "../contexts/UserContext"; @@ -35,6 +35,12 @@ const AddTask = () => { const [isDeadlineFocused, setIsDeadlineFocused] = useState(false); + const [isImportant, setisimportant] = useStorageState( + false, + "isImportant", + "sessionStorage", + ); + const n = useNavigate(); useEffect(() => { @@ -96,6 +102,7 @@ const AddTask = () => { id: generateUUID(), done: false, pinned: false, + isimportant: isImportant, name, description: description !== "" ? description : undefined, emoji: emoji ? emoji : undefined, @@ -104,6 +111,7 @@ const AddTask = () => { deadline: deadline !== "" ? new Date(deadline) : undefined, category: selectedCategories ? selectedCategories : [], }; + console.log("New Task: ", newTask); setUser((prevUser) => ({ ...prevUser, @@ -203,6 +211,16 @@ const AddTask = () => { }, }} /> + setisimportant(e.target.checked)} + customcolor={color} + /> + } + label="Important" + /> {user.settings.enableCategories !== undefined && user.settings.enableCategories && (
diff --git a/src/styles/addTask.styled.tsx b/src/styles/addTask.styled.tsx index 02244649..2ca84eb1 100644 --- a/src/styles/addTask.styled.tsx +++ b/src/styles/addTask.styled.tsx @@ -1,5 +1,5 @@ import styled from "@emotion/styled"; -import { Button, TextField } from "@mui/material"; +import { Button, TextField, Switch } from "@mui/material"; import { getFontColor } from "../utils"; export const Container = styled.div` @@ -48,3 +48,14 @@ export const StyledInput = styled(TextField)<{ helpercolor?: string; hidetext?: opacity: 0.8; } `; + +export const CustomSwitch = styled(Switch, { + shouldForwardProp: (prop) => prop !== "customcolor", +})<{ customcolor: string }>(({ customcolor }) => ({ + "& .MuiSwitch-switchBase.Mui-checked": { + color: customcolor, + "& + .MuiSwitch-track": { + backgroundColor: customcolor, + }, + }, +})); diff --git a/src/styles/index.ts b/src/styles/index.ts index 3a0d6987..a0a4626a 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -5,3 +5,4 @@ export * from "./keyframes.styled"; export * from "./common.styled"; export * from "./categories.styled"; export * from "./taskManagement.styled"; +export * from "./addTask.styled"; diff --git a/src/styles/keyframes.styled.tsx b/src/styles/keyframes.styled.tsx index 0f991098..325b0d27 100644 --- a/src/styles/keyframes.styled.tsx +++ b/src/styles/keyframes.styled.tsx @@ -1,5 +1,20 @@ import { keyframes } from "@emotion/react"; +export const glowBorder = keyframes` + 0% { + box-shadow: 0 0 0px red; + border-color: red; + } + 50% { + box-shadow: 0 0 10px red; + border-color: #ff4d4d; + } + 100% { + box-shadow: 0 0 0px red; + border-color: red; + } + `; + export const fadeInLeft = keyframes` from { opacity: 0; diff --git a/src/types/user.ts b/src/types/user.ts index 90ab4fa9..57b70f63 100644 --- a/src/types/user.ts +++ b/src/types/user.ts @@ -31,6 +31,7 @@ export interface Task { id: UUID; done: boolean; pinned: boolean; + isimportant?: boolean; name: string; description?: string; emoji?: string;