Skip to content

Commit

Permalink
✨ promote/demote event
Browse files Browse the repository at this point in the history
  • Loading branch information
valenber committed Aug 23, 2020
1 parent 820621f commit 1ebcf1f
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 8 deletions.
8 changes: 4 additions & 4 deletions data/databaseService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,19 @@ async function deleteAgendaEvent(id: string): Promise<string> {

async function updateAgendaEvent(
eventObject: Partial<AgendaEvent>,
): Promise<string> {
): Promise<AgendaEvent> {
const { id } = eventObject;
delete eventObject.id;

const [client, q] = getDB();

const { ref } = await client.query(
q.Update(q.Ref(q.Collection(targetCollection, id)), eventObject),
const { ref, data } = await client.query(
q.Update(q.Ref(q.Collection(targetCollection), id), { data: eventObject }),
);

const updatedRecordRef: string = extractRefString(ref);

return updatedRecordRef;
return { ...data, id: updatedRecordRef };
}

export const databaseService = {
Expand Down
2 changes: 1 addition & 1 deletion data/dbSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export type AgendaEventCategory =
| 'events'
| 'christmas';

type AgendaEventStatus = 'candidate' | 'highlight' | 'mainfocus';
export type AgendaEventStatus = 'candidate' | 'highlight' | 'mainfocus';

// this is an examle of a valid agenda event object
export const exampleAgendaEvent: AgendaEvent = {
Expand Down
75 changes: 75 additions & 0 deletions features/edit-event/eventButtonGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from 'react';
import { ButtonGroup, IconButton } from '@material-ui/core';
import StarIcon from '@material-ui/icons/Star';
import StarBorderIcon from '@material-ui/icons/StarBorder';
import StarsIcon from '@material-ui/icons/Stars';
import { AgendaEvent } from '../../data/dbSchema';
import { useSelector, useDispatch } from 'react-redux';
import { getSelectedCategory } from './getSelectedCategory';
import { updateEventProps } from '../../services/api';
import { patchEvent } from '../../store/eventsSlice';

interface EventButtonGroupProps {
event: AgendaEvent;
}

/*
[x] display correct star
on click
[x] prepare DB update objetc
[x] call endpoint to update DB
[ ] patch the store with new version of event */

export const EventButtonGroup: React.FC<EventButtonGroupProps> = ({
event,
}) => {
const dispatch = useDispatch();

const selectedCategory = useSelector(getSelectedCategory);
const eventStatus = event.state[selectedCategory];
const { id } = event;

const stateIconMap = {
candidate: <StarBorderIcon color="primary" />,
highlight: <StarIcon color="primary" />,
mainfocus: <StarsIcon color="primary" />,
};

const StateButton = (): React.ReactElement => stateIconMap[eventStatus];

const nextStatusMap = {
candidate: 'highlight',
highlight: 'mainfocus',
mainfocus: 'candidate',
};

async function handlePromoteButtonClic(): Promise<void> {
const statusUpdateObject = {
id: id,
state: {
[selectedCategory]: nextStatusMap[eventStatus],
},
};

const { event, error } = await updateEventProps(statusUpdateObject);

if (error) {
console.error(error);
return;
}

if (event) {
dispatch(patchEvent(event));
return;
}
}

return (
<ButtonGroup>
<IconButton onClick={handlePromoteButtonClic}>
<StateButton />
</IconButton>
</ButtonGroup>
);
};
6 changes: 6 additions & 0 deletions features/edit-event/getSelectedCategory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { AppState } from '../../store/';
import { AgendaEventCategory } from '../../data/dbSchema';

export function getSelectedCategory(state: AppState): AgendaEventCategory {
return state.events.selectedCategory;
}
2 changes: 2 additions & 0 deletions features/view-candidate-events/CandidatesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getCandidatesForSelectedCategory } from './getCandidatesForSelectedCate
import { useSelector } from 'react-redux';
import { AgendaEvent } from '../../data/dbSchema';
import { dateFormat } from '../shared/helpers';
import { EventButtonGroup } from '../edit-event/eventButtonGroup';

export const CandidatesList: React.FC = () => {
const categoryCandidates: AgendaEvent[] = useSelector(
Expand All @@ -29,6 +30,7 @@ export const CandidatesList: React.FC = () => {
<Typography gutterBottom variant="body1" component="h5">
{event.name}
</Typography>
<EventButtonGroup event={event} />
</CardContent>
</Card>
);
Expand Down
2 changes: 2 additions & 0 deletions features/view-highlighted-events/HighlightsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { AgendaEvent } from '../../data/dbSchema';
import { useSelector } from 'react-redux';
import { getHighlightsForSelectedCategory } from './getHighlightsForSelectedCategory';
import { dateFormat } from '../shared/helpers';
import { EventButtonGroup } from '../edit-event/eventButtonGroup';

export const HighlightsList: React.FC = () => {
const categoryHighlights = useSelector(getHighlightsForSelectedCategory);
Expand All @@ -23,6 +24,7 @@ export const HighlightsList: React.FC = () => {
<Typography gutterBottom variant="h6" component="h3">
{event.name}
</Typography>
<EventButtonGroup event={event} />
</CardContent>
</Card>
);
Expand Down
34 changes: 31 additions & 3 deletions services/api.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import fetch from 'isomorphic-unfetch';
import { AgendaEvent } from '../data/dbSchema';

export interface ApiEventsResponse {
export interface ApiGetEventsResponse {
events: AgendaEvent[] | null;
error: string | null;
}

export async function getAllApiEvents(): Promise<ApiEventsResponse> {
export async function getAllApiEvents(): Promise<ApiGetEventsResponse> {
try {
const res = await fetch('/api/events');
if (!res.ok) {
Expand All @@ -17,7 +17,35 @@ export async function getAllApiEvents(): Promise<ApiEventsResponse> {

return { events, error: null };
} catch (error) {
console.log(error.code);
return { error: error.message, events: null };
}
}

export interface ApiUpdateEventResponse {
event: AgendaEvent | null;
error: string | null;
}

export async function updateEventProps(
updateObject: Partial<AgendaEvent>,
): Promise<ApiUpdateEventResponse> {
try {
const res = await fetch('/api/events', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(updateObject),
});

if (!res.ok) {
throw new Error(`Bad server response - ${res.status}: ${res.statusText}`);
}

const updatedEvent = await res.json().then((json) => json.data);

return { event: updatedEvent, error: null };
} catch (error) {
return { event: null, error: error.message };
}
}
13 changes: 13 additions & 0 deletions store/eventsSlice.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
addEvent,
addEventsList,
removeEventById,
patchEvent,
initialState,
selectEventCategory,
} from './eventsSlice';
Expand Down Expand Up @@ -52,4 +53,16 @@ describe('reducers', () => {

expect(newState.selectedCategory).toBe(null);
});

test('update event props by id', () => {
const updatedEvent = { ...firstEvent, name: 'Event twenty one' };
const newState = eventsReducer(
{ ...initialState, list: [firstEvent, secondEvent] },
patchEvent(updatedEvent),
);
expect(newState).toEqual({
...initialState,
list: [updatedEvent, secondEvent],
});
});
});
11 changes: 11 additions & 0 deletions store/eventsSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ const events = createSlice({
): void {
state.selectedCategory = action.payload;
},

patchEvent(state, action: PayloadAction<AgendaEvent>): EventsSlice {
const { payload } = action;
return {
...state,
list: state.list.map((event) =>
event.id === payload.id ? payload : event,
),
};
},
},
});

Expand All @@ -51,4 +61,5 @@ export const {
addEventsList,
removeEventById,
selectEventCategory,
patchEvent,
} = events.actions;

0 comments on commit 1ebcf1f

Please sign in to comment.