Adding priority

This commit is contained in:
Kasper Juul Hermansen 2021-11-21 20:40:41 +01:00
parent 09d71b71d8
commit 33f050085c
Signed by: kjuulh
GPG Key ID: 0F95C140730F2F23
13 changed files with 116 additions and 26 deletions

View File

@ -81,12 +81,16 @@ public class TodosController : ApiController
[JsonPropertyName("created")] [JsonPropertyName("created")]
public long Created { get; init; } = 0; public long Created { get; init; } = 0;
[JsonPropertyName("priority")]
public string? Priority { get; init; }
internal ReplaceTodoCommand To(string id) => new( internal ReplaceTodoCommand To(string id) => new(
id, id,
Title, Title,
Project, Project,
Description, Description,
Status, Status,
Created); Created,
Priority);
} }
} }

View File

@ -11,7 +11,8 @@ namespace Todo.Core.Application.Commands.Todo;
public record CreateTodoCommand( public record CreateTodoCommand(
[Required] string TodoTitle, [Required] string TodoTitle,
string? TodoProject, string? TodoProject,
string? TodoDescription) : IRequest<TodoViewModel> string? TodoDescription,
string? Priority) : IRequest<TodoViewModel>
{ {
internal class Handler : IRequestHandler<CreateTodoCommand, TodoViewModel> internal class Handler : IRequestHandler<CreateTodoCommand, TodoViewModel>
{ {
@ -41,6 +42,7 @@ public record CreateTodoCommand(
request.TodoTitle, request.TodoTitle,
request.TodoProject, request.TodoProject,
request.TodoDescription, request.TodoDescription,
request.Priority
userId, userId,
DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()); DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());

View File

@ -12,7 +12,8 @@ public record ReplaceTodoCommand(
string? Project, string? Project,
string? Description, string? Description,
bool Status, bool Status,
long Created) : IRequest<Unit> long Created,
string? Priority) : IRequest<Unit>
{ {
internal class Handler : IRequestHandler<ReplaceTodoCommand, Unit> internal class Handler : IRequestHandler<ReplaceTodoCommand, Unit>
{ {
@ -51,5 +52,6 @@ public record ReplaceTodoCommand(
Project, Project,
authorId, authorId,
Description, Description,
Created); Created,
Priority);
} }

View File

@ -7,4 +7,5 @@ public record Todo(
string? Project, string? Project,
string AuthorId, string AuthorId,
string? Description, string? Description,
long Created); long Created,
string? Priority);

View File

@ -8,6 +8,7 @@ public interface ITodoRepository
string title, string title,
string? projectName, string? projectName,
string? description, string? description,
string? priority,
string userId, string userId,
long created); long created);

View File

@ -20,6 +20,7 @@ public record MongoTodo
public string? ProjectName { get; set; } = string.Empty; public string? ProjectName { get; set; } = string.Empty;
public string AuthorId { get; set; } public string AuthorId { get; set; }
public long Created { get; set; } = 0; public long Created { get; set; } = 0;
public string? Priority { get; set; } = string.Empty;
public Core.Entities.Todo To() => new( public Core.Entities.Todo To() => new(
Id, Id,
@ -28,5 +29,6 @@ public record MongoTodo
ProjectName, ProjectName,
AuthorId, AuthorId,
Description, Description,
Created); Created,
Priority);
} }

View File

@ -0,0 +1,54 @@
import { ButtonHTMLAttributes, FC, useState } from "react";
import { OutlinedButton } from "@src/components/common/buttons/outlinedButton";
import Tippy from "@tippyjs/react";
interface AddPriorityButtonProps
extends ButtonHTMLAttributes<HTMLButtonElement> {
initialPriority?: string;
onPriorityChanged: (project: string) => void;
}
export const AddPriorityButton: FC<AddPriorityButtonProps> = (props) => {
const [menuIsOpen, setMenuIsOpen] = useState(false);
return (
<Tippy
placement="bottom"
visible={menuIsOpen}
onClickOutside={() => {
setMenuIsOpen(false);
}}
delay={0}
interactive={true}
duration={0}
content={
<div
className="py-2 px-2 bg-white dark:bg-gray-700 border border-accent-500 rounded-md flex flex-col gap-4"
tabIndex={0}
>
<div className="space-y-2">
{["p1", "p2", "p3"].map((p) => (
<div key={p}>
<button
type="button"
className="whitespace-nowrap py-1 px-4 dark:text-white dark:bg-gray-500 rounded-sm"
onClick={() => props.onPriorityChanged(p)}
>
{p}
</button>
</div>
))}
</div>
</div>
}
>
<span>
<OutlinedButton
className="whitespace-nowrap"
onClick={() => setMenuIsOpen(true)}
>
{props.children || "Add Priority"}
</OutlinedButton>
</span>
</Tippy>
);
};

View File

@ -4,19 +4,26 @@ import { PrimaryButton } from "@src/components/common/buttons/primaryButton";
import { TodoShortForm } from "@src/components/todos/collapsed/todoShortForm"; import { TodoShortForm } from "@src/components/todos/collapsed/todoShortForm";
export const AddTodoForm: FC<{ export const AddTodoForm: FC<{
onAdd: (todoName: string, project: string, description: string) => void; onAdd: (
todoName: string,
project: string,
description: string,
priority: string
) => void;
onClose: () => void; onClose: () => void;
project: string; project: string;
priority: string;
}> = ({ onAdd, onClose, ...props }) => { }> = ({ onAdd, onClose, ...props }) => {
const [todoName, setTodoName] = useState(""); const [todoName, setTodoName] = useState("");
const [todoDescription, setTodoDescription] = useState(""); const [todoDescription, setTodoDescription] = useState("");
const [project, setProject] = useState(props.project); const [project, setProject] = useState(props.project);
const [priority, setPriority] = useState(props.priority);
return ( return (
<form <form
onSubmit={(e) => { onSubmit={(e) => {
e.preventDefault(); e.preventDefault();
onAdd(todoName, project, todoDescription); onAdd(todoName, project, todoDescription, priority);
setTodoName(""); setTodoName("");
setTodoDescription(""); setTodoDescription("");
}} }}
@ -25,6 +32,8 @@ export const AddTodoForm: FC<{
<TodoShortForm <TodoShortForm
project={project} project={project}
onProjectChanged={(p) => setProject(p)} onProjectChanged={(p) => setProject(p)}
priority={priority}
onPriorityChanged={setPriority}
name={todoName} name={todoName}
onNameChange={(e) => setTodoName(e.target.value)} onNameChange={(e) => setTodoName(e.target.value)}
description={todoDescription} description={todoDescription}

View File

@ -22,8 +22,9 @@ export function AddTodo(props: { project: string }) {
return ( return (
<AddTodoForm <AddTodoForm
project={props.project} project={props.project}
onAdd={(todoName, project, description) => { priority={""}
createTodo(todoName, project, description); onAdd={(todoName, project, description, priority) => {
createTodo(todoName, description, project, priority);
}} }}
onClose={() => setCollapsed(CollapsedState.collapsed)} onClose={() => setCollapsed(CollapsedState.collapsed)}
/> />

View File

@ -1,9 +1,12 @@
import TextareaAutosize from "react-textarea-autosize"; import TextareaAutosize from "react-textarea-autosize";
import { AddProjectButton } from "@src/components/todos/add/addProjectButton"; import { AddProjectButton } from "@src/components/todos/add/addProjectButton";
import { AddPriorityButton } from "@src/components/todos/add/addPriorityButton";
export const TodoShortForm = (props: { export const TodoShortForm = (props: {
project: string; project: string;
onProjectChanged: (project: string) => void; onProjectChanged: (project: string) => void;
priority: string;
onPriorityChanged: (project: string) => void;
name: string; name: string;
onNameChange: (e) => void; onNameChange: (e) => void;
description: string; description: string;
@ -34,20 +37,24 @@ export const TodoShortForm = (props: {
minRows={3} minRows={3}
/> />
</div> </div>
<div className="flex flex-row pb-1"> <div className="flex flex-col sm:flex-row pb-1 gap-2 justify-between">
<div>
<AddProjectButton <AddProjectButton
onProjectChanged={props.onProjectChanged} onProjectChanged={props.onProjectChanged}
initialProject={props.project} initialProject={props.project}
> >
{props.project} {props.project}
</AddProjectButton> </AddProjectButton>
<AddProjectButton </div>
onProjectChanged={props.onProjectChanged}
initialProject={props.project} <div>
<AddPriorityButton
onPriorityChanged={props.onPriorityChanged}
initialPriority={props.priority}
> >
{props.project} {props.priority}
</AddProjectButton> </AddPriorityButton>
<div className="flex-grow w-1/2" /> </div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -14,6 +14,7 @@ export interface Todo {
project?: string; project?: string;
authorId?: string; authorId?: string;
created: number; created: number;
priority?: string;
} }
export const asTodo = (item: Todo): Todo => { export const asTodo = (item: Todo): Todo => {

View File

@ -55,7 +55,7 @@ const HomePage = () => {
/> />
</div> </div>
))} ))}
{data && data.length === 0 && ( {onlyActiveTodos && onlyActiveTodos.length === 0 && (
<div className="space-y-4"> <div className="space-y-4">
<PageHeading title="You're done!" /> <PageHeading title="You're done!" />
<AddTodo project={""} /> <AddTodo project={""} />

View File

@ -18,7 +18,12 @@ export const useCreateTodo = () => {
const [createTodo, { isLoading }] = todosApi.useCreateTodoMutation(); const [createTodo, { isLoading }] = todosApi.useCreateTodoMutation();
return { return {
createTodo: (todoName: string, project: string, description: string) => { createTodo: (
todoName: string,
description: string,
project?: string,
priority?: string
) => {
createTodo({ createTodo({
id: nanoid(), id: nanoid(),
created: 0, created: 0,
@ -26,6 +31,7 @@ export const useCreateTodo = () => {
title: todoName, title: todoName,
project, project,
description, description,
priority,
}); });
}, },
}; };