1
0
Fork 0
mirror of https://github.com/pawelmalak/flame.git synced 2025-07-22 04:49:36 +02:00

Updating categories using form

This commit is contained in:
unknown 2021-05-26 13:13:56 +02:00
parent 0f2125e720
commit 216c12a33c
11 changed files with 176 additions and 30 deletions

View file

@ -5,6 +5,7 @@ import { App, NewApp } from '../../../interfaces';
import ModalForm from '../../UI/Forms/ModalForm/ModalForm'; import ModalForm from '../../UI/Forms/ModalForm/ModalForm';
import InputGroup from '../../UI/Forms/InputGroup/InputGroup'; import InputGroup from '../../UI/Forms/InputGroup/InputGroup';
import Button from '../../UI/Buttons/Button/Button';
interface ComponentProps { interface ComponentProps {
modalHandler: () => void; modalHandler: () => void;
@ -35,6 +36,12 @@ const AppForm = (props: ComponentProps): JSX.Element => {
url: props.app.url, url: props.app.url,
icon: props.app.icon icon: props.app.icon
}) })
} else {
setFormData({
name: '',
url: '',
icon: ''
})
} }
}, [props.app]) }, [props.app])
@ -114,8 +121,8 @@ const AppForm = (props: ComponentProps): JSX.Element => {
</span> </span>
</InputGroup> </InputGroup>
{!props.app {!props.app
? <button type="submit">add</button> ? <Button>Add new application</Button>
: <button type="submit">update</button> : <Button>Update application</Button>
} }
</ModalForm> </ModalForm>
) )

View file

@ -21,8 +21,11 @@
} }
} }
/* 320px 480px: Mobile devices. .GridMessage {
481px 768px: iPads, Tablets. color: var(--color-primary);
769px 1024px: Small screens, laptops. }
1025px 1200px: Desktops, large screens.
1201px and more Extra large screens, TV. */ .GridMessage a {
color: var(--color-accent);
font-weight: 600;
}

View file

@ -104,7 +104,7 @@ const Apps = (props: ComponentProps): JSX.Element => {
: (!isInEdit : (!isInEdit
? props.apps.length > 0 ? props.apps.length > 0
? <AppGrid apps={props.apps} /> ? <AppGrid apps={props.apps} />
: <p className={classes.AppsMessage}>You don't have any applications. You can a new one from <Link to='/applications'>/application</Link> menu</p> : <p className={classes.AppsMessage}>You don't have any applications. You can add a new one from <Link to='/applications'>/application</Link> menu</p>
: <AppTable updateAppHandler={toggleUpdate} />) : <AppTable updateAppHandler={toggleUpdate} />)
} }
</div> </div>

View file

@ -3,16 +3,20 @@ import { connect } from 'react-redux';
import ModalForm from '../../UI/Forms/ModalForm/ModalForm'; import ModalForm from '../../UI/Forms/ModalForm/ModalForm';
import InputGroup from '../../UI/Forms/InputGroup/InputGroup'; import InputGroup from '../../UI/Forms/InputGroup/InputGroup';
import { Category, GlobalState, NewBookmark, NewCategory } from '../../../interfaces'; import { Category, GlobalState, NewBookmark, NewCategory, NewNotification } from '../../../interfaces';
import { ContentType } from '../Bookmarks'; import { ContentType } from '../Bookmarks';
import { getCategories, addCategory, addBookmark } from '../../../store/actions'; import { getCategories, addCategory, addBookmark, updateCategory, createNotification } from '../../../store/actions';
import Button from '../../UI/Buttons/Button/Button';
interface ComponentProps { interface ComponentProps {
modalHandler: () => void; modalHandler: () => void;
contentType: ContentType; contentType: ContentType;
categories: Category[]; categories: Category[];
category?: Category;
addCategory: (formData: NewCategory) => void; addCategory: (formData: NewCategory) => void;
addBookmark: (formData: NewBookmark) => void; addBookmark: (formData: NewBookmark) => void;
updateCategory: (id: number, formData: NewCategory) => void;
createNotification: (notification: NewNotification) => void;
} }
const BookmarkForm = (props: ComponentProps): JSX.Element => { const BookmarkForm = (props: ComponentProps): JSX.Element => {
@ -26,24 +30,46 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => {
categoryId: -1 categoryId: -1
}) })
useEffect(() => {
if (props.category) {
setCategoryName({ name: props.category.name });
} else {
setCategoryName({ name: '' });
}
}, [props.category])
const formSubmitHandler = (e: SyntheticEvent<HTMLFormElement>): void => { const formSubmitHandler = (e: SyntheticEvent<HTMLFormElement>): void => {
e.preventDefault(); e.preventDefault();
if (props.contentType === ContentType.category) { if (!props.category) {
props.addCategory(categoryName); // Add new
setCategoryName({ name: '' }); if (props.contentType === ContentType.category) {
} else if (props.contentType === ContentType.bookmark) { props.addCategory(categoryName);
if (formData.categoryId === -1) { setCategoryName({ name: '' });
alert('select category'); } else if (props.contentType === ContentType.bookmark) {
return; if (formData.categoryId === -1) {
props.createNotification({
title: 'Error',
message: 'Please select category'
})
return;
}
props.addBookmark(formData);
setFormData({
name: '',
url: '',
categoryId: formData.categoryId
})
}
} else {
// Update
if (props.contentType === ContentType.category) {
props.updateCategory(props.category.id, categoryName);
setCategoryName({ name: '' });
} }
props.addBookmark(formData); props.modalHandler();
setFormData({
name: '',
url: '',
categoryId: formData.categoryId
})
} }
} }
@ -133,7 +159,10 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => {
</Fragment> </Fragment>
) )
} }
<button type='submit'>add</button> {!props.category
? <Button>Add new category</Button>
: <Button>Update category</Button>
}
</ModalForm> </ModalForm>
) )
} }
@ -144,4 +173,12 @@ const mapStateToProps = (state: GlobalState) => {
} }
} }
export default connect(mapStateToProps, { getCategories, addCategory, addBookmark })(BookmarkForm); const dispatchMap = {
getCategories,
addCategory,
addBookmark,
updateCategory,
createNotification
}
export default connect(mapStateToProps, dispatchMap)(BookmarkForm);

View file

@ -13,6 +13,7 @@ interface ComponentProps {
categories: Category[]; categories: Category[];
pinCategory: (category: Category) => void; pinCategory: (category: Category) => void;
deleteCategory: (id: number) => void; deleteCategory: (id: number) => void;
updateCategoryHandler: (category: Category) => void;
} }
const BookmarkTable = (props: ComponentProps): JSX.Element => { const BookmarkTable = (props: ComponentProps): JSX.Element => {
@ -50,7 +51,7 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => {
</div> </div>
<div <div
className={classes.TableAction} className={classes.TableAction}
// onClick={() => props.updateAppHandler(app)} onClick={() => props.updateCategoryHandler(category)}
// onKeyDown={(e) => keyboardActionHandler(e, app, props.updateAppHandler)} // onKeyDown={(e) => keyboardActionHandler(e, app, props.updateAppHandler)}
tabIndex={0}> tabIndex={0}>
<Icon icon='mdiPencil' /> <Icon icon='mdiPencil' />

View file

@ -32,6 +32,15 @@ const Bookmarks = (props: ComponentProps): JSX.Element => {
const [formContentType, setFormContentType] = useState(ContentType.category); const [formContentType, setFormContentType] = useState(ContentType.category);
const [isInEdit, setIsInEdit] = useState(false); const [isInEdit, setIsInEdit] = useState(false);
const [tableContentType, setTableContentType] = useState(ContentType.category); const [tableContentType, setTableContentType] = useState(ContentType.category);
const [isInUpdate, setIsInUpdate] = useState(false);
const [categoryInUpdate, setCategoryInUpdate] = useState<Category>({
name: '',
id: -1,
isPinned: false,
bookmarks: [],
createdAt: new Date(),
updatedAt: new Date()
})
useEffect(() => { useEffect(() => {
if (props.categories.length === 0) { if (props.categories.length === 0) {
@ -45,6 +54,7 @@ const Bookmarks = (props: ComponentProps): JSX.Element => {
const addActionHandler = (contentType: ContentType) => { const addActionHandler = (contentType: ContentType) => {
setFormContentType(contentType); setFormContentType(contentType);
setIsInUpdate(false);
toggleModal(); toggleModal();
} }
@ -62,10 +72,21 @@ const Bookmarks = (props: ComponentProps): JSX.Element => {
} }
} }
const goToUpdateMode = (category: Category): void => {
setIsInUpdate(true);
setCategoryInUpdate(category);
toggleModal();
}
let modalForm: JSX.Element;
return ( return (
<Container> <Container>
<Modal isOpen={modalIsOpen} setIsOpen={toggleModal}> <Modal isOpen={modalIsOpen} setIsOpen={toggleModal}>
<BookmarkForm modalHandler={toggleModal} contentType={formContentType} /> {!isInUpdate
? <BookmarkForm modalHandler={toggleModal} contentType={formContentType} />
: <BookmarkForm modalHandler={toggleModal} contentType={formContentType} category={categoryInUpdate} />
}
</Modal> </Modal>
<Headline <Headline
@ -101,8 +122,13 @@ const Bookmarks = (props: ComponentProps): JSX.Element => {
: (!isInEdit : (!isInEdit
? props.categories.length > 0 ? props.categories.length > 0
? <BookmarkGrid categories={props.categories} /> ? <BookmarkGrid categories={props.categories} />
: <p className={classes.BookmarksMessage}>You don't have any bookmarks. You can a new one from <Link to='/bookmarks'>/bookmarks</Link> menu</p> : <p className={classes.BookmarksMessage}>You don't have any bookmarks. You can add a new one from <Link to='/bookmarks'>/bookmarks</Link> menu</p>
: <BookmarkTable contentType={tableContentType} categories={props.categories} />) : (<BookmarkTable
contentType={tableContentType}
categories={props.categories}
updateCategoryHandler={goToUpdateMode}
/>)
)
} }
</Container> </Container>
) )

View file

@ -0,0 +1,14 @@
.Button {
padding: 8px 15px;
border: 1px solid var(--color-accent);
background-color: var(--color-background);
color: var(--color-primary);
border-radius: 4px;
}
.Button:hover,
.Button:focus {
cursor: pointer;
background-color: var(--color-accent);
color: var(--color-background);
}

View file

@ -0,0 +1,11 @@
import classes from './Button.module.css';
interface ComponentProps {
children: string;
}
const Button = (props: ComponentProps): JSX.Element => {
return <button className={classes.Button}>{props.children}</button>
}
export default Button;

View file

@ -13,6 +13,7 @@ import {
AddBookmarkAction, AddBookmarkAction,
PinCategoryAction, PinCategoryAction,
DeleteCategoryAction, DeleteCategoryAction,
UpdateCategoryAction,
// Notifications // Notifications
CreateNotificationAction, CreateNotificationAction,
ClearNotificationAction ClearNotificationAction
@ -38,6 +39,7 @@ export enum ActionTypes {
addBookmark = 'ADD_BOOKMARK', addBookmark = 'ADD_BOOKMARK',
pinCategory = 'PIN_CATEGORY', pinCategory = 'PIN_CATEGORY',
deleteCategory = 'DELETE_CATEGORY', deleteCategory = 'DELETE_CATEGORY',
updateCategory = 'UPDATE_CATEGORY',
// Notifications // Notifications
createNotification = 'CREATE_NOTIFICATION', createNotification = 'CREATE_NOTIFICATION',
clearNotification = 'CLEAR_NOTIFICATION' clearNotification = 'CLEAR_NOTIFICATION'
@ -58,6 +60,7 @@ export type Action =
AddBookmarkAction | AddBookmarkAction |
PinCategoryAction | PinCategoryAction |
DeleteCategoryAction | DeleteCategoryAction |
UpdateCategoryAction |
// Notifications // Notifications
CreateNotificationAction | CreateNotificationAction |
ClearNotificationAction; ClearNotificationAction;

View file

@ -147,4 +147,33 @@ export const deleteCategory = (id: number) => async (dispatch: Dispatch) => {
} catch (err) { } catch (err) {
console.log(err); console.log(err);
} }
}
/**
* UPDATE CATEGORY
*/
export interface UpdateCategoryAction {
type: ActionTypes.updateCategory,
payload: Category
}
export const updateCategory = (id: number, formData: NewCategory) => async (dispatch: Dispatch) => {
try {
const res = await axios.put<ApiResponse<Category>>(`/api/categories/${id}`, formData);
dispatch<CreateNotificationAction>({
type: ActionTypes.createNotification,
payload: {
title: 'Success',
message: `Category ${formData.name} updated`
}
})
dispatch<UpdateCategoryAction>({
type: ActionTypes.updateCategory,
payload: res.data.data
})
} catch (err) {
console.log(err);
}
} }

View file

@ -78,6 +78,20 @@ const deleteCategory = (state: State, action: Action): State => {
} }
} }
const updateCategory = (state: State, action: Action): State => {
const tmpCategories = [...state.categories];
const categoryInUpdate = tmpCategories.find((category: Category) => category.id === action.payload.id);
if (categoryInUpdate) {
categoryInUpdate.name = action.payload.name;
}
return {
...state,
categories: tmpCategories
}
}
const bookmarkReducer = (state = initialState, action: Action) => { const bookmarkReducer = (state = initialState, action: Action) => {
switch (action.type) { switch (action.type) {
case ActionTypes.getCategories: return getCategories(state, action); case ActionTypes.getCategories: return getCategories(state, action);
@ -86,6 +100,7 @@ const bookmarkReducer = (state = initialState, action: Action) => {
case ActionTypes.addBookmark: return addBookmark(state, action); case ActionTypes.addBookmark: return addBookmark(state, action);
case ActionTypes.pinCategory: return pinCategory(state, action); case ActionTypes.pinCategory: return pinCategory(state, action);
case ActionTypes.deleteCategory: return deleteCategory(state, action); case ActionTypes.deleteCategory: return deleteCategory(state, action);
case ActionTypes.updateCategory: return updateCategory(state, action);
default: return state; default: return state;
} }
} }