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

Added App Edit Functionality

This commit is contained in:
unknown 2021-05-22 17:03:32 +02:00
parent 28683e7511
commit 8813bf6181
6 changed files with 98 additions and 12 deletions

View file

@ -1,7 +1,7 @@
import { useState, ChangeEvent, SyntheticEvent } from 'react'; import { useState, useEffect, ChangeEvent, SyntheticEvent } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { addApp } from '../../../store/actions'; import { addApp, updateApp } from '../../../store/actions';
import { NewApp } from '../../../interfaces/App'; import { App, NewApp } from '../../../interfaces/App';
import classes from './AppForm.module.css'; import classes from './AppForm.module.css';
import Icon from '../../UI/Icons/Icon/Icon'; import Icon from '../../UI/Icons/Icon/Icon';
@ -9,6 +9,8 @@ import Icon from '../../UI/Icons/Icon/Icon';
interface ComponentProps { interface ComponentProps {
modalHandler: Function; modalHandler: Function;
addApp: (formData: NewApp) => any; addApp: (formData: NewApp) => any;
updateApp: (id: number, formData: NewApp) => any;
app?: App;
} }
const AppForm = (props: ComponentProps): JSX.Element => { const AppForm = (props: ComponentProps): JSX.Element => {
@ -18,6 +20,17 @@ const AppForm = (props: ComponentProps): JSX.Element => {
icon: '' icon: ''
}); });
useEffect(() => {
if (props.app) {
console.log('app');
setFormData({
name: props.app.name,
url: props.app.url,
icon: props.app.icon
})
}
}, [props.app])
const _modalHandler = () => { const _modalHandler = () => {
props.modalHandler(); props.modalHandler();
} }
@ -31,7 +44,14 @@ const AppForm = (props: ComponentProps): JSX.Element => {
const formSubmitHandler = (e: SyntheticEvent): void => { const formSubmitHandler = (e: SyntheticEvent): void => {
e.preventDefault(); e.preventDefault();
if (!props.app) {
props.addApp(formData); props.addApp(formData);
} else {
props.updateApp(props.app.id, formData);
props.modalHandler();
}
setFormData({ setFormData({
name: '', name: '',
url: '', url: '',
@ -90,10 +110,13 @@ const AppForm = (props: ComponentProps): JSX.Element => {
</a> </a>
</span> </span>
</div> </div>
<button type="submit">add</button> {!props.app
? <button type="submit">add</button>
: <button type="submit">update</button>
}
</form> </form>
</div> </div>
) )
} }
export default connect(null, { addApp })(AppForm); export default connect(null, { addApp, updateApp })(AppForm);

View file

@ -9,6 +9,7 @@ interface ComponentProps {
apps: App[]; apps: App[];
pinApp: (id: number, isPinned: boolean) => void; pinApp: (id: number, isPinned: boolean) => void;
deleteApp: (id: number) => void; deleteApp: (id: number) => void;
updateAppHandler: (app: App) => void;
} }
const AppTable = (props: ComponentProps): JSX.Element => { const AppTable = (props: ComponentProps): JSX.Element => {
@ -44,7 +45,11 @@ const AppTable = (props: ComponentProps): JSX.Element => {
onClick={() => deleteAppHandler(app)}> onClick={() => deleteAppHandler(app)}>
<Icon icon='mdiDelete' /> <Icon icon='mdiDelete' />
</div> </div>
<div className={classes.TableAction}><Icon icon='mdiPencil' /></div> <div
className={classes.TableAction}
onClick={() => props.updateAppHandler(app)}>
<Icon icon='mdiPencil' />
</div>
<div className={classes.TableAction} onClick={() => props.pinApp(app.id, app.isPinned)}> <div className={classes.TableAction} onClick={() => props.pinApp(app.id, app.isPinned)}>
{app.isPinned? <Icon icon='mdiPinOff' color='var(--color-accent)' /> : <Icon icon='mdiPin' />} {app.isPinned? <Icon icon='mdiPinOff' color='var(--color-accent)' /> : <Icon icon='mdiPin' />}
</div> </div>

View file

@ -34,6 +34,16 @@ interface ComponentProps {
const Apps = (props: ComponentProps): JSX.Element => { const Apps = (props: ComponentProps): JSX.Element => {
const [modalIsOpen, setModalIsOpen] = useState(false); const [modalIsOpen, setModalIsOpen] = useState(false);
const [isInEdit, setIsInEdit] = useState(false); const [isInEdit, setIsInEdit] = useState(false);
const [isInUpdate, setIsInUpdate] = useState(false);
const [appInUpdate, setAppInUpdate] = useState<App>({
name: 'string',
url: 'string',
icon: 'string',
isPinned: false,
id: 0,
createdAt: new Date(),
updatedAt: new Date()
})
useEffect(() => { useEffect(() => {
if (props.apps.length === 0) { if (props.apps.length === 0) {
@ -43,16 +53,27 @@ const Apps = (props: ComponentProps): JSX.Element => {
const toggleModal = (): void => { const toggleModal = (): void => {
setModalIsOpen(!modalIsOpen); setModalIsOpen(!modalIsOpen);
setIsInUpdate(false);
} }
const toggleEdit = (): void => { const toggleEdit = (): void => {
setIsInEdit(!isInEdit); setIsInEdit(!isInEdit);
setIsInUpdate(false);
}
const toggleUpdate = (app: App): void => {
setAppInUpdate(app);
setIsInUpdate(true);
setModalIsOpen(true);
} }
return ( return (
<Container> <Container>
<Modal isOpen={modalIsOpen} setIsOpen={setModalIsOpen}> <Modal isOpen={modalIsOpen} setIsOpen={setModalIsOpen}>
<AppForm modalHandler={toggleModal} /> {!isInUpdate
? <AppForm modalHandler={toggleModal} />
: <AppForm modalHandler={toggleModal} app={appInUpdate} />
}
</Modal> </Modal>
<Headline <Headline
@ -80,7 +101,7 @@ const Apps = (props: ComponentProps): JSX.Element => {
? 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 a new one from <Link to='/applications'>/application</Link> menu</p>
: <AppTable />) : <AppTable updateAppHandler={toggleUpdate} />)
} }
</div> </div>
</Container> </Container>

View file

@ -3,7 +3,8 @@ import {
SetThemeAction, SetThemeAction,
PinAppAction, PinAppAction,
AddAppAction, AddAppAction,
DeleteAppAction DeleteAppAction,
UpdateAppAction
} from './'; } from './';
export enum ActionTypes { export enum ActionTypes {
@ -14,7 +15,8 @@ export enum ActionTypes {
pinApp = 'PIN_APP', pinApp = 'PIN_APP',
addApp = 'ADD_APP', addApp = 'ADD_APP',
addAppSuccess = 'ADD_APP_SUCCESS', addAppSuccess = 'ADD_APP_SUCCESS',
deleteApp = 'DELETE_APP' deleteApp = 'DELETE_APP',
updateApp = 'UPDATE_APP'
} }
export type Action = GetAppsAction<any> | SetThemeAction | PinAppAction | AddAppAction | DeleteAppAction; export type Action = GetAppsAction<any> | SetThemeAction | PinAppAction | AddAppAction | DeleteAppAction | UpdateAppAction;

View file

@ -82,3 +82,21 @@ export const deleteApp = (id: number) => async (dispatch: Dispatch) => {
console.log(err); console.log(err);
} }
} }
export interface UpdateAppAction {
type: ActionTypes.updateApp;
payload: App;
}
export const updateApp = (id: number, formData: NewApp) => async (dispatch: Dispatch) => {
try {
const res = await axios.put<ApiResponse<App>>(`/api/apps/${id}`, formData);
dispatch<UpdateAppAction>({
type: ActionTypes.updateApp,
payload: res.data.data
})
} catch (err) {
console.log(err);
}
}

View file

@ -69,6 +69,22 @@ const deleteApp = (state: State, action: Action): State => {
} }
} }
const updateApp = (state: State, action: Action): State => {
const tmpApps = [...state.apps];
const appInUpdate = tmpApps.find((app: App) => app.id === action.payload.id);
if (appInUpdate) {
appInUpdate.name = action.payload.name;
appInUpdate.url = action.payload.url;
appInUpdate.icon = action.payload.icon;
}
return {
...state,
apps: tmpApps
}
}
const appReducer = (state = initialState, action: Action) => { const appReducer = (state = initialState, action: Action) => {
switch (action.type) { switch (action.type) {
case ActionTypes.getApps: return getApps(state, action); case ActionTypes.getApps: return getApps(state, action);
@ -77,6 +93,7 @@ const appReducer = (state = initialState, action: Action) => {
case ActionTypes.pinApp: return pinApp(state, action); case ActionTypes.pinApp: return pinApp(state, action);
case ActionTypes.addAppSuccess: return addAppSuccess(state, action); case ActionTypes.addAppSuccess: return addAppSuccess(state, action);
case ActionTypes.deleteApp: return deleteApp(state, action); case ActionTypes.deleteApp: return deleteApp(state, action);
case ActionTypes.updateApp: return updateApp(state, action);
default: return state; default: return state;
} }
} }