Skip to content
This repository has been archived by the owner on Jun 9, 2023. It is now read-only.

[WIP] Feature/events crud #341

Merged
merged 30 commits into from
Mar 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
7c01f69
Update react-hook-form
Zeko369 Feb 13, 2020
d006c54
Refactor routes to add support for dynamic routing
Zeko369 Feb 13, 2020
3b89d44
WIP: add create page\
Zeko369 Feb 13, 2020
4d6d323
WIP: Add show page
Zeko369 Feb 13, 2020
1c598ff
Fix typo
Zeko369 Feb 13, 2020
bb59eb6
Merge branch 'master' into feature/ChapterCRUDUi
Zeko369 Feb 14, 2020
15bb555
Add dashboard index and fix warning
Zeko369 Feb 14, 2020
b6cbf7f
Add tags to events
Zeko369 Feb 14, 2020
3e69352
Add tags to all events when seeding
Zeko369 Feb 15, 2020
dfba6d8
Cascade delete tags on event deletion
Zeko369 Feb 15, 2020
fa26a0d
Add cancel action
Zeko369 Feb 16, 2020
10f8ef1
Add delete method to http-service
Zeko369 Feb 16, 2020
361586f
Add event cancel action to redux
Zeko369 Feb 16, 2020
6a9e1e6
Update UI to add cancel event button
Zeko369 Feb 16, 2020
f9f24c9
Merge branch 'master' into feature/eventsCrud
Zeko369 Mar 14, 2020
c6e19e2
Merge branch 'master' into feature/eventsCrud
Zeko369 Mar 14, 2020
0ef8ef5
Make canceled optional param in Event constructor
Zeko369 Mar 14, 2020
5d4c910
Extract event create form to separete component
Zeko369 Mar 14, 2020
bc0607d
Finish event creation
Zeko369 Mar 14, 2020
a32e7da
Add cascade on delete for events
Zeko369 Mar 14, 2020
d800c9b
Add delete action and useConfirm hook
Zeko369 Mar 14, 2020
80900a1
Merge branch 'master' into feature/eventsCrud
Zeko369 Mar 14, 2020
93338d9
Fix merge error
Zeko369 Mar 14, 2020
3d738b3
Use useThunkDispatch and rename create.tsx to new.tsx
Zeko369 Mar 14, 2020
7cafd88
Merge branch 'master' into feature/eventsCrud
Zeko369 Mar 15, 2020
2f3d798
Load venues form API and add them to select on event create
Zeko369 Mar 15, 2020
47bf8ef
Add skeleton to events
Zeko369 Mar 15, 2020
3f93fbb
Add stub for edit action
Zeko369 Mar 15, 2020
a231d39
Nicer tmp dashboard
Zeko369 Mar 15, 2020
9918e35
Add events show page
Zeko369 Mar 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions client/components/Dashboard/Events/EventForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import React from 'react';
import { useForm, Controller } from 'react-hook-form';
import {
FormControl,
TextField,
Button,
makeStyles,
InputLabel,
Select,
MenuItem,
} from '@material-ui/core';
import { IVenueModal } from 'client/store/types/venues';

interface IField {
key: string;
label: string;
placeholder?: string;
type: string;
defaultValue?: string;
}

const fields: IField[] = [
{
key: 'name',
type: 'text',
label: 'Event title',
placeholder: 'Foo and the Bars',
},
{
key: 'description',
type: 'text',
label: 'Description',
placeholder: '',
},
{
key: 'capacity',
type: 'number',
label: 'Capacity',
placeholder: '50',
},
{
key: 'tags',
type: 'text',
label: 'Tags (separated by a comma)',
placeholder: 'Foo, bar',
},
{
key: 'start_at',
type: 'datetime-local',
label: 'Start at',
defaultValue: new Date().toISOString().slice(0, 16),
},
{
key: 'ends_at',
type: 'datetime-local',
label: 'End at',
defaultValue: new Date(Date.now() + 1000 * 60 * 60)
.toISOString()
.slice(0, 16),
},
];

const useStyles = makeStyles(() => ({
form: {
display: 'flex',
flexDirection: 'column',
maxWidth: '25%',
},
item: {
marginTop: '20px',
},
}));

export interface IEventFormData {
name: string;
description: string;
capacity: number;
tags: string;
venue: number;
}

interface IEventFormProps {
onSubmit: (data: IEventFormData) => void;
loading: boolean;
venues: IVenueModal[];
venuesLoading: boolean;
}

const EventForm: React.FC<IEventFormProps> = ({
onSubmit,
loading,
venues,
venuesLoading,
}) => {
const { control, handleSubmit } = useForm();
const styles = useStyles();

return (
<form onSubmit={handleSubmit(onSubmit)} className={styles.form}>
{fields.map(field => (
<FormControl className={styles.item} key={field.key}>
<Controller
control={control}
as={
<TextField
label={field.label}
type={field.type}
placeholder={field.placeholder}
/>
}
name={field.key}
defaultValue={field.defaultValue}
options={{ required: true }}
/>
</FormControl>
))}
{venuesLoading ? (
<h1>Loading venues...</h1>
) : (
<FormControl className={styles.item}>
<InputLabel id="venue-label">Venue</InputLabel>
<Controller
control={control}
as={
<Select labelId="venue-label">
{venues.map(venue => (
<MenuItem value={venue.id} key={venue.id}>
{venue.name}
</MenuItem>
))}
</Select>
}
name="venue"
options={{ required: true }}
defaultValue={0}
/>
</FormControl>
)}
<Button
className={styles.item}
variant="contained"
color="primary"
type="submit"
disabled={loading}
>
Add Event
</Button>
</form>
);
};

export default EventForm;
49 changes: 44 additions & 5 deletions client/components/Dashboard/Events/EventItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React from 'react';
import { Card, Typography } from '@material-ui/core';
import { Card, Typography, Button } from '@material-ui/core';
import { useDispatch } from 'react-redux';
import Link from 'next/link';

import { IEventModal } from 'client/store/types/events';
import { eventActions } from 'client/store/actions';
import useConfirm from 'client/hooks/useConfirm';
import { ProgressCardContent } from 'client/components';

interface IEventItemProps {
Expand All @@ -10,18 +14,53 @@ interface IEventItemProps {
}

const EventItem: React.FC<IEventItemProps> = ({ event, loading }) => {
const dispatch = useDispatch();

const [confirmCancel, clickCancel] = useConfirm(() =>
dispatch(eventActions.cancelEvent(1, event.id)),
);
const [confirmRemove, clickRemove] = useConfirm(() =>
dispatch(eventActions.removeEvent(1, event.id)),
);

return (
<Card style={{ marginTop: '12px' }} key={`event-${event.id}`}>
<Card style={{ marginTop: '12px' }}>
<ProgressCardContent loading={loading}>
<Typography gutterBottom variant="h5" component="h2">
{event.name}
</Typography>
<Link
href="/dashboard/events/[id]"
as={`/dashboard/events/${event.id}`}
>
<a>
<Typography gutterBottom variant="h5" component="h2">
{event.name}
</Typography>
</a>
</Link>
{event.canceled && (
<Typography variant="h5" color="error">
Canceled
</Typography>
)}
<Typography variant="body2" color="textSecondary" component="p">
{event.description}
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
{event.capacity}
</Typography>
{!event.canceled && (
<Button onClick={clickCancel}>
{confirmCancel ? 'Are you sure?' : 'Cancel'}
</Button>
)}
<Button onClick={clickRemove}>
{confirmRemove ? 'Are you sure?' : 'delete'}
</Button>
<Link
href={`/dashboard/events/[id]/edit`}
as={`/dashboard/events/${event.id}/edit`}
>
<a style={{ marginLeft: '10px' }}>Edit</a>
</Link>
</ProgressCardContent>
</Card>
);
Expand Down
15 changes: 15 additions & 0 deletions client/components/Dashboard/Events/Skeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import Link from 'next/link';

const Skeleton: React.FC = ({ children }) => {
return (
<>
<Link href="/dashboard/events">
<a>Events</a>
</Link>
{children}
</>
);
};

export default Skeleton;
4 changes: 3 additions & 1 deletion client/components/Dashboard/Events/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import EventItem from './EventItem';
import EventForm from './EventForm';
import Skeleton from './Skeleton';

export { EventItem };
export { EventItem, EventForm, Skeleton };
25 changes: 25 additions & 0 deletions client/hooks/useConfirm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useEffect, useState } from 'react';

const useConfirm = (callback: Function): [boolean, () => void] => {
const [confirm, setConfirm] = useState<boolean>(false);

const click = () => {
if (confirm) {
callback();
} else {
setConfirm(true);
}
};

useEffect(() => {
if (confirm) {
setTimeout(() => {
setConfirm(false);
}, 2000);
}
}, [confirm]);

return [confirm, click];
};

export default useConfirm;
2 changes: 1 addition & 1 deletion client/modules/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const Home: React.FC = () => {
</Link>
<br />
<Link href="/dashboard">
<a>Dashboard</a>
<a>Admin dashboard</a>
</Link>
</>
);
Expand Down
Loading