Skip to content
Open
2 changes: 2 additions & 0 deletions client/Store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {ContactsStore} from '@client/admin/users/store/ContactsStore';
import {ExampleStore} from '@client/admin/example/store';

export interface Store {
example: ExampleStore;
contacts: ContactsStore;
}
31 changes: 31 additions & 0 deletions client/admin/users/actions/ContactsActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {bindActionCreators, Dispatch} from 'redux';
import {Action} from 'redux-actions';

const PREFIX = 'USERS_MODUL_';

export const ContactsActionType = {
DELETE_CONTACT: `${PREFIX}DELETE_CONTACT`,
ID: `${PREFIX}ID`,
EMPTY_CONTACT: `${PREFIX}EMPTY_CONTACT`,
ISOPEN: `${PREFIX}ISOPEN`,
ID_CONTACT: `${PREFIX}ID_CONTACT`,
HANDLE_CONTACT: `${PREFIX}HANDLE_CONTACT`,
SAVE_CONTACT: `${PREFIX}SAVE_CONTACT`,
};

const ContactsActionDispatch = {
isOpen: (): Action<void> => ({type: ContactsActionType.ISOPEN}),
contact: (): Action<string> => ({type: ContactsActionType.EMPTY_CONTACT, payload: ''}),
deleteContact: (id: number): Action<number> => ({type: ContactsActionType.DELETE_CONTACT, payload: id}),
idContact: (id: number): Action<number> => ({type: ContactsActionType.ID_CONTACT, payload: id}),
id: (id: number): Action<number> => ({type: ContactsActionType.ID, payload: id}),
handleOnChange: (e: React.ChangeEvent<HTMLInputElement>): Action<React.ChangeEvent<HTMLInputElement>> => ({
type: ContactsActionType.HANDLE_CONTACT,
payload: e,
}),
saveContact: (): Action<string> => ({type: ContactsActionType.SAVE_CONTACT, payload: ''}),
};

export type ContactsAction = typeof ContactsActionDispatch;

export const ContactsActionCreator = (dispatch: Dispatch) => bindActionCreators(ContactsActionDispatch, dispatch);
1 change: 1 addition & 0 deletions client/admin/users/actions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ContactsActions';
24 changes: 24 additions & 0 deletions client/admin/users/components/ContactList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as React from 'react';
import {TableRow, TableCell} from '@material-ui/core';
import {ContactModel} from './model';
import {EditButton} from './buttons/EditButton';
import {DeleteButton} from './buttons/DeleteButton';

interface Props {
contact: ContactModel;
deleteContact: (id: number) => () => void;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tady bys nemel potrebovat funkci, co vraci funkci

handleOnUserId: (id: number) => () => void;
}

export const ContactList: React.SFC<Props> = ({contact, deleteContact, handleOnUserId}) => (
<TableRow>
<TableCell>{contact.firstName}</TableCell>
<TableCell>{contact.lastName}</TableCell>
<TableCell>{contact.email}</TableCell>
<TableCell>{contact.phoneNumber}</TableCell>
<TableCell>
<EditButton handleOnUserId={handleOnUserId} contact={contact} />
<DeleteButton contact={contact} deleteContact={deleteContact} />
</TableCell>
</TableRow>
);
55 changes: 55 additions & 0 deletions client/admin/users/components/ContactsList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import * as React from 'react';
import {Paper, Table, TableHead, TableRow, TableCell, TableBody, withStyles} from '@material-ui/core';
import {ContactModel} from './model';
import {ContactList} from './ContactList';

interface Props {
contacts: ContactModel[];
deleteContact: (id: number) => () => void;
handleOnUserId: (id: number) => () => void;
nadpis?: string;
}

// type WithDataProps = Pick<Props, 'deleteContact' | 'handleOnUserId'>;

const decorate = withStyles(() => ({
paper: {
margin: '0 10px',
},
}));

const ContactsListData = decorate<Props>(({nadpis, classes, contacts, deleteContact, handleOnUserId}) => (
<Paper className={classes.paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>First Name</TableCell>
<TableCell>Last Name</TableCell>
<TableCell>E-mail</TableCell>
<TableCell>Phone number</TableCell>
<TableCell>{nadpis}</TableCell>
</TableRow>
</TableHead>
<TableBody>
{contacts.map((contact: ContactModel) => (
<ContactList key={contact.id} contact={contact} deleteContact={deleteContact} handleOnUserId={handleOnUserId} />
))}
</TableBody>
</Table>
</Paper>
));

const WithDataComponent = (BaseComponent: React.ComponentType<Props>): React.ComponentClass<Props> => {
const initialState = {
nadpis: 'Icons',
};
return class extends React.Component<Props, typeof initialState> {
readonly state = initialState;
render() {
const {nadpis} = this.state;
return <BaseComponent {...this.props} nadpis={nadpis} />;
}
};
};

export const ContactsList = WithDataComponent(ContactsListData);
60 changes: 60 additions & 0 deletions client/admin/users/components/SimpleModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import * as React from 'react';
import {TextField, withStyles} from '@material-ui/core';
import Modal from '@material-ui/core/Modal';
import Slide from '@material-ui/core/Slide';
import Typography from '@material-ui/core/Typography';
import {CancelButton} from './buttons/CancelButton';
import {ContactModel} from './model';
import {SubmitButton} from './buttons/SubmitButton';

interface Props {
isOpen: boolean;
handleOnClose: () => void;
contact: ContactModel;
handleOnChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
handleOnSave: () => void;
}

const decorate = withStyles(() => ({
modal: {
top: '25%',
margin: 'auto',
width: '400px',
backgroundColor: 'white',
padding: '20px',
},
modal_window: {
alignItems: 'center',
justifyContent: 'center',
},
}));

export const SimpleModal = decorate<Props>(({classes, isOpen, handleOnClose, contact, handleOnChange, handleOnSave}) => {
return (
<Modal
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
open={isOpen}
onClose={handleOnClose}
className={classes.modal_window}
>
<Slide direction="up" in={isOpen} mountOnEnter unmountOnExit>
<div className={classes.modal} style={{position: 'relative'}}>
<Typography variant="title" id="modal-title">
Add new user to database
</Typography>
<TextField name="firstName" id="name" label="First Name" value={contact.firstName} onChange={handleOnChange} margin="normal" required />
<br />
<TextField name="lastName" id="name" label="Last Name" value={contact.lastName} onChange={handleOnChange} margin="normal" required />
<br />
<TextField name="email" id="name" label="E-mail" value={contact.email} onChange={handleOnChange} margin="normal" required />
<br />
<TextField name="phoneNumber" id="name" label="Phone Number" value={contact.phoneNumber} onChange={handleOnChange} margin="normal" />
<br />
<SubmitButton handleOnSave={handleOnSave} />
<CancelButton handleOnClose={handleOnClose} />
</div>
</Slide>
</Modal>
);
});
68 changes: 66 additions & 2 deletions client/admin/users/components/UsersIndexPage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,72 @@
import * as React from 'react';
import {WithAdminProps} from '@client/with/withAdmin';
import {SimpleModal} from '@client/admin/users/components/SimpleModal';
import {ContactsList} from '@client/admin/users/components/ContactsList';
import {AddButton} from './buttons/AddButton';
import {ContactsStore} from '../store';
import {connect} from 'react-redux';
import {Store} from '@client/Store';
import {ContactsActionCreator, ContactsAction} from '../actions';

interface OwnProps extends WithAdminProps {}

interface ConnectedState {
readonly contacts: ContactsStore;
}

interface ConnectedDispatch extends ContactsAction {}

type Props = ConnectedState & ConnectedDispatch & OwnProps;

class UsersPage extends React.Component<Props> {
handleOnOpen = () => {
this.props.isOpen();
};

handleOnClose = () => {
this.props.isOpen();
this.props.contact();
};

handleOnDelete = (id: number) => () => {
this.props.deleteContact(id);
};

handleOnUserId = (id: number) => () => {
this.props.id(id);
this.props.isOpen();
this.props.idContact(id);
};

handleOnChange = (e: any) => {
this.props.handleOnChange(e);
};

handleOnSave = () => {
this.props.saveContact();
};

export class UsersIndexPage extends React.Component<WithAdminProps> {
render() {
return <div>UsersIndexPage</div>;
const {
contacts: {contacts, isOpen, contact},
} = this.props;
return (
<>
<AddButton handleOnOpen={this.handleOnOpen} />
<ContactsList contacts={contacts} deleteContact={this.handleOnDelete} handleOnUserId={this.handleOnUserId} />
<SimpleModal
isOpen={isOpen}
handleOnClose={this.handleOnClose}
contact={contact}
handleOnChange={this.handleOnChange}
handleOnSave={this.handleOnSave}
/>
</>
);
}
}

export const UsersIndexPage = connect<ConnectedState, ConnectedDispatch, OwnProps, any>(
({contacts}: Store) => ({contacts}),
ContactsActionCreator,
)(UsersPage);
21 changes: 21 additions & 0 deletions client/admin/users/components/buttons/AddButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as React from 'react';
import {Add} from '@material-ui/icons';
import {Button, withStyles} from '@material-ui/core';

interface Props {
handleOnOpen: () => void;
}

const decorate = withStyles(() => ({
button: {
margin: '10px',
},
}));

export const AddButton = decorate<Props>(({classes, handleOnOpen}) => {
return (
<Button className={classes.button} variant="fab" color="primary" aria-label="Add" mini onClick={handleOnOpen}>
<Add />
</Button>
);
});
20 changes: 20 additions & 0 deletions client/admin/users/components/buttons/CancelButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react';
import {Button, withStyles} from '@material-ui/core';

interface Props {
handleOnClose: () => void;
}

const decorate = withStyles(() => ({
button: {
margin: '10px',
},
}));

export const CancelButton = decorate<Props>(({classes, handleOnClose}) => {
return (
<Button variant="contained" color="default" mini onClick={handleOnClose} className={classes.button}>
Cancel
</Button>
);
});
23 changes: 23 additions & 0 deletions client/admin/users/components/buttons/DeleteButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from 'react';
import {Delete as DeleteIcon} from '@material-ui/icons';
import {Button, withStyles} from '@material-ui/core';
import {ContactModel} from '@client/admin/users/components/model';

interface Props {
contact: ContactModel;
deleteContact: (id: number) => () => void;
}

const decorate = withStyles(() => ({
button_edit: {
margin: '10px',
},
}));

export const DeleteButton = decorate<Props>(({deleteContact, contact}) => {
return (
<Button variant="fab" aria-label="Delete" mini onClick={deleteContact(contact.id)}>
<DeleteIcon />
</Button>
);
});
23 changes: 23 additions & 0 deletions client/admin/users/components/buttons/EditButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from 'react';
import Icon from '@material-ui/core/Icon';
import {Button, withStyles} from '@material-ui/core';
import {ContactModel} from '@client/admin/users/components/model';

interface Props {
contact: ContactModel;
handleOnUserId: (id: number) => () => void;
}

const decorate = withStyles(() => ({
button_edit: {
margin: '10px',
},
}));

export const EditButton = decorate<Props>(({classes, handleOnUserId, contact}) => {
return (
<Button variant="fab" color="secondary" aria-label="Edit" mini className={classes.button_edit} onClick={handleOnUserId(contact.id)}>
<Icon>edit_icon</Icon>
</Button>
);
});
20 changes: 20 additions & 0 deletions client/admin/users/components/buttons/SubmitButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react';
import {Button, withStyles} from '@material-ui/core';

interface Props {
handleOnSave: () => void;
}

const decorate = withStyles(() => ({
button: {
margin: '10px',
},
}));

export const SubmitButton = decorate<Props>(({handleOnSave}) => {
return (
<Button variant="contained" color="primary" mini onClick={handleOnSave}>
Submit
</Button>
);
});
1 change: 1 addition & 0 deletions client/admin/users/components/model/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './initialState';
Loading