Add base project
This commit is contained in:
parent
55ee0516da
commit
f6331c8aea
@ -17,7 +17,7 @@ public class TodosController : ControllerBase
|
|||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<Core.Entities.Todo>> CreateTodo([FromBody] CreateTodoRequest request) =>
|
public async Task<ActionResult<Core.Entities.Todo>> CreateTodo([FromBody] CreateTodoRequest request) =>
|
||||||
Ok(await _todoRepository.CreateTodoAsync(request.Title));
|
Ok(await _todoRepository.CreateTodoAsync(request.Title, String.Empty));
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<ActionResult<IEnumerable<Core.Entities.Todo>>> GetTodos() =>
|
public async Task<ActionResult<IEnumerable<Core.Entities.Todo>>> GetTodos() =>
|
||||||
|
@ -12,4 +12,7 @@ public record TodoResponse
|
|||||||
|
|
||||||
[JsonPropertyName("status")]
|
[JsonPropertyName("status")]
|
||||||
public bool Status { get; init; }
|
public bool Status { get; init; }
|
||||||
|
|
||||||
|
[JsonPropertyName("project")]
|
||||||
|
public string Project { get; set; }
|
||||||
}
|
}
|
@ -14,14 +14,14 @@ namespace Todo.Api.Hubs
|
|||||||
_todoRepository = todoRepository;
|
_todoRepository = todoRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task CreateTodo(string todoTitle)
|
public async Task CreateTodo(string todoTitle, string projectName)
|
||||||
{
|
{
|
||||||
var _ = await _todoRepository.CreateTodoAsync(todoTitle);
|
var _ = await _todoRepository.CreateTodoAsync(todoTitle, projectName);
|
||||||
|
|
||||||
var todos = await _todoRepository.GetNotDoneTodos();
|
var todos = await _todoRepository.GetNotDoneTodos();
|
||||||
var serializedTodos =
|
var serializedTodos =
|
||||||
JsonSerializer.Serialize(todos
|
JsonSerializer.Serialize(todos
|
||||||
.Select(t => new TodoResponse { Id = t.Id, Title = t.Title })
|
.Select(t => new TodoResponse { Id = t.Id, Title = t.Title, Project = t.Project })
|
||||||
.ToList());
|
.ToList());
|
||||||
|
|
||||||
await Clients.Caller.SendAsync("getInboxTodos", serializedTodos);
|
await Clients.Caller.SendAsync("getInboxTodos", serializedTodos);
|
||||||
@ -34,7 +34,8 @@ namespace Todo.Api.Hubs
|
|||||||
var todos = await _todoRepository.GetNotDoneTodos();
|
var todos = await _todoRepository.GetNotDoneTodos();
|
||||||
var serializedTodos =
|
var serializedTodos =
|
||||||
JsonSerializer.Serialize(todos
|
JsonSerializer.Serialize(todos
|
||||||
.Select(t => new TodoResponse { Id = t.Id, Title = t.Title, Status = t.Status })
|
.Select(t => new TodoResponse
|
||||||
|
{ Id = t.Id, Title = t.Title, Status = t.Status, Project = t.Project })
|
||||||
.ToList());
|
.ToList());
|
||||||
|
|
||||||
await Clients.Caller.SendAsync("getInboxTodos", serializedTodos);
|
await Clients.Caller.SendAsync("getInboxTodos", serializedTodos);
|
||||||
@ -44,7 +45,7 @@ namespace Todo.Api.Hubs
|
|||||||
{
|
{
|
||||||
var todos = await _todoRepository.GetTodosAsync();
|
var todos = await _todoRepository.GetTodosAsync();
|
||||||
var serializedTodos = JsonSerializer.Serialize(todos
|
var serializedTodos = JsonSerializer.Serialize(todos
|
||||||
.Select(t => new TodoResponse { Id = t.Id, Title = t.Title, Status = t.Status })
|
.Select(t => new TodoResponse { Id = t.Id, Title = t.Title, Status = t.Status, Project = t.Project })
|
||||||
.ToList());
|
.ToList());
|
||||||
|
|
||||||
await Clients.Caller.SendAsync("todos", serializedTodos);
|
await Clients.Caller.SendAsync("todos", serializedTodos);
|
||||||
@ -55,7 +56,7 @@ namespace Todo.Api.Hubs
|
|||||||
{
|
{
|
||||||
var todos = await _todoRepository.GetNotDoneTodos();
|
var todos = await _todoRepository.GetNotDoneTodos();
|
||||||
var serializedTodos = JsonSerializer.Serialize(todos
|
var serializedTodos = JsonSerializer.Serialize(todos
|
||||||
.Select(t => new TodoResponse { Id = t.Id, Title = t.Title, Status = t.Status })
|
.Select(t => new TodoResponse { Id = t.Id, Title = t.Title, Status = t.Status, Project = t.Project })
|
||||||
.ToList());
|
.ToList());
|
||||||
|
|
||||||
await Clients.Caller.SendAsync("getInboxTodos", serializedTodos);
|
await Clients.Caller.SendAsync("getInboxTodos", serializedTodos);
|
||||||
|
@ -5,4 +5,5 @@ public record Todo
|
|||||||
public string Id { get; init; }
|
public string Id { get; init; }
|
||||||
public string Title { get; init; }
|
public string Title { get; init; }
|
||||||
public bool Status { get; init; }
|
public bool Status { get; init; }
|
||||||
|
public string Project { get; init; }
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ namespace Todo.Core.Interfaces.Persistence;
|
|||||||
|
|
||||||
public interface ITodoRepository
|
public interface ITodoRepository
|
||||||
{
|
{
|
||||||
Task<Entities.Todo> CreateTodoAsync(string title);
|
Task<Entities.Todo> CreateTodoAsync(string title, string projectName);
|
||||||
Task<IEnumerable<Entities.Todo>> GetTodosAsync();
|
Task<IEnumerable<Entities.Todo>> GetTodosAsync();
|
||||||
Task UpdateTodoStatus(string todoId, bool todoStatus);
|
Task UpdateTodoStatus(string todoId, bool todoStatus);
|
||||||
Task<IEnumerable<Entities.Todo>> GetNotDoneTodos();
|
Task<IEnumerable<Entities.Todo>> GetNotDoneTodos();
|
||||||
|
@ -11,4 +11,5 @@ public record MongoTodo
|
|||||||
|
|
||||||
[BsonRequired] public string Title { get; init; }
|
[BsonRequired] public string Title { get; init; }
|
||||||
[BsonRequired] public bool Status { get; set; }
|
[BsonRequired] public bool Status { get; set; }
|
||||||
|
public string ProjectName { get; set; } = String.Empty;
|
||||||
}
|
}
|
@ -15,11 +15,12 @@ public class TodoRepository : ITodoRepository
|
|||||||
_todosCollection = database.GetCollection<MongoTodo>("todos");
|
_todosCollection = database.GetCollection<MongoTodo>("todos");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Core.Entities.Todo> CreateTodoAsync(string title)
|
public async Task<Core.Entities.Todo> CreateTodoAsync(string title, string projectName)
|
||||||
{
|
{
|
||||||
var todo = new MongoTodo() { Title = title };
|
var todo = new MongoTodo() { Title = title, ProjectName = projectName };
|
||||||
await _todosCollection.InsertOneAsync(todo);
|
await _todosCollection.InsertOneAsync(todo);
|
||||||
return new Core.Entities.Todo() { Id = todo.Id, Title = todo.Title, Status = false};
|
return new Core.Entities.Todo()
|
||||||
|
{ Id = todo.Id, Title = todo.Title, Status = false, Project = todo.ProjectName };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<Core.Entities.Todo>> GetTodosAsync()
|
public async Task<IEnumerable<Core.Entities.Todo>> GetTodosAsync()
|
||||||
@ -28,7 +29,7 @@ public class TodoRepository : ITodoRepository
|
|||||||
return todos
|
return todos
|
||||||
.ToEnumerable()
|
.ToEnumerable()
|
||||||
.Select(t =>
|
.Select(t =>
|
||||||
new Core.Entities.Todo() { Id = t.Id, Title = t.Title, Status = t.Status});
|
new Core.Entities.Todo() { Id = t.Id, Title = t.Title, Status = t.Status, Project = t.ProjectName });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateTodoStatus(string todoId, bool todoStatus)
|
public async Task UpdateTodoStatus(string todoId, bool todoStatus)
|
||||||
|
@ -21,8 +21,8 @@ export function AddTodo(props: {}) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AddTodoForm
|
<AddTodoForm
|
||||||
onAdd={(todoName) => {
|
onAdd={(todoName, project) => {
|
||||||
createTodo(todoName);
|
createTodo(todoName, project);
|
||||||
}}
|
}}
|
||||||
onClose={() => setCollapsed(CollapsedState.collapsed)}
|
onClose={() => setCollapsed(CollapsedState.collapsed)}
|
||||||
/>
|
/>
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
import { FC, useState } from "react";
|
import { FC, useState } from "react";
|
||||||
|
|
||||||
export const AddTodoForm: FC<{
|
export const AddTodoForm: FC<{
|
||||||
onAdd: (todoName: string) => void;
|
onAdd: (todoName: string, project: string) => void;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}> = ({ onAdd, onClose }) => {
|
}> = ({ onAdd, onClose }) => {
|
||||||
const [todoName, setTodoName] = useState("");
|
const [todoName, setTodoName] = useState("");
|
||||||
|
const [project, setProject] = useState("");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onAdd(todoName);
|
onAdd(todoName, project);
|
||||||
setTodoName("");
|
setTodoName("");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="py-2 space-y-3">
|
<div className="py-2 space-y-3">
|
||||||
<div className="todo-input-form py-2 px-4 bg-gray-800 border border-gray-500 rounded-lg">
|
<div className="flex flex-col md:flex-row gap-4">
|
||||||
|
<div className="todo-input-form md:flex-grow py-2 px-4 bg-gray-800 border border-gray-500 rounded-lg">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Todo name"
|
placeholder="Todo name"
|
||||||
@ -26,6 +28,17 @@ export const AddTodoForm: FC<{
|
|||||||
onChange={(e) => setTodoName(e.target.value)}
|
onChange={(e) => setTodoName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="todo-project py-2 px-4 bg-gray-700 border border-gray-500 rounded-lg ">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Project name"
|
||||||
|
className="text-sm w-full placeholder-gray-400"
|
||||||
|
value={project}
|
||||||
|
tabIndex={2}
|
||||||
|
onChange={(e) => setProject(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="space-x-2">
|
<div className="space-x-2">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -5,13 +5,19 @@ import { TodoCheckmark } from "@src/components/todos/todoCheckmark";
|
|||||||
interface TodoItemProps {
|
interface TodoItemProps {
|
||||||
todo: Todo;
|
todo: Todo;
|
||||||
updateTodo: (todo: Todo) => void;
|
updateTodo: (todo: Todo) => void;
|
||||||
|
displayProject: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TodoItem: FC<TodoItemProps> = (props) => (
|
export const TodoItem: FC<TodoItemProps> = (props) => (
|
||||||
<div className="py-3 border-b border-gray-300 dark:border-gray-600">
|
<div className="py-3 border-b border-gray-300 dark:border-gray-600">
|
||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center space-x-4">
|
||||||
<TodoCheckmark {...props} />
|
<TodoCheckmark {...props} />
|
||||||
<span className="pb-1">{props.todo.title}</span>
|
<div className="flex flex-row flex-grow gap-2 pr-6">
|
||||||
|
<div className="flex-grow w-full break-all">{props.todo.title}</div>
|
||||||
|
{props.displayProject && props.todo.project && (
|
||||||
|
<div className="text-gray-500 text-right">{props.todo.project}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -18,6 +18,7 @@ export const TodoList = (props: { todos: Todo[]; hideDone: boolean }) => {
|
|||||||
updateTodo={(todo) => {
|
updateTodo={(todo) => {
|
||||||
updateTodoState(todo.id, todo.status);
|
updateTodoState(todo.id, todo.status);
|
||||||
}}
|
}}
|
||||||
|
displayProject={false}
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
@ -10,6 +10,7 @@ export interface Todo {
|
|||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
status: StatusState;
|
status: StatusState;
|
||||||
|
project?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const asTodo = (item: Todo): Todo => {
|
export const asTodo = (item: Todo): Todo => {
|
||||||
|
@ -12,7 +12,7 @@ interface SocketContextProps {
|
|||||||
inboxTodos: Todo[];
|
inboxTodos: Todo[];
|
||||||
getTodos: () => void;
|
getTodos: () => void;
|
||||||
getInboxTodos: () => void;
|
getInboxTodos: () => void;
|
||||||
createTodo: (todoName: string) => void;
|
createTodo: (todoName: string, project: string) => void;
|
||||||
updateTodo: (todoId: string, todoStatus: StatusState) => void;
|
updateTodo: (todoId: string, todoStatus: StatusState) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ export const SocketContext = createContext<SocketContextProps>({
|
|||||||
inboxTodos: [],
|
inboxTodos: [],
|
||||||
getTodos: () => {},
|
getTodos: () => {},
|
||||||
getInboxTodos: () => {},
|
getInboxTodos: () => {},
|
||||||
createTodo: (todoName) => {},
|
createTodo: (todoName, project) => {},
|
||||||
updateTodo: (todoId, todoStatus) => {},
|
updateTodo: (todoId, todoStatus) => {},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -72,8 +72,8 @@ export const SocketProvider: FC = (props) => {
|
|||||||
getInboxTodos: () => {
|
getInboxTodos: () => {
|
||||||
conn.invoke("GetInboxTodos").catch(console.error);
|
conn.invoke("GetInboxTodos").catch(console.error);
|
||||||
},
|
},
|
||||||
createTodo: (todoName) => {
|
createTodo: (todoName, project) => {
|
||||||
conn.invoke("CreateTodo", todoName).catch(console.error);
|
conn.invoke("CreateTodo", todoName, project).catch(console.error);
|
||||||
},
|
},
|
||||||
updateTodo: (todoId, todoStatus) => {
|
updateTodo: (todoId, todoStatus) => {
|
||||||
conn.invoke("UpdateTodo", todoId, todoStatus).catch(console.error);
|
conn.invoke("UpdateTodo", todoId, todoStatus).catch(console.error);
|
||||||
|
@ -19,8 +19,8 @@ export const useCreateTodo = () => {
|
|||||||
const socketContext = useContext(SocketContext);
|
const socketContext = useContext(SocketContext);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createTodo: (todoName: string) => {
|
createTodo: (todoName: string, project: string) => {
|
||||||
socketContext.createTodo(todoName);
|
socketContext.createTodo(todoName, project);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user