{"id":28646723,"url":"https://github.com/firedev/todo-mock","last_synced_at":"2026-02-11T07:03:46.813Z","repository":{"id":146128108,"uuid":"283605506","full_name":"firedev/todo-mock","owner":"firedev","description":null,"archived":false,"fork":false,"pushed_at":"2020-11-22T10:06:18.000Z","size":216,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-01T06:13:47.105Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/firedev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-07-29T21:24:58.000Z","updated_at":"2020-11-22T10:06:21.000Z","dependencies_parsed_at":"2023-05-22T13:15:42.521Z","dependency_job_id":null,"html_url":"https://github.com/firedev/todo-mock","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/firedev/todo-mock","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/firedev%2Ftodo-mock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/firedev%2Ftodo-mock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/firedev%2Ftodo-mock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/firedev%2Ftodo-mock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/firedev","download_url":"https://codeload.github.com/firedev/todo-mock/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/firedev%2Ftodo-mock/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29329492,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-11T06:13:03.264Z","status":"ssl_error","status_checked_at":"2026-02-11T06:12:55.843Z","response_time":97,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-13T02:06:40.335Z","updated_at":"2026-02-11T07:03:46.288Z","avatar_url":"https://github.com/firedev.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Todo Mockup\n\n![](board.png)\n\nWe're making a Kanban ToDo app with a few column and three levels of prioritization. Each task has two date fields and sorted automatically depending on the schedule date.\n\n```js\ntask = {\n  id: uuid.required,\n  title: string.required,\n  completed: boolean.required,\n  priority: oneOf([1, 2, 3]).required,\n  description: string, // markdown, multi-line\n  dueDate: string, // date-like string\n  sheduleDate: string, // same\n  // optional\n  position: number, // if time permits so one can rearrange cards\n}\n\ntask.defaultProps = {\n  completed: false,\n  priority: 1,\n}\n```\n\n```css\n/** colors **/\n--red: #e80d00;\n--orange: #ff851b;\n--blue: #7fdbff;\n```\n\n```js\nPRIORITIES = {\n\t1: { title: 'P1', color: '--red' }\n\t2: { title: 'P2', color: '--orange' }\n\t3: { title: 'P3', color: '--blue' }\n}\n```\n\n# Stack\n\n- https://github.com/facebook/react - for components\n- https://github.com/apollographql/react-apollo - for data loading\n- https://github.com/ReactTraining/react-router - routing and UI state\n- https://github.com/atlassian/react-beautiful-dnd for drag and drop\n- https://github.com/formium/formik - forms\n- https://github.com/jquense/yup - validation\n- https://github.com/datejs/Datejs - human date parser\n- https://github.com/wojtekmaj/react-calendar - dropdown calendar\n- https://github.com/rexxars/react-markdown - for markdown\n\n# Interface\n\n- The app loads all tasks at once and sorts them once they are loaded.\n- This way we don't need to worry about having additional models on the backend.\n- If we hide the `Done` tasks- we can load only incomplete tasks.\n- This is debateable but shouln't be a problem unless someone creates billion cards, and we can test things sooner.\n\n```gql\n{ tasks { id title ... }}\n```\n\n- When creating/editing a task we display all fields, but pre-fill `scheduledDate` depending on a column.\n- Users can change data and the card could end up in a different column after save.\n- New card goes to the top of the list so it's not confusing\n- State in url, active column, active card, calendar, etc.\n- On the mobile phone we see only one column, so the app shows the resulting column the card is added to.\n  - We store the active column in the url like so `/:column/:task_uuid(/calendar)` so we know which column to display when the screen is small\n- I propose `apollo-graphql` with optimistic updates turned on, so after validation in the frontend we can be almost sure the actual data will be correct and update interface right away.\n- Generate `uuid` in the frontend as well\n- When one starts dragging a card on the mobile phone, replace the column view with slots to drop the card into:\n\n```\n+----------+\n| Backlog  |\n+----------+\n| Today    |\n+----------+\n| Tomorrow |\n+----------+\n| Schedule |\n+----------+\n| Done     |\n+----------+\n```\n\n- Probably worth color-coding the columns\n- When card needs to be scheduled use an additional route to display the calendar `/tasks/id/schedule` this way the state is easy to manage and until the user enters the date the card stays where it was\n- When creating a card in scheduled column without the date we should drop it to the `Backlog` and let user decide, if time allows - add an `Are you sure?` dialog\n- Cards are split per column by their `id` and if time permits – `position`:\n\n```js\nstate: {\n  cards: {\n    uuid10: { id: 'uuid10', column: 'backlog', title: 'Hello' },\n    uuid11: { .... },\n    ...\n  },\n  columns: {\n    backlog: [ uuid10, uuid11, ... ],\n    today: [ uuid20, uuid21, ... ],\n    tomorrow: [ uuid30, uuid31, ... ],\n    scheduled: [ uuid40, uuid41, ... ],\n    done: [ uuid50, uuid51, ... ],\n  }\n},\n```\n\n- The idea is to fetch a flat list from the server and \"hydrate\" the state:\n  - Each key in the `tasks` object equals `task.id` for this key. This would allow us a direct access to each task using `task[taskId]` without searching through the array.\n  - `column` is referenced front the the `card` as well. This makes it easier to work with the cards and columns since you know which column it resides in.\n\n# `TaskCard`\n\nComponent that displays `task`\n\n![task.png](task.png)\n\n- `title` is always displayed in full\n- `description` is cut off so it's not too long, rendered using markdown\n- `priority` is color coded\n- `completed` fades out priority 50% and displays the `completed` icon in the corner\n- `sheduleDate` and `dueDate` are displayed without the year if the year is current\n- Human-readable time to/from each of the dates\n- If both `sheduleDate` and `dueDate` are present display human-readable estimates amount of time\n- When there is not enough width date lines go one under another, similar to [task-create-edit.png](task-create-edit.png)\n- Fluid width, no maximum width, defined by the column container\n- Draggable\n\n# `CardColumn`\n\nComponent that displays a stack of `TaskCard` + `AddTask`, see [column.png](column.png) and [board.png](board.png)\n\n![](column.png)\n\n- On mobile we display only one column and column title becomes a dropdown menu to switch between columns\n- Clicking `AddTask` opens `TaskForm` component, same when you click the card\n- When dragging the card on the desktop one sees the marker where the card was dragged from and where it lands\n- EXTRA: In the first version cards are auto-sorted, later we could add `position`. Then cards will be ordered by `position` which is scoped to a column. New card will have `position: 0`, so it is always at the top.\n\n# `TaskBoard`\n\nOne can use board as simple scheduler, cards with no near dates, today, tomorrow, and due later.\n\n![](board.png)\n\n- Cards are auto-sorted based on `scheduledDate` and `completed` using the following rules, they are applied top to bottom:\n\n  - no `scheduledDate` - `Backlog`\n  - `scheduledDate` is `today` - `Today`\n  - `scheduledDate` is `tomorrow` - `Tomorrow`\n  - `scheduledDate` exists and not `[today, tomorrow]` - `Scheduled`\n  - `completed`, with any dates – `Done`\n\n- Dragging card from one column to another changes it's `scheduledDate`, and sets/clears `completed` if applicable:\n\n  - `Backlog` - clear `scheduledDate`, `completed: false`\n  - `Today` - set `scheduledDate` to `today`, `completed: false`\n  - `Tomorrow` - set `scheduledDate` to `tomorrow`, `completed: false`\n  - `Scheduled` - set `completed: false`, display the date popup if `scheduledDate` is `[ null, today, tomorrow ]`\n\n- Due date can only be changed manually\n\n# `TaskForm`\n\nThis is what the user sees when they click the card or `Add task`\n\n![](task-create-edit.png)\n\n- There is only one self-expanding text area for both title and description, everything after the first newline is considered as description.\n- `Add task` prefills `scheduledDate` depending on a column:\n  - `Backlog` - nothing is prefilled\n  - `Today` - `scheduledDate` is set to today\n  - `Tomorrow` - `scheduledDate` is set to tomorrow\n  - `Scheduled` - `scheduledDate` is not set but when you try to save you are shown a warning and you can change the date or the card lands in `Backlog`. If you enter today's or tomorrow's date, the card lands in the respective column.\n- Card is highlighted after creation so it can be easily seen.\n- On the mobile the view switches to the column the card is created in\n  - The simplest way to do this is via `CSS`, so the last column has `.active` class and the other ones are hidden when the viewport is too small.\n  - We store the active column in the url like `/:column/:task_uuid(/calendar)` but it only changes what is visible on mobile devices\n- They can enter dates manually or via dropdown once they focus in a field\n- Manual entry is very fast on the desktop as you can just type `13` or `monday` and it will be recognized.\n- By default priority is `P3` (low)\n- Card can be completed right away then it will be added on the top of the `Done` column\n\n# Concerns\n\n- `dueDate` does not affect anything, we should at least highlight overdue cards\n- `startDate` is a better way for `scheduledDate` should be named\n- Original version did not have `Done` column but I see no reason keeping the `Done` items in sight. We could even hide the `Done` column and treat is as an `Archive` if we need to restore something\n- Task splitting could be done on the backend as well\n\n# Estimates\n\nTasks are estimated in scores not hours. `3` is a \"`standard task`\" that you know how to do. And if the coast is clear you do one before lunch, one after and pick up a couple of smaller ones along the way. `5` is something you are not so sure about or maybe it needs to be broken down into smaller tasks.\n\n## Day 1 - Data Handling\n\n- Project Setup - 3\n- Data loading - 3\n- Data splitting - 2\n\n## Day 2 - `TaskCard`\n\n- TaskCard component - 1\n- Subcomponents for priority, dates - 2\n- Responsive styles - 2\n\n## Day 3 - `TaskColumn`\n\n- TaskColumn component - 3\n  - Display Cards nicely\n- Add dropdown for mobile - 2\n- Add task component - 3\n\n## Day 4 - `TaskBoard`\n\n- Board layout with multiple columns - 2\n- Mobile version - 2\n- Add drag-n-drop - 2\n- Add placeholders - 2\n- Mobile drop target - 2\n\n## Day 5 - `TaskForm`\n\n- `TaskForm` component - 3\n- Error handling - 3\n- Create/edit card - 3\n\n## Day 6 - Card Creation\n\n- Card created with no date - 2\n- Card created for today - 2\n- Card created for tomorrow - 2\n\n## Day 7 - Card Creation 2\n\n- Scheduled card creation - 2\n- Scheduler popup - 3\n- Calendar - 3\n\n## Day 8 - Done Column\n\n- Make sure unscheduled Tasks display popup when dropped in the schedules column - 3\n- Done column - 3\n\n## EXTRA: Positioning\n\n- Add position column - 2\n- Allow drag and drop withing a column - 3\n\n# Figures\n\n![](task.png)\n![](task-grid.png)\n![](task-create-edit.png)\n![](column.png)\n![](board.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffiredev%2Ftodo-mock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffiredev%2Ftodo-mock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffiredev%2Ftodo-mock/lists"}