frontend: iterate on CSS / UI
This commit is contained in:
parent
7b600c2e82
commit
6bd3e3ad65
16 changed files with 316 additions and 189 deletions
|
@ -1,9 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Twenty::Model < ActiveRecord::Base
|
||||
require "fileutils"
|
||||
extend FileUtils
|
||||
|
||||
require_relative "model/project"
|
||||
require_relative "model/task"
|
||||
end
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
$black: lighten(#000, 20%);
|
||||
$gray1: #f4f0ec;
|
||||
$gray2: lighten($gray1, 5%);
|
||||
$gray3: #cfcfc4;
|
||||
$blue: #008cff;
|
||||
$primary-color: #FFF;
|
||||
$secondary-color: #333;
|
||||
$accent-color: #0066CC;
|
||||
|
|
17
twenty-frontend/src/css/_global.scss
Normal file
17
twenty-frontend/src/css/_global.scss
Normal file
|
@ -0,0 +1,17 @@
|
|||
body .wrapper {
|
||||
a {
|
||||
@import "colors";
|
||||
color: $accent-color;
|
||||
&:hover,
|
||||
&:active,
|
||||
&:visited {
|
||||
color: $accent-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.w-85 { width: 85%; }
|
||||
}
|
20
twenty-frontend/src/css/_layout.scss
Normal file
20
twenty-frontend/src/css/_layout.scss
Normal file
|
@ -0,0 +1,20 @@
|
|||
.two-columns {
|
||||
display: flex;
|
||||
flex-direction: space-between;
|
||||
|
||||
.column-1 {
|
||||
width: 20%;
|
||||
}
|
||||
.column-2 {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.max-width {
|
||||
width: 75%;
|
||||
max-width: 1024px;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
margin: 0 auto;
|
||||
}
|
|
@ -1,66 +1,108 @@
|
|||
/**
|
||||
-----------------
|
||||
| ul.collection |
|
||||
-----------------
|
||||
**/
|
||||
|
||||
ul.collection {
|
||||
h1 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: $primary-color;
|
||||
color: $secondary-color;
|
||||
height: 25px;
|
||||
width: 100%;
|
||||
font-size: medium;
|
||||
}
|
||||
}
|
||||
|
||||
ul.collection li.item {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding-bottom: 5px;
|
||||
a {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 50px;
|
||||
justify-content: space-between;
|
||||
padding: 10px 10px 5px 0px;
|
||||
.title {
|
||||
display: flex;
|
||||
padding-bottom: 5px;
|
||||
font-size: smaller;
|
||||
}
|
||||
.subtitle {
|
||||
font-size: small;
|
||||
color: $secondary-color;
|
||||
}
|
||||
}
|
||||
ul.actions {
|
||||
list-style-type: none;
|
||||
width: 5%;
|
||||
display: flex;
|
||||
place-content: flex-end;
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul.collection li.item.removed {
|
||||
animation: bounceOutDown;
|
||||
animation-duration: 0.5s;
|
||||
}
|
||||
|
||||
ul.collection li.item.completed {
|
||||
animation: bounceOutUp;
|
||||
animation-duration: 0.5s;
|
||||
}
|
||||
|
||||
ul.items {
|
||||
@import "colors";
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
|
||||
li.item:first-child {
|
||||
a {
|
||||
border-top: 1px solid #FFF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ul.items.nav {
|
||||
border: 1px solid $secondary-color;
|
||||
border-radius: 5px;
|
||||
background: $secondary-color;
|
||||
color: $primary-color;
|
||||
width: 85%;
|
||||
padding: 10px;
|
||||
|
||||
h1 {
|
||||
height: unset;
|
||||
font-size: smaller;
|
||||
align-items: center;
|
||||
background: $secondary-color;
|
||||
color: $primary-color;
|
||||
margin-top: 10px;
|
||||
}
|
||||
h1:first-child {
|
||||
margin-top: unset;
|
||||
}
|
||||
|
||||
li.item {
|
||||
padding: 5px;
|
||||
justify-content: space-between;
|
||||
background: $primary-color;
|
||||
color: $secondary-color;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
font-size: smaller;
|
||||
height: 25px;
|
||||
a {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 60px;
|
||||
justify-content: space-between;
|
||||
$blue: #008cff;
|
||||
color: $blue;
|
||||
padding: 10px 10px 5px 10px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #FFF;
|
||||
border-top: 1px solid $gray1;
|
||||
|
||||
&:hover {
|
||||
background: $gray1;
|
||||
border: 1px solid $gray3;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
color: $blue;
|
||||
}
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
}
|
||||
span.date, span.path {
|
||||
font-size: small;
|
||||
color: $black;
|
||||
}
|
||||
display: inline;
|
||||
height: unset;
|
||||
padding: unset;
|
||||
}
|
||||
ul.actions {
|
||||
list-style-type: none;
|
||||
width: 5%;
|
||||
display: flex;
|
||||
place-content: flex-end;
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
li.item.removed {
|
||||
animation: bounceOutDown;
|
||||
animation-duration: 0.5s;
|
||||
}
|
||||
li.item.completed {
|
||||
animation: bounceOutUp;
|
||||
animation-duration: 0.5s;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
73
twenty-frontend/src/css/_panels.scss
Normal file
73
twenty-frontend/src/css/_panels.scss
Normal file
|
@ -0,0 +1,73 @@
|
|||
.panel h1 {
|
||||
@import "colors";
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: $primary-color;
|
||||
color: $secondary-color;
|
||||
height: 25px;
|
||||
width: 100%;
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
.panel .panel-header.panel-tabs {
|
||||
@import "colors";
|
||||
padding: 5px 5px 0 0px;
|
||||
ul.tabs {
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
li:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
li {
|
||||
font-size: small;
|
||||
height: 100%;
|
||||
margin-right: 5px;
|
||||
border: 1px solid $accent-color;
|
||||
border-bottom: none;
|
||||
padding: 10px 5px 5px 10px;
|
||||
border-radius: 5px;
|
||||
min-width: 120px;
|
||||
text-align: center;
|
||||
background: $secondary-color;
|
||||
color: lighten($secondary-color, 15%);
|
||||
cursor: pointer;
|
||||
opacity: 0.5;
|
||||
}
|
||||
li.active, li:hover {
|
||||
font-weight: bold;
|
||||
color: $secondary-color;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.panel .panel-body {
|
||||
@import "colors";
|
||||
width: 100%;
|
||||
.task.content {
|
||||
padding: 10px;
|
||||
ul li {
|
||||
line-height: 1.7em;
|
||||
}
|
||||
h3,h4,h5 {
|
||||
&:first-child {
|
||||
margin: 0 0 5px 0;
|
||||
}
|
||||
margin: 15px 0 5px 0;
|
||||
}
|
||||
code {
|
||||
padding: 0px 5px 0px 5px;
|
||||
font-family: "Noto Sans Mono Regular";
|
||||
font-size: smaller;
|
||||
font-weight: bold;
|
||||
color: lighten(#FF0000, 25%);
|
||||
border-radius: 5px;
|
||||
border: 1px solid $accent-color;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
width: 100%;
|
||||
color: #FFF;
|
||||
background: $gray1;
|
||||
color: $black;
|
||||
color: $secondary-color;
|
||||
border-radius: 2px;
|
||||
border: #cfcfc4 1px solid;
|
||||
border-bottom: none;
|
||||
|
@ -37,14 +37,14 @@
|
|||
min-width: 120px;
|
||||
text-align: center;
|
||||
background: darken($gray1, 10%);
|
||||
color: lighten($black, 15%);
|
||||
color: lighten($secondary-color, 15%);
|
||||
cursor: pointer;
|
||||
opacity: 0.5;
|
||||
}
|
||||
li.active, li:hover {
|
||||
font-weight: bold;
|
||||
background: #FFF;
|
||||
color: $black;
|
||||
color: $secondary-color;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
@import "fonts";
|
||||
@import "colors";
|
||||
@import "tables";
|
||||
@import "global";
|
||||
@import "layout";
|
||||
@import "panels";
|
||||
@import "lists";
|
||||
|
||||
@import "vendor/forms";
|
||||
@import "vendor/animations";
|
||||
|
||||
|
@ -9,39 +12,13 @@
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html, html body, .root {
|
||||
html, html body, .wrapper {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Courier new', serif;
|
||||
font-weight: normal;
|
||||
font-family: "Noto Sans Regular";
|
||||
}
|
||||
|
||||
body header {
|
||||
width: 100%;
|
||||
background: $gray1;
|
||||
min-height: 40px;
|
||||
border-bottom: 1px solid $gray3;
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
ul.nav {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
list-style-type: none;
|
||||
column-gap: 10px;
|
||||
align-items: center;
|
||||
li a {
|
||||
&:hover {
|
||||
color: $blue;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pt-20 { padding-top: 20px; }
|
||||
|
@ -50,24 +27,11 @@ body header {
|
|||
.mb-50 { margin-bottom: 50px; }
|
||||
.w-100 { width: 100%; }
|
||||
|
||||
.max-width {
|
||||
width: 75%;
|
||||
max-width: 1024px;
|
||||
}
|
||||
.wrapper {
|
||||
color: $secondary-color;
|
||||
|
||||
.align-center {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.root {
|
||||
color: $black;
|
||||
.task {
|
||||
.content {
|
||||
padding: 10px;
|
||||
}
|
||||
.content, textarea {
|
||||
min-height: 350px;
|
||||
}
|
||||
.react-mount {
|
||||
padding-top: 25px;
|
||||
}
|
||||
|
||||
.trash.icon, .done.icon {
|
||||
|
|
|
@ -1 +1 @@
|
|||
<svg id="Layer_2_00000088828019791583343630000013885780770304495538_" enable-background="new 0 0 512 512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><g id="Icon"><g id="_29"><path d="m362.7 414.8c-37.4 0-68.4-13.9-92.2-41.4-23.4-27.1-35.2-66.6-35.2-117.6s11.9-90.4 35.5-117c23.9-27 55.1-40.7 92.7-40.7s68.6 13.7 92 40.6c23 26.5 34.6 66.4 34.6 118.4s-11.9 91.8-35.4 117.9c-23.7 26.4-54.7 39.8-92 39.8zm0-217.5c-4.4 0-11.1 1.4-18.3 13.1-6.3 10.3-9.5 25.7-9.5 45.8 0 20 3.1 35.4 9.1 45.4 6.8 11.4 13.9 12.7 18.7 12.7s11.8-1.3 18.6-12.9c6-10.2 9.1-25.6 9.1-45.7s-3.2-35.4-9.5-45.5c-7.9-12.9-15.7-12.9-18.2-12.9zm-306.9 213.4c-15 0-25.1-12.1-30-36.1v-.1c-2.1-10.9-3.1-19-3.1-25 0-5.1.5-12.5 5.3-17.3 77.9-80.4 89.6-111.3 89.6-122.6 0-4.9-1-8.3-2.9-10.1-2-1.9-6.3-3-12-3-7.4 0-14.9 1.4-22.4 4.3-7.7 2.9-13.7 6-17.9 9.3-1.8 1.4-4 2.1-6.1 2.1-2.9 0-5.7-1.2-7.7-3.6-11.6-14-19.8-29-24.3-44.6-1.6-5.5-2.5-10.8-2.5-15.8s.9-10 2.6-14.7c3.4-10.5 15.2-18.8 36.9-26.4 19.3-6.7 39.9-10 61.3-10 84.7 0 102.5 50.1 102.5 92.1 0 26.1-8.9 52.8-26.4 79.2-11.6 17.5-24.7 33.6-39.1 48l56-2.2h.4c5.1 0 9.5 3.9 9.9 9.1 1.4 14.9 2.1 28 2.1 38.9 0 12.5-2.7 23.4-8 32.3-6.2 10.5-15.6 16-27.2 16z" fill="#003c72"/><path d="m192.8 400.7h-137c-9.6 0-16.4-9.3-20.2-28.1-1.9-10.2-2.9-17.9-2.9-23.1s.8-8.7 2.5-10.3c61.6-63.6 92.5-106.8 92.5-129.6 0-7.7-2-13.5-6-17.3s-10.3-5.8-19-5.8-17.3 1.7-26 5-15.5 6.9-20.4 10.7c-10.7-12.9-18.2-26.6-22.3-40.9-1.4-4.7-2.1-9-2.1-13s.7-7.8 2.1-11.4c2.2-7.1 12.5-13.9 30.8-20.2s37.6-9.5 58-9.5c61.6 0 92.5 27.4 92.5 82.1 0 24.2-8.3 48.8-24.8 73.7s-35.8 46.4-57.8 64.6l83.4-3.3c1.4 14.6 2.1 27.2 2.1 38 0 10.7-2.2 19.8-6.6 27.2-4.6 7.5-10.8 11.2-18.8 11.2zm169.9 4.1c-34.5 0-62.7-12.7-84.6-38s-32.8-62.3-32.8-111 11-85.5 33-110.4 50.4-37.4 85.2-37.4 63 12.4 84.4 37.1c21.5 24.8 32.2 62.1 32.2 111.9s-10.9 86.9-32.8 111.2c-21.9 24.4-50.1 36.6-84.6 36.6zm0-217.5c-10.6 0-19.5 6-26.8 17.9-7.3 12-10.9 29-10.9 51s3.5 38.9 10.5 50.6 16.1 17.5 27.2 17.5 20.2-5.9 27.2-17.8c7-11.8 10.5-28.8 10.5-50.8s-3.6-38.9-10.9-50.8c-7.3-11.7-16.2-17.6-26.8-17.6z" fill="#008cff"/></g></g></svg>
|
||||
<svg id="Layer_2_00000088828019791583343630000013885780770304495538_" enable-background="new 0 0 512 512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><g id="Icon"><g id="_29"><path d="m362.7 414.8c-37.4 0-68.4-13.9-92.2-41.4-23.4-27.1-35.2-66.6-35.2-117.6s11.9-90.4 35.5-117c23.9-27 55.1-40.7 92.7-40.7s68.6 13.7 92 40.6c23 26.5 34.6 66.4 34.6 118.4s-11.9 91.8-35.4 117.9c-23.7 26.4-54.7 39.8-92 39.8zm0-217.5c-4.4 0-11.1 1.4-18.3 13.1-6.3 10.3-9.5 25.7-9.5 45.8 0 20 3.1 35.4 9.1 45.4 6.8 11.4 13.9 12.7 18.7 12.7s11.8-1.3 18.6-12.9c6-10.2 9.1-25.6 9.1-45.7s-3.2-35.4-9.5-45.5c-7.9-12.9-15.7-12.9-18.2-12.9zm-306.9 213.4c-15 0-25.1-12.1-30-36.1v-.1c-2.1-10.9-3.1-19-3.1-25 0-5.1.5-12.5 5.3-17.3 77.9-80.4 89.6-111.3 89.6-122.6 0-4.9-1-8.3-2.9-10.1-2-1.9-6.3-3-12-3-7.4 0-14.9 1.4-22.4 4.3-7.7 2.9-13.7 6-17.9 9.3-1.8 1.4-4 2.1-6.1 2.1-2.9 0-5.7-1.2-7.7-3.6-11.6-14-19.8-29-24.3-44.6-1.6-5.5-2.5-10.8-2.5-15.8s.9-10 2.6-14.7c3.4-10.5 15.2-18.8 36.9-26.4 19.3-6.7 39.9-10 61.3-10 84.7 0 102.5 50.1 102.5 92.1 0 26.1-8.9 52.8-26.4 79.2-11.6 17.5-24.7 33.6-39.1 48l56-2.2h.4c5.1 0 9.5 3.9 9.9 9.1 1.4 14.9 2.1 28 2.1 38.9 0 12.5-2.7 23.4-8 32.3-6.2 10.5-15.6 16-27.2 16z" fill="#003c72"/><path d="m192.8 400.7h-137c-9.6 0-16.4-9.3-20.2-28.1-1.9-10.2-2.9-17.9-2.9-23.1s.8-8.7 2.5-10.3c61.6-63.6 92.5-106.8 92.5-129.6 0-7.7-2-13.5-6-17.3s-10.3-5.8-19-5.8-17.3 1.7-26 5-15.5 6.9-20.4 10.7c-10.7-12.9-18.2-26.6-22.3-40.9-1.4-4.7-2.1-9-2.1-13s.7-7.8 2.1-11.4c2.2-7.1 12.5-13.9 30.8-20.2s37.6-9.5 58-9.5c61.6 0 92.5 27.4 92.5 82.1 0 24.2-8.3 48.8-24.8 73.7s-35.8 46.4-57.8 64.6l83.4-3.3c1.4 14.6 2.1 27.2 2.1 38 0 10.7-2.2 19.8-6.6 27.2-4.6 7.5-10.8 11.2-18.8 11.2zm169.9 4.1c-34.5 0-62.7-12.7-84.6-38s-32.8-62.3-32.8-111 11-85.5 33-110.4 50.4-37.4 85.2-37.4 63 12.4 84.4 37.1c21.5 24.8 32.2 62.1 32.2 111.9s-10.9 86.9-32.8 111.2c-21.9 24.4-50.1 36.6-84.6 36.6zm0-217.5c-10.6 0-19.5 6-26.8 17.9-7.3 12-10.9 29-10.9 51s3.5 38.9 10.5 50.6 16.1 17.5 27.2 17.5 20.2-5.9 27.2-17.8c7-11.8 10.5-28.8 10.5-50.8s-3.6-38.9-10.9-50.8c-7.3-11.7-16.2-17.6-26.8-17.6z" fill="#FFF"/></g></g></svg>
|
||||
|
|
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
|
@ -1,4 +1,4 @@
|
|||
<div class='root align-center max-width'>
|
||||
<div class='wrapper align-center max-width'>
|
||||
<div class="react-mount projects"></div>
|
||||
<script src="/js/main/projects.js"></script>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="root align-center max-width">
|
||||
<div class="wrapper align-center max-width">
|
||||
<div class="react-mount tasks"></div>
|
||||
<script src="/js/main/tasks.js"></script>
|
||||
</div>
|
||||
|
|
19
twenty-frontend/src/js/components/NavBar.tsx
Normal file
19
twenty-frontend/src/js/components/NavBar.tsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
import React from "react";
|
||||
|
||||
export function NavBar() {
|
||||
return (
|
||||
<ul className="items nav">
|
||||
<h1>Tasks</h1>
|
||||
<li className="item">
|
||||
<a href="/tasks/new">New</a> task
|
||||
</li>
|
||||
<li className="item">
|
||||
<a href="/tasks">Show</a> tasks
|
||||
</li>
|
||||
<h1>Projects</h1>
|
||||
<li className="item">
|
||||
<a href="/projects">Show</a> projects
|
||||
</li>
|
||||
</ul>
|
||||
);
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import React, { useEffect } from "react";
|
||||
import { NavBar } from "/components/NavBar";
|
||||
import { useProjects } from "/hooks/useProjects";
|
||||
|
||||
export function Projects() {
|
||||
|
@ -9,23 +10,28 @@ export function Projects() {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<div className="table">
|
||||
<div className="table div">
|
||||
<span>Projects</span>
|
||||
<div className="two-columns">
|
||||
<div className="column-1">
|
||||
<NavBar/>
|
||||
</div>
|
||||
<div className="table content">
|
||||
<ul className="items projects">
|
||||
{projects.map((project, i) => {
|
||||
return (
|
||||
<li className="item" key={i}>
|
||||
<a href={`/tasks#project_id=${project.id}`}>
|
||||
<span>{project.name}</span>
|
||||
<span className="path">{project.path}</span>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
<div className="column-2">
|
||||
<div className="panel">
|
||||
<h1>Projects</h1>
|
||||
<div className="panel-body">
|
||||
<ul className="collection">
|
||||
{projects.map((project, i) => {
|
||||
return (
|
||||
<li className="item" key={i}>
|
||||
<a href={`/tasks#project_id=${project.id}`}>
|
||||
<span className="title">{project.name}</span>
|
||||
<span className="subtitle">{project.path}</span>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -47,8 +47,8 @@ export function Task({ task }: { task?: Task }) {
|
|||
return (
|
||||
<form className="task" onSubmit={handleSubmit(onSave)}>
|
||||
<input type="hidden" value={task?.id} {...register("id")} />
|
||||
<div className="table">
|
||||
<div className="table tabbed div">
|
||||
<div className="panel">
|
||||
<div className="panel-header panel-tabs">
|
||||
<ul className="tabs">
|
||||
<li
|
||||
className={classnames({ active: isEditable })}
|
||||
|
@ -64,7 +64,7 @@ export function Task({ task }: { task?: Task }) {
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="table content">
|
||||
<div className="panel-body">
|
||||
<div>
|
||||
<Select {...register("projectId")} className="form">
|
||||
{projects.map((project, key) => {
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react";
|
|||
import { useTasks } from "/hooks/useTasks";
|
||||
import { useDestroyTask } from "/hooks/useDestroyTask";
|
||||
import { TrashIcon, DoneIcon } from "/components/Icons";
|
||||
import { NavBar } from "/components/NavBar";
|
||||
import { DateTime } from "luxon";
|
||||
import { Task, TASK_COMPLETE } from "/types/schema";
|
||||
import { useUpsertTask } from "/hooks/useUpsertTask";
|
||||
|
@ -49,53 +50,57 @@ export function Tasks() {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<div className="table">
|
||||
<div className="table div">
|
||||
<span>Tasks</span>
|
||||
<a href="/tasks/new">New task</a>
|
||||
<div className="two-columns">
|
||||
<div className="column-1">
|
||||
<NavBar/>
|
||||
</div>
|
||||
<div className="table content">
|
||||
<ul className="items tasks">
|
||||
{tasks.map((task: Task, key: number) => {
|
||||
const { updated_at: updatedAt } = task;
|
||||
const datetime = DateTime.fromISO(updatedAt);
|
||||
const wasDestroyed = task === destroyedTask;
|
||||
const wasCompleted = task === completedTask;
|
||||
const classes = { completed: wasCompleted, removed: wasDestroyed };
|
||||
const editHref = `/tasks/edit#id=${task.id}`;
|
||||
return (
|
||||
<li className={classnames("item", classes)} key={key}>
|
||||
<a href={editHref}>
|
||||
<span className="item title">{task.title}</span>
|
||||
<span className="date">
|
||||
{datetime.toFormat("dd LLL, yyyy")} at{" "}
|
||||
{datetime.toFormat("HH:mm")}
|
||||
</span>
|
||||
</a>
|
||||
<ul className="actions">
|
||||
<li>
|
||||
<DoneIcon
|
||||
title="Complete task"
|
||||
onClick={(e: React.MouseEvent) => [
|
||||
e.stopPropagation(),
|
||||
onComplete(task),
|
||||
]}
|
||||
/>
|
||||
<div className="column-2">
|
||||
<div className="panel">
|
||||
<h1>Tasks</h1>
|
||||
<div className="panel-body">
|
||||
<ul className="collection">
|
||||
{tasks.map((task: Task, key: number) => {
|
||||
const { updated_at: updatedAt } = task;
|
||||
const datetime = DateTime.fromISO(updatedAt);
|
||||
const wasDestroyed = task === destroyedTask;
|
||||
const wasCompleted = task === completedTask;
|
||||
const classes = { completed: wasCompleted, removed: wasDestroyed };
|
||||
const editHref = `/tasks/edit#id=${task.id}`;
|
||||
return (
|
||||
<li className={classnames("item", classes)} key={key}>
|
||||
<a className="w-85" href={editHref}>
|
||||
<span className="title">{task.title}</span>
|
||||
<span className="subtitle">
|
||||
{datetime.toFormat("dd LLL, yyyy")} at{" "}
|
||||
{datetime.toFormat("HH:mm")}
|
||||
</span>
|
||||
</a>
|
||||
<ul className="actions">
|
||||
<li>
|
||||
<DoneIcon
|
||||
title="Complete task"
|
||||
onClick={(e: React.MouseEvent) => [
|
||||
e.stopPropagation(),
|
||||
onComplete(task),
|
||||
]}
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<TrashIcon
|
||||
title="Delete task"
|
||||
onClick={(e: React.MouseEvent) => [
|
||||
e.stopPropagation(),
|
||||
onDestroy(task),
|
||||
]}
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<TrashIcon
|
||||
title="Delete task"
|
||||
onClick={(e: React.MouseEvent) => [
|
||||
e.stopPropagation(),
|
||||
onDestroy(task),
|
||||
]}
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -7,20 +7,6 @@
|
|||
<link rel="icon" href="/favicon.svg"/>
|
||||
</head>
|
||||
<body>
|
||||
<header class="mb-50">
|
||||
<div class="align-center max-width wrapper">
|
||||
<a href="/">
|
||||
<img width=48 height=48 src="/favicon.svg"/>
|
||||
</a>
|
||||
<ul class="nav">
|
||||
<li>
|
||||
<a href="/projects">Projects</a>
|
||||
<li>
|
||||
<a href="/tasks">Tasks</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</header>
|
||||
<%= yield %>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue