Move delete logic from event list to event detail page and implement Dialog component for confirmation. Redirect to event list after delete

This commit is contained in:
Scott Roach 2021-03-08 02:09:07 -08:00
parent 78f3e69e25
commit 2ee4be8de6
No known key found for this signature in database
GPG Key ID: 641478CF54A92761
2 changed files with 42 additions and 24 deletions

View File

@ -1,5 +1,10 @@
import { h, Fragment } from 'preact'; import { h, Fragment } from 'preact';
import { useCallback, useState } from 'preact/hooks';
import { route } from 'preact-router';
import ActivityIndicator from '../components/ActivityIndicator'; import ActivityIndicator from '../components/ActivityIndicator';
import Button from '../components/Button';
import Delete from '../icons/Delete'
import Dialog from '../components/Dialog';
import Heading from '../components/Heading'; import Heading from '../components/Heading';
import Link from '../components/Link'; import Link from '../components/Link';
import { FetchStatus, useApiHost, useEvent } from '../api'; import { FetchStatus, useApiHost, useEvent } from '../api';
@ -8,6 +13,23 @@ import { Table, Thead, Tbody, Th, Tr, Td } from '../components/Table';
export default function Event({ eventId }) { export default function Event({ eventId }) {
const apiHost = useApiHost(); const apiHost = useApiHost();
const { data, status } = useEvent(eventId); const { data, status } = useEvent(eventId);
const [showDialog, setShowDialog] = useState(false);
const handleClickDelete = () => {
setShowDialog(true);
}
const handleDismissDeleteDialog = () => {
setShowDialog(false);
};
const handleClickDeleteDialog = useCallback(
async () => {
await fetch(`${apiHost}/api/events/${eventId}`, {method: 'DELETE'});
setShowDialog(false);
route('/events', true);
}, [apiHost, eventId, setShowDialog]
);
if (status !== FetchStatus.LOADED) { if (status !== FetchStatus.LOADED) {
return <ActivityIndicator />; return <ActivityIndicator />;
@ -18,9 +40,25 @@ export default function Event({ eventId }) {
return ( return (
<div className="space-y-4"> <div className="space-y-4">
<Heading> <div className="flex">
<Heading className="flex-grow">
{data.camera} {data.label} <span className="text-sm">{startime.toLocaleString()}</span> {data.camera} {data.label} <span className="text-sm">{startime.toLocaleString()}</span>
</Heading> </Heading>
<Button className="self-start" color="red" aria-label="Delete Event" onClick={handleClickDelete}>
<Delete className="w-6" />
</Button>
{showDialog ? (
<Dialog
onDismiss={handleDismissDeleteDialog}
title="Delete Event?"
text="This event will be permanently deleted along with any related clips and snapshots"
actions={[
{ text: 'Delete', color: 'red', onClick: handleClickDeleteDialog },
{ text: 'Cancel', onClick: handleDismissDeleteDialog },
]}
/>
) : null}
</div>
<Table class="w-full"> <Table class="w-full">
<Thead> <Thead>

View File

@ -7,8 +7,6 @@ import produce from 'immer';
import { route } from 'preact-router'; import { route } from 'preact-router';
import { useIntersectionObserver } from '../hooks'; import { useIntersectionObserver } from '../hooks';
import { FetchStatus, useApiHost, useConfig, useEvents } from '../api'; import { FetchStatus, useApiHost, useConfig, useEvents } from '../api';
import Button from '../components/Button';
import Delete from '../icons/Delete'
import { Table, Thead, Tbody, Tfoot, Th, Tr, Td } from '../components/Table'; import { Table, Thead, Tbody, Tfoot, Th, Tr, Td } from '../components/Table';
import { useCallback, useEffect, useMemo, useReducer, useState } from 'preact/hooks'; import { useCallback, useEffect, useMemo, useReducer, useState } from 'preact/hooks';
@ -101,18 +99,6 @@ export default function Events({ path: pathname, limit = API_LIMIT } = {}) {
[limit, pathname, setSearchString] [limit, pathname, setSearchString]
); );
const handleDelete = useCallback(
async (eventId) => {
// eslint-disable-next-line no-alert
if(confirm('Are you sure you want to delete this event and any related clips and snapshots?')) {
await fetch(`${apiHost}/api/events/${eventId}`);
const { searchParams } = new URL(window.location);
handleFilter(searchParams)
}
},
[apiHost, handleFilter]
);
const searchParams = useMemo(() => new URLSearchParams(searchString), [searchString]); const searchParams = useMemo(() => new URLSearchParams(searchString), [searchString]);
return ( return (
@ -133,7 +119,6 @@ export default function Events({ path: pathname, limit = API_LIMIT } = {}) {
<Th>Date</Th> <Th>Date</Th>
<Th>Start</Th> <Th>Start</Th>
<Th>End</Th> <Th>End</Th>
<Th />
</Tr> </Tr>
</Thead> </Thead>
<Tbody> <Tbody>
@ -194,11 +179,6 @@ export default function Events({ path: pathname, limit = API_LIMIT } = {}) {
<Td>{start.toLocaleDateString()}</Td> <Td>{start.toLocaleDateString()}</Td>
<Td>{start.toLocaleTimeString()}</Td> <Td>{start.toLocaleTimeString()}</Td>
<Td>{end.toLocaleTimeString()}</Td> <Td>{end.toLocaleTimeString()}</Td>
<Td>
<Button color="red" name="Delete" onClick={() => handleDelete(id)}>
<Delete className="w-6" />
</Button>
</Td>
</Tr> </Tr>
); );
} }
@ -206,7 +186,7 @@ export default function Events({ path: pathname, limit = API_LIMIT } = {}) {
</Tbody> </Tbody>
<Tfoot> <Tfoot>
<Tr> <Tr>
<Td className="text-center p-4" colspan="9"> <Td className="text-center p-4" colspan="8">
{status === FetchStatus.LOADING ? <ActivityIndicator /> : reachedEnd ? 'No more events' : null} {status === FetchStatus.LOADING ? <ActivityIndicator /> : reachedEnd ? 'No more events' : null}
</Td> </Td>
</Tr> </Tr>