frontend: add trash icon to destroy an issue

And remove DestroyIssueButton.
This commit is contained in:
0x1eef 2023-12-22 16:28:06 -03:00
parent f13093fa91
commit 08aaec54d5
5 changed files with 55 additions and 65 deletions

View file

@ -0,0 +1,24 @@
ul.items {
margin: 0;
padding: 0;
list-style-type: none;
li.item {
margin: 0 0 15px 0;
display: flex;
background: #f4f0ec;
border: #cfcfc4 1px solid;
border-radius: 10px;
padding: 10px;
flex-wrap: wrap;
.top, .bottom {
display: flex;
justify-content: space-between;
width: 100%;
}
.bottom {
margin: 10px 0 0 0;
font-size: small;
}
}
}

View file

@ -2,6 +2,7 @@
@import "colors"; @import "colors";
@import "forms"; @import "forms";
@import "tables"; @import "tables";
@import "items";
*, *:before, *:after { *, *:before, *:after {
box-sizing: border-box; box-sizing: border-box;
@ -34,38 +35,12 @@ body {
} }
} }
.react-mount.issues { .trash.icon {
ul { height: 20px;
margin: 0; width: 20px;
padding: 0; cursor: pointer;
list-style-type: none; g {
li { fill: #d9534f;
margin: 0 0 15px 0;
.item.row {
display: flex;
background: #f4f0ec;
border: #cfcfc4 1px solid;
border-radius: 10px;
padding: 10px;
flex-wrap: wrap;
.header {
.item.id {
border: 1px #cfcfc4 solid;
border-radius: 10px;
padding: 5px;
margin-right: 5px;
background: #FFF;
}
}
.footer {
display: flex;
width: 100%;
justify-content: space-between;
margin: 10px 0 0 0;
font-size: small;
}
}
}
} }
} }
} }

View file

@ -1,17 +0,0 @@
import React from "react";
import { Issue } from "/types/schema";
import { useDestroyIssue } from "/hooks/useDestroyIssue";
type Props = {
issue: Issue;
onSuccess: (issue: Issue) => unknown;
};
export function DestroyIssueButton({ issue, onSuccess }: Props) {
const destroy = useDestroyIssue();
const onClick = () => {
destroy({ id: issue.id }).then(() => onSuccess(issue));
};
return <button onClick={onClick}>Destroy</button>;
}

View file

@ -1,6 +1,6 @@
import React from "react"; import React from "react";
export function TrashIcon({onClick}: {onClick: () => unknown}) { export function TrashIcon({onClick}: {onClick?: () => unknown}) {
return ( return (
<svg <svg
height="512" height="512"
@ -8,6 +8,7 @@ export function TrashIcon({onClick}: {onClick: () => unknown}) {
width="512" width="512"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
onClick={onClick} onClick={onClick}
className="trash icon"
> >
<g> <g>
<path d="m95.331 27.471h-14.248v-4.516a5.712 5.712 0 0 0 -5.7-5.7h-22.762a5.712 5.712 0 0 0 -5.705 5.7v4.516h-14.248a5.425 5.425 0 0 0 -5.419 5.419v5.857a5.426 5.426 0 0 0 5.419 5.419h.071v59.041a7.551 7.551 0 0 0 7.542 7.543h47.437a7.551 7.551 0 0 0 7.542-7.543v-59.041h.071a5.425 5.425 0 0 0 5.418-5.419v-5.857a5.424 5.424 0 0 0 -5.418-5.419zm-44.915-4.516a2.207 2.207 0 0 1 2.205-2.2h22.757a2.207 2.207 0 0 1 2.2 2.2v4.516h-27.162zm41.344 80.252a4.047 4.047 0 0 1 -4.042 4.043h-47.437a4.047 4.047 0 0 1 -4.042-4.043v-59.041h55.521zm5.489-64.46a1.92 1.92 0 0 1 -1.918 1.919h-62.663a1.921 1.921 0 0 1 -1.919-1.919v-5.857a1.921 1.921 0 0 1 1.919-1.919h62.663a1.92 1.92 0 0 1 1.918 1.919z" /> <path d="m95.331 27.471h-14.248v-4.516a5.712 5.712 0 0 0 -5.7-5.7h-22.762a5.712 5.712 0 0 0 -5.705 5.7v4.516h-14.248a5.425 5.425 0 0 0 -5.419 5.419v5.857a5.426 5.426 0 0 0 5.419 5.419h.071v59.041a7.551 7.551 0 0 0 7.542 7.543h47.437a7.551 7.551 0 0 0 7.542-7.543v-59.041h.071a5.425 5.425 0 0 0 5.418-5.419v-5.857a5.424 5.424 0 0 0 -5.418-5.419zm-44.915-4.516a2.207 2.207 0 0 1 2.205-2.2h22.757a2.207 2.207 0 0 1 2.2 2.2v4.516h-27.162zm41.344 80.252a4.047 4.047 0 0 1 -4.042 4.043h-47.437a4.047 4.047 0 0 1 -4.042-4.043v-59.041h55.521zm5.489-64.46a1.92 1.92 0 0 1 -1.918 1.919h-62.663a1.921 1.921 0 0 1 -1.919-1.919v-5.857a1.921 1.921 0 0 1 1.919-1.919h62.663a1.92 1.92 0 0 1 1.918 1.919z" />

View file

@ -1,33 +1,40 @@
import React from "react"; import React from "react";
import { useIssues } from "/hooks/useIssues"; import { useIssues } from "/hooks/useIssues";
import { useDestroyIssue } from "/hooks/useDestroyIssue";
import { TrashIcon } from "/components/Icons"; import { TrashIcon } from "/components/Icons";
import { DateTime } from "luxon"; import { DateTime } from "luxon";
import { Issue } from "/types/schema"; import { Issue } from "/types/schema";
export function Issues() { export function Issues() {
const { issues } = useIssues(); const { issues, setIssues } = useIssues();
const destroyIssue = useDestroyIssue();
const onDestroy = (issue: Issue) => {
destroyIssue({id: issue.id})
.then(() => issues.filter((i) => i.id !== issue.id))
.then((issues) => setIssues(issues));
}
return ( return (
<div className="table"> <div className="table">
<div className="table div">Issues</div> <div className="table div">Issues</div>
<div className="table content"> <div className="table content">
<ul> <ul className="items">
{issues.map((issue: Issue, key: number) => { {issues.map((issue: Issue, key: number) => {
const { updated_at: updatedAt } = issue; const { updated_at: updatedAt } = issue;
const datetime = DateTime.fromISO(updatedAt); const datetime = DateTime.fromISO(updatedAt);
return ( return (
<li key={key}> <li className="item" key={key}>
<div className="item row"> <div className="top">
<div className="header"> <a href={`/issues/read#id=${issue.id}`}>
<a href={`/issues/read#id=${issue.id}`}> <span className="item title">{issue.title}</span>
<span className="item title">{issue.title}</span> </a>
</a> <span><TrashIcon onClick={() => onDestroy(issue)} /></span>
</div> </div>
<div className="footer"> <div className="bottom">
<span> <span>
{datetime.toFormat("dd LLL, yyyy")} at{" "} {datetime.toFormat("dd LLL, yyyy")} at{" "}
{datetime.toFormat("HH:mm")} {datetime.toFormat("HH:mm")}
</span> </span>
</div>
</div> </div>
</li> </li>
); );