mirror of
https://github.com/rjNemo/ticket_manager
synced 2026-06-12 11:46:40 +00:00
Created PageLayout and wrapped Project/User/TicketPages
This commit is contained in:
parent
880d7fafda
commit
6dea3bf41c
5 changed files with 167 additions and 99 deletions
43
client/src/layouts/PageLayout.tsx
Normal file
43
client/src/layouts/PageLayout.tsx
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
import React, { FC, ReactNode } from "react";
|
||||||
|
import { makeStyles, Theme, Container } from "@material-ui/core";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function useStyles creates the css styles used in the following component.
|
||||||
|
*/
|
||||||
|
const useStyles = makeStyles((theme: Theme) => ({
|
||||||
|
// root style allow for fixed footer
|
||||||
|
header: {
|
||||||
|
margin: theme.spacing(1),
|
||||||
|
marginTop: theme.spacing(2),
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
flexGrow: 1,
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
margin: theme.spacing(1),
|
||||||
|
marginTop: theme.spacing(2),
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
header: ReactNode;
|
||||||
|
content: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PageLayout divide the page in 2 parts: Header and Content, to ensure cohesion.
|
||||||
|
*
|
||||||
|
* @param Header - The encapsulated component.
|
||||||
|
* @param Content - The encapsulated component.
|
||||||
|
*/
|
||||||
|
const PageLayout: FC<IProps> = ({ header, content }) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
return (
|
||||||
|
<Container maxWidth="md">
|
||||||
|
<div className={classes.header}>{header}</div>
|
||||||
|
<div className={classes.content}>{content}</div>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PageLayout;
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
import React, { FC } from "react";
|
import React, { FC } from "react";
|
||||||
|
import PageLayout from "../layouts/PageLayout";
|
||||||
|
import { Header } from "../components/Header";
|
||||||
|
|
||||||
interface IProps {}
|
interface IProps {}
|
||||||
export const NotFoundPage: FC<IProps> = () => {
|
export const NotFoundPage: FC<IProps> = () => {
|
||||||
return (
|
return (
|
||||||
<div className="section">
|
<PageLayout
|
||||||
<p>error</p>
|
header={<Header title="Error page" description="Something went wrong" />}
|
||||||
</div>
|
content={<p>error</p>}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
import React, { FC, useState } from "react";
|
import React, { FC, useState } from "react";
|
||||||
import ProjectVM from "../VM/ProjectVM";
|
import { Container, Grid, makeStyles, Theme } from "@material-ui/core";
|
||||||
import { Header } from "../components/Header";
|
import { Header } from "../components/Header";
|
||||||
import { AvatarList } from "../components/AvatarList";
|
import { AvatarList } from "../components/AvatarList";
|
||||||
import { ProgressBar } from "../components/ProgressBar";
|
import { ProgressBar } from "../components/ProgressBar";
|
||||||
import { FloatingButton } from "../components/FloatingButton";
|
import { FloatingButton } from "../components/FloatingButton";
|
||||||
import { UsersModal } from "../components/UsersModal";
|
import { UsersModal } from "../components/UsersModal";
|
||||||
import { Container, Grid, makeStyles, Theme } from "@material-ui/core";
|
|
||||||
import { ProjectTabPanel } from "../components/ProjectTabPanel";
|
import { ProjectTabPanel } from "../components/ProjectTabPanel";
|
||||||
|
import ProjectVM from "../VM/ProjectVM";
|
||||||
|
import PageLayout from "../layouts/PageLayout";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
viewModel: ProjectVM;
|
viewModel: ProjectVM;
|
||||||
|
|
@ -15,8 +16,8 @@ interface IProps {
|
||||||
const useStyles = makeStyles((theme: Theme) => ({
|
const useStyles = makeStyles((theme: Theme) => ({
|
||||||
root: {
|
root: {
|
||||||
margin: theme.spacing(1),
|
margin: theme.spacing(1),
|
||||||
flexGrow: 1
|
flexGrow: 1,
|
||||||
}
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const ProjectPage: FC<IProps> = ({ viewModel }) => {
|
export const ProjectPage: FC<IProps> = ({ viewModel }) => {
|
||||||
|
|
@ -33,7 +34,7 @@ export const ProjectPage: FC<IProps> = ({ viewModel }) => {
|
||||||
remainingDays,
|
remainingDays,
|
||||||
files,
|
files,
|
||||||
// activities,
|
// activities,
|
||||||
allProjects
|
allProjects,
|
||||||
} = viewModel;
|
} = viewModel;
|
||||||
|
|
||||||
const tabNames: string[] = ["Tickets", "Files"]; //, "Activity"];
|
const tabNames: string[] = ["Tickets", "Files"]; //, "Activity"];
|
||||||
|
|
@ -41,47 +42,53 @@ export const ProjectPage: FC<IProps> = ({ viewModel }) => {
|
||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
return (
|
const Content: FC = () => {
|
||||||
<Container maxWidth="md">
|
return (
|
||||||
<div className={classes.root}>
|
<>
|
||||||
<Header title={title} description={description} />
|
<UsersModal
|
||||||
</div>
|
show={showModal}
|
||||||
<UsersModal
|
users={users}
|
||||||
show={showModal}
|
allUsers={allUsers}
|
||||||
users={users}
|
handleClose={() => setShowModal(false)}
|
||||||
allUsers={allUsers}
|
|
||||||
handleClose={() => setShowModal(false)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Grid container>
|
|
||||||
<Grid item xs={3}>
|
|
||||||
<AvatarList users={users} />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={9}>
|
|
||||||
<FloatingButton
|
|
||||||
icon="add"
|
|
||||||
color="default"
|
|
||||||
size="small"
|
|
||||||
onClick={() => setShowModal(true)}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<div className={classes.root}>
|
|
||||||
<ProgressBar
|
|
||||||
value={progression}
|
|
||||||
tasksDone={ticketsDone}
|
|
||||||
tasksTotalCount={ticketsTotalCount}
|
|
||||||
remainingDays={remainingDays}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<ProjectTabPanel
|
<Grid container>
|
||||||
tabNames={tabNames}
|
<Grid item xs={3}>
|
||||||
tickets={tickets}
|
<AvatarList users={users} />
|
||||||
files={files}
|
</Grid>
|
||||||
// activities={activities}
|
<Grid item xs={9}>
|
||||||
allProjects={allProjects}
|
<FloatingButton
|
||||||
/>
|
icon="add"
|
||||||
</Container>
|
color="default"
|
||||||
|
size="small"
|
||||||
|
onClick={() => setShowModal(true)}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<div className={classes.root}>
|
||||||
|
<ProgressBar
|
||||||
|
value={progression}
|
||||||
|
tasksDone={ticketsDone}
|
||||||
|
tasksTotalCount={ticketsTotalCount}
|
||||||
|
remainingDays={remainingDays}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ProjectTabPanel
|
||||||
|
tabNames={tabNames}
|
||||||
|
tickets={tickets}
|
||||||
|
files={files}
|
||||||
|
// activities={activities}
|
||||||
|
allProjects={allProjects}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageLayout
|
||||||
|
header={<Header title={title} description={description} />}
|
||||||
|
content={<Content />}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,10 @@ import {
|
||||||
makeStyles,
|
makeStyles,
|
||||||
Theme,
|
Theme,
|
||||||
Grid,
|
Grid,
|
||||||
Typography
|
Typography,
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import { Timer } from "@material-ui/icons";
|
import { Timer } from "@material-ui/icons";
|
||||||
|
import PageLayout from "../layouts/PageLayout";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
viewModel: TicketVM;
|
viewModel: TicketVM;
|
||||||
|
|
@ -28,11 +29,11 @@ interface IProps {
|
||||||
const useStyles = makeStyles((theme: Theme) => ({
|
const useStyles = makeStyles((theme: Theme) => ({
|
||||||
root: {
|
root: {
|
||||||
margin: theme.spacing(1),
|
margin: theme.spacing(1),
|
||||||
flexGrow: 1
|
flexGrow: 1,
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
minWidth: 650
|
minWidth: 650,
|
||||||
}
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const TicketPage: FC<IProps> = ({ viewModel }) => {
|
export const TicketPage: FC<IProps> = ({ viewModel }) => {
|
||||||
|
|
@ -45,50 +46,55 @@ export const TicketPage: FC<IProps> = ({ viewModel }) => {
|
||||||
status,
|
status,
|
||||||
category,
|
category,
|
||||||
impact,
|
impact,
|
||||||
difficulty
|
difficulty,
|
||||||
} = viewModel;
|
} = viewModel;
|
||||||
const daysToEnd: number = getRemainingdays(endingDate);
|
const daysToEnd: number = getRemainingdays(endingDate);
|
||||||
// let notes: string = "";
|
// let notes: string = "";
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
|
const Content: FC = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AvatarList users={users} />
|
||||||
|
|
||||||
|
<div className={classes.root}>
|
||||||
|
<Grid container>
|
||||||
|
<Grid item xs={9}>
|
||||||
|
<Typography variant="h5" component="h5">
|
||||||
|
<b>In project: </b>{" "}
|
||||||
|
<Link to={`/projects/${project.id}`}>{project.title}</Link>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs>
|
||||||
|
<Timer /> <span>Due in {daysToEnd} days</span>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={classes.root}>
|
||||||
|
<InfoTable
|
||||||
|
status={status}
|
||||||
|
category={category}
|
||||||
|
impact={impact}
|
||||||
|
difficulty={difficulty}
|
||||||
|
/>
|
||||||
|
{/* <textarea
|
||||||
|
id="notes"
|
||||||
|
className="materialize-textarea validate"
|
||||||
|
value={notes}
|
||||||
|
// onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
|
||||||
|
// setDescription(e.target.value)
|
||||||
|
// }
|
||||||
|
></textarea> */}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<Container maxWidth="md">
|
<PageLayout
|
||||||
<div className={classes.root}>
|
header={<Header title={title} description={description} />}
|
||||||
<Header title={title} description={description} />
|
content={<Content />}
|
||||||
</div>
|
/>
|
||||||
<AvatarList users={users} />
|
|
||||||
|
|
||||||
<div className={classes.root}>
|
|
||||||
<Grid container>
|
|
||||||
<Grid item xs={9}>
|
|
||||||
<Typography variant="h5" component="h5">
|
|
||||||
<b>In project: </b>{" "}
|
|
||||||
<Link to={`/projects/${project.id}`}>{project.title}</Link>
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs>
|
|
||||||
<Timer /> <span>Due in {daysToEnd} days</span>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={classes.root}>
|
|
||||||
<InfoTable
|
|
||||||
status={status}
|
|
||||||
category={category}
|
|
||||||
impact={impact}
|
|
||||||
difficulty={difficulty}
|
|
||||||
/>
|
|
||||||
{/* <textarea
|
|
||||||
id="notes"
|
|
||||||
className="materialize-textarea validate"
|
|
||||||
value={notes}
|
|
||||||
// onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
|
|
||||||
// setDescription(e.target.value)
|
|
||||||
// }
|
|
||||||
></textarea> */}
|
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { UserVM } from "../VM/UserVM";
|
||||||
import { UserHeader } from "../components/UserHeader";
|
import { UserHeader } from "../components/UserHeader";
|
||||||
import { UserTabPanel } from "../components/UserTabPanel";
|
import { UserTabPanel } from "../components/UserTabPanel";
|
||||||
import { Container } from "@material-ui/core";
|
import { Container } from "@material-ui/core";
|
||||||
|
import PageLayout from "../layouts/PageLayout";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
viewModel: UserVM;
|
viewModel: UserVM;
|
||||||
|
|
@ -13,13 +14,21 @@ export const UserPage: FC<IProps> = ({ viewModel }) => {
|
||||||
const tabNames: string[] = ["Projects", "Tickets"];
|
const tabNames: string[] = ["Projects", "Tickets"];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container maxWidth="md">
|
<PageLayout
|
||||||
<UserHeader
|
header={
|
||||||
picture={picture}
|
<UserHeader
|
||||||
fullName={fullName}
|
picture={picture}
|
||||||
presentation={presentation}
|
fullName={fullName}
|
||||||
/>
|
presentation={presentation}
|
||||||
<UserTabPanel tabNames={tabNames} projects={projects} tickets={tickets} />
|
/>
|
||||||
</Container>
|
}
|
||||||
|
content={
|
||||||
|
<UserTabPanel
|
||||||
|
tabNames={tabNames}
|
||||||
|
projects={projects}
|
||||||
|
tickets={tickets}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue