Added UserTabRouter, UserHeader,ProjectList,Avatar components. UserPage Layout done. UserVM updated. Added User/:id route to Router

This commit is contained in:
Ruidy Nemausat 2020-03-01 14:05:16 +01:00
parent 86fd097481
commit 9e89955b1c
15 changed files with 266 additions and 28 deletions

View file

@ -6,7 +6,7 @@ import { User } from "../types/User";
import { getRemainingdays } from "../utils/methods";
export default class ProjectVM {
public id: number;
// public id: number;
public title: string;
public description: string;
public creationDate: string;
@ -24,7 +24,7 @@ export default class ProjectVM {
public remainingDays: number;
public constructor(project: Project, allUsers: User[]) {
this.id = project.id;
// this.id = project.id;
this.title = project.title;
this.description = project.description;
this.creationDate = project.creationDate;

View file

@ -1,5 +1,19 @@
export class UserVM {
public Id?: number;
import { Project } from "../types/Project";
import { Ticket } from "../types/Ticket";
import { User } from "../types/User";
public constructor() {}
export class UserVM {
public fullName: string;
public presentation: string;
public picture: string;
public projects: Project[];
public tickets: Ticket[];
public constructor(user: User) {
this.fullName = user.fullName;
this.presentation = user.presentation;
this.picture = user.picture;
this.projects = user.projects;
this.tickets = user.tickets;
}
}

View file

@ -1,6 +1,5 @@
import React, { FC } from "react";
import { Activity } from "../types/Activity";
import { act } from "react-dom/test-utils";
type IProps = {
activities: Activity[];

View file

@ -0,0 +1,12 @@
import React, { FC } from "react";
interface IProps {
picture: string;
}
export const Avatar: FC<IProps> = ({ picture }) => {
return (
<>
<img className="circle" src={picture} height="100vh" width="100vh" />
</>
);
};

View file

@ -0,0 +1,85 @@
import React, { FC, useState, ChangeEvent, MouseEvent } from "react";
import { Ticket } from "../types/Ticket";
import { FloatingButton } from "./FloatingButton";
import { HorizontalCard } from "./HorizontalCard";
import { FilterBar } from "./FilterBar";
import { put } from "../utils/http";
import { HttpResponse } from "../types/HttpResponse";
import { Constants } from "../utils/Constants";
import { NewTicketModal } from "./NewTicketModal";
import { Project } from "../types/Project";
type IProps = {
projects: Project[];
};
export const ProjectList: FC<IProps> = ({ projects }) => {
const [filterText, setFilterText] = useState<string>("");
const clearFilterText: (e: MouseEvent) => void = (e: MouseEvent) => {
setFilterText("");
};
// const archiveTicket = () => {};
const onClick: (e: MouseEvent) => void = (e: MouseEvent) => {
e.preventDefault();
setShowNew(true);
};
const handleChange: (e: ChangeEvent<HTMLInputElement>) => void = (
e: ChangeEvent<HTMLInputElement>
) => {
setFilterText(e.target.value);
};
const [showNew, setShowNew] = useState(false);
let filteredTickets = projects.filter(
t =>
t.status !== "Done" &&
t.title.toLowerCase().includes(filterText.toLowerCase())
);
return (
<>
<div className="row valign-wrapper">
<NewTicketModal
handleClose={() => {
setShowNew(false);
}}
show={showNew}
/>
<h3>Projects</h3>
<FloatingButton
color="indigo lighten-1"
size="small"
onClick={onClick}
/>
<FilterBar
filterText={filterText}
handleChange={handleChange}
clearFilterText={clearFilterText}
/>
</div>
<div className="col s12 grey">
<ul>
{filteredTickets.length === 0 ? (
<HorizontalCard />
) : (
filteredTickets.map((t: Ticket) => (
<HorizontalCard
key={t.id}
title={t.title}
remainingDays={t.endingDate}
validateTicket={async (e: MouseEvent) => {
e.preventDefault();
await put<HttpResponse<Ticket>>(
`${Constants.ticketsURI}/${t.id}/closed`,
{}
);
}}
// archiveTicket={archiveTicket}
/>
))
)}
</ul>
</div>
</>
);
};

View file

@ -65,7 +65,7 @@ export const TicketList: FC<TicketListProps> = ({ tickets }) => {
<HorizontalCard
key={t.id}
title={t.title}
remainingDays={t.plannedEnding}
remainingDays={t.endingDate}
validateTicket={async (e: MouseEvent) => {
e.preventDefault();
await put<HttpResponse<Ticket>>(

View file

@ -0,0 +1,21 @@
import React, { FC } from "react";
import { Header } from "../components/Header";
import { Avatar } from "../components/Avatar";
interface IProps {
fullName: string;
presentation: string;
picture: string;
}
export const UserHeader: FC<IProps> = ({ fullName, presentation, picture }) => {
return (
<div className="row valign-wrapper">
<div className="col s2">
<Avatar picture={picture} />
</div>
<div className="col s10">
<Header title={fullName} description={presentation} />
</div>
</div>
);
};

View file

@ -0,0 +1,38 @@
import React, { FC } from "react";
import { TabRouterHeader } from "./TabRouterHeader";
import { TicketList } from "./TicketList";
import { Ticket } from "../types/Ticket";
import { Route, useRouteMatch, Redirect } from "react-router-dom";
import { Project } from "../types/Project";
import { ProjectList } from "./ProjectList";
interface IProps {
tabNames: string[];
tickets: Ticket[];
projects: Project[];
}
export const UserTabRouter: FC<IProps> = ({ tickets, tabNames, projects }) => {
const { url } = useRouteMatch();
return (
<>
<div className="row">
<TabRouterHeader tabNames={tabNames} />
<Redirect from={url} to={`${url}/projects`} />
<Route path={`${url}/projects`}>
<ProjectList projects={projects} />
</Route>
<Route path={`${url}/tickets`}>
<TicketList tickets={tickets} />
</Route>
</div>
</>
);
};

View file

@ -3,12 +3,10 @@ import { Modal } from "./Modal";
import { AvatarList } from "./AvatarList";
import { User } from "../types/User";
import { FilterBar } from "./FilterBar";
import { HttpResponse } from "../types/HttpResponse";
import { get, put, patch } from "../utils/http";
import { patch } from "../utils/http";
import { Constants } from "../utils/Constants";
import { UsersModalEntry } from "./UsersModalEntry";
import { useParams } from "react-router-dom";
import _ from "underscore";
interface IProps {
show: boolean;

View file

@ -1,6 +1,5 @@
import React, { FC } from "react";
import { User } from "../types/User";
import _ from "underscore";
interface IProps {
setMembers: React.Dispatch<React.SetStateAction<User[]>>;

View file

@ -1,6 +1,62 @@
import React, { FC } from "react";
import React, { FC, useState, useEffect } from "react";
import { UserPage } from "../pages/UserPage";
import { UserVM } from "../VM/UserVM";
import { User } from "../types/User";
import { AppFile } from "../types/AppFile";
import { Activity } from "../types/Activity";
import { Ticket } from "../types/Ticket";
import { Preloader } from "../components/Preloader";
export const UserController: FC = () => {
return <UserPage />;
const [isLoading, setIsLoading] = useState(true);
const user: User = {
id: "resldsm,dgd",
firstName: "David",
lastName: "Whittaker",
fullName: "David Whittaker",
presentation: "Interface designer and front-end developer",
creationDate: new Date().toDateString(),
email: "dw@mail.au",
phone: "0998765432",
picture: require("../images/user_1.jpg"),
projects: [
{
id: 1,
title: "Project Title",
description: "What is it about",
progression: 25,
creationDate: new Date().toDateString(),
endingDate: "2020-02-17 15:51:02.787373",
status: "Todo",
manager: {} as User,
users: [] as User[],
tickets: [] as Ticket[],
files: [] as AppFile[],
activities: [] as Activity[]
}
],
tickets: [
{
id: 1,
title: "Client objective meeting",
description: "Client objective meeting",
endingDate: "2020-02-17 15:51:02.787373",
status: "Done"
},
{
id: 2,
title: "Assemble Outcomes Report for client",
description: "Assemble Outcomes Report for client",
endingDate: "2020-02-27 15:51:02.787373",
status: "To Do"
}
],
activities: []
};
useEffect(() => {
setTimeout(() => setIsLoading(false), 1000);
});
const viewModel = new UserVM(user);
return isLoading ? <Preloader /> : <UserPage viewModel={viewModel} />;
};

View file

@ -1,12 +1,32 @@
import React, { FC } from "react";
import { Header } from "../components/Header";
import { UserVM } from "../VM/UserVM";
import { UserHeader } from "../components/UserHeader";
import { UserTabRouter } from "../components/UserTabRouter";
export const UserPage: FC = () => {
interface IProps {
viewModel: UserVM;
}
export const UserPage: FC<IProps> = ({ viewModel }) => {
const { fullName, presentation, picture, projects, tickets } = viewModel;
const tabNames: string[] = ["Projects", "Tickets"];
return (
<Header title = "Brand Concept and Design" description = "Research, ideate and present brand concepts for client consideration"/>
// <TabView>
<div className="section">
<div className="container">
<UserHeader
picture={picture}
fullName={fullName}
presentation={presentation}
/>
<UserTabRouter
tabNames={tabNames}
projects={projects}
tickets={tickets}
/>
</div>
{/* // <TabView>
// <CardList>
// <CardList>
// </TabView>
// </TabView> */}
</div>
);
};

View file

@ -3,5 +3,5 @@ export interface Ticket {
title: string;
description: string;
status: string;
plannedEnding: string;
endingDate: string;
}

View file

@ -10,7 +10,7 @@ export interface User {
presentation: string;
email: string;
phone: string;
createdAt: string;
creationDate: string;
picture: string;
activities: Activity[];
projects: Project[];

View file

@ -12,7 +12,7 @@ import * as creacteHistory from "history";
import { ProjectController } from "../controllers/ProjectController";
import { NotFoundPage } from "../pages/NotFoundPage";
import { TestPage } from "../pages/TestPage";
// import { UserController } from "../controllers/UserController";
import { UserController } from "../controllers/UserController";
// import { TicketController } from "../controllers/TicketController";
export const history = creacteHistory.createBrowserHistory();
@ -28,24 +28,20 @@ export const AppRouter = () => {
{/* <Route path="/">
<HomeController />
</Route>
</Route> */}
<Route path="/users/:id">
<UserController />
</Route> */}
</Route>
<Route path="/projects/:id">
<ProjectController />
</Route>
{/* <Route path="/tickets/:id">
<TicketController />
</Route> */}
</Route> */}
<Route path="/404">
<NotFoundPage />
</Route>
{/* <Route path="*">
<Redirect to="/error" />
</Route> */}
</Switch>
</div>
</Router>