Skip to content

Commit

Permalink
Reports filter addition (#364)
Browse files Browse the repository at this point in the history
* report page updated

* lint fixes

* aligment fixed

* spec fixes
  • Loading branch information
Ajinkya Deshmukh authored May 9, 2022
1 parent fcbddef commit 677f462
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 87 deletions.
8 changes: 4 additions & 4 deletions app/javascript/src/apis/axios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ const handleErrorResponse = error => {
}
Toastr.error(
error.response?.data?.error ||
error.response?.data?.notice ||
error.message ||
error.notice ||
"Something went wrong!"
error.response?.data?.notice ||
error.message ||
error.notice ||
"Something went wrong!"
);
if (error.response?.status === 423) {
window.location.href = "/";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
import React from "react";
import { minutesToHHMM } from "../../helpers/hhmm-parser";
import { minutesToHHMM } from "../../../helpers/hhmm-parser";
import { ITimeEntry } from "../interface";

export interface ITimeEntry {
id: number;
project: string;
client: string;
note: string;
teamMember: string;
workDate: string;
duration: number;
}

export const TimeEntry = ({
const TableRow = ({
id,
project,
client,
Expand All @@ -20,28 +11,31 @@ export const TimeEntry = ({
workDate,
duration
}: ITimeEntry) => (

<tr key={id} className="flex flex-row items-center">
<td className="w-full px-6 py-4 text-left whitespace-nowrap">
<td className="w-2/5 px-6 py-4 text-left whitespace-nowrap">
<p className="font-semibold text-base text-miru-dark-purple-1000">
{project}
</p>
<p className="font-normal text-sm text-miru-dark-purple-400">
{client}
</p>
</td>
<td className="w-full px-6 py-4 text-left text-xs font-normal text-miru-dark-purple-1000 whitespace-pre-wrap">
<td className="w-3/5 px-6 py-4 text-left text-xs font-normal text-miru-dark-purple-1000 whitespace-pre-wrap">
{note}
</td>
<td className="w-full px-6 py-4 text-left whitespace-nowrap">
<td className="w-1/5 px-6 py-4 text-left whitespace-nowrap">
<p className="font-semibold text-base text-miru-dark-purple-1000">
{teamMember}
</p>
<p className="font-normal text-sm text-miru-dark-purple-400">
{workDate}
</p>
</td>
<td className="w-full px-6 py-4 text-xl text-left whitespace-nowrap font-bold text-miru-dark-purple-1000">
<td className=" px-6 py-4 text-xl text-left whitespace-nowrap font-bold text-miru-dark-purple-1000">
{minutesToHHMM(duration)}
</td>
</tr>
);

export default TableRow;
59 changes: 59 additions & 0 deletions app/javascript/src/components/Reports/Container/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from "react";
import TableRow from "./TableRow";
import { useEntry } from "../context/EntryContext";

const Container = () => {
const { entries } = useEntry();

const getEntryList = () => {
if (entries.length > 0) {
return entries.map((timeEntry, index) => (
<TableRow key={index} {...timeEntry} />
));
}
};

return (
<table className="min-w-full divide-y divide-gray-200 mt-4">
<thead>
<tr className="flex flex-row items-center">
<th
scope="col"
className="w-2/5 px-6 py-5 text-left text-xs font-normal text-miru-dark-purple-600 tracking-widest"
>
PROJECT/
<br />
CLIENT
</th>
<th
scope="col"
className="w-3/5 px-6 py-5 text-left text-xs font-normal text-miru-dark-purple-600 tracking-widest"
>
NOTE
</th>
<th
scope="col"
className="w-1/5 px-6 py-5 text-left text-xs font-normal text-miru-dark-purple-600 tracking-widest"
>
TEAM MEMBER/
<br />
DATE
</th>
<th
scope="col"
className="px-6 py-5 text-left text-xs font-normal text-miru-dark-purple-600 tracking-widest"
>
HOURS
<br />
LOGGED
</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{getEntryList()}
</tbody>
</table>
);
};

export default Container;
106 changes: 106 additions & 0 deletions app/javascript/src/components/Reports/Filters/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React from "react";
import Select from "react-select";
import { X } from "phosphor-react";

import getStatusCssClass from "../../../utils/getStatusTag";

const FilterSideBar = ({ setFilterVisibilty }) => {

const dateRangeOptions = [
{ value: "", label: "All" },
{ value: "cwa", label: "This month (1st Dec - 31st Dec)" },
{ value: "alexa", label: "Last Month (1st Nov - 30th Nov)" },
{ value: "abc", label: "This Week (27th Dec - 2nd Jan)" },
{ value: "dwss", label: "Last Week (20th Dec - 26th Dec)" }
];
const projectOption = [
{ value: "onedrive", label: "One Drive" },
{ value: "cwa", label: "Outlook" },
{ value: "alexa", label: "Alexa" },
{ value: "abc", label: "One Drive" },
{ value: "dwss", label: "Outlook" },
{ value: "rrr", label: "Alexa" },
{ value: "xyz", label: "One Drive" },
{ value: "outlook", label: "Outlook" },
{ value: "pppp", label: "Alexa" }
];

const statusOption = [
{ value: "overdue", label: "OVERDUE" },
{ value: "sent", label: "SENT" },
{ value: "paid", label: "PAID" }
];

const customStyles = {
control: (provided) => ({
...provided,
marginTop: "8px",
backgroundColor: "#F5F7F9",
color: "#1D1A31",
minHeight: 32,
padding: "0"
}),
menu: (provided) => ({
...provided,
fontSize: "12px",
letterSpacing: "2px"
})
};

const CustomOption = (props) => {
const { innerProps, innerRef } = props;

return (
<div ref={innerRef} {...innerProps} className="py-1 px-2 cursor-pointer hover:bg-miru-gray-100">
<span className={`${getStatusCssClass(props.data.label)} text-xs tracking-widest`} >
{props.data.label}
</span>
</div>
);
};

return (
<div className="sidebar__container flex flex-col">
<div>
<div className="flex px-5 pt-5 mb-7 justify-between items-center">
<h4 className="text-base font-bold">
Filters
</h4>
<button onClick={() => setFilterVisibilty(false)}>
<X size={12} />
</button>
</div>
<div className="sidebar__filters">
<ul>
<li className="px-5 pb-5">
<h5 className="text-xs font-normal">Date Range</h5>
<Select isMulti={true} classNamePrefix="react-select-filter" styles={customStyles} options={dateRangeOptions} />
</li>
<li className="px-5 pb-5">
<h5 className="text-xs font-normal">Clients</h5>
<Select isMulti={true} classNamePrefix="react-select-filter" styles={customStyles} />
</li>
<li className="px-5 pb-5">
<h5 className="text-xs font-normal">Team Members</h5>
<Select isMulti={true} classNamePrefix="react-select-filter" styles={customStyles} options={projectOption} />
</li>
<li className="px-5 pb-5">
<h5 className="text-xs font-normal">Status</h5>
<Select isMulti={true} classNamePrefix="react-select-filter" styles={customStyles} options={statusOption} components={{ Option: CustomOption }} />
</li>
<li className="px-5 pb-5">
<h5 className="text-xs font-normal">Group By</h5>
<Select isMulti={true} classNamePrefix="react-select-filter" styles={customStyles} options={statusOption} components={{ Option: CustomOption }} />
</li>
</ul>
</div>
</div>
<div className="sidebar__footer">
<button className="sidebar__reset">RESET</button>
<button className="sidebar__apply">APPLY</button>
</div>
</div>
);
};

export default FilterSideBar;
21 changes: 21 additions & 0 deletions app/javascript/src/components/Reports/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";
import {
Funnel
} from "phosphor-react";

const Header = ({ setFilterVisibilty, isFilterVisible }) => (
<div className="sm:flex sm:items-center sm:justify-between mt-6 mb-3">
<div className="flex items-center">
<h2 className="text-3xl font-extrabold text-gray-900 sm:text-4xl sm:truncate py-1">
Time entry report
</h2>
<button className="ml-7 p-3 rounded hover:bg-miru-gray-1000 relative" onClick={() => { setFilterVisibilty(!isFilterVisible); }}>
<Funnel size={16} color="#7C5DEE" />
{/* Need to work on below code when integrating the api values */}
{/* <sup className="filter__counter">3</sup> */}
</button>
</div>
</div>
);

export default Header;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createContext, useContext } from "react";

const EntryContext = createContext(({
entries: []
}));

export const useEntry = () => useContext(EntryContext);

export default EntryContext;
69 changes: 16 additions & 53 deletions app/javascript/src/components/Reports/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import React, { useState, useEffect } from "react";

import { setAuthHeaders, registerIntercepts } from "apis/axios";
import reports from "apis/reports";
import { TimeEntry, ITimeEntry } from "./TimeEntry";
import Container from "./Container";
import EntryContext from "./context/EntryContext";

import Filters from "./Filters";
import Header from "./Header";

import { ITimeEntry } from "./interface";

const Reports = () => {
const [timeEntries, setTimeEntries] = useState<Array<ITimeEntry>>([]);

const [isFilterVisible, setFilterVisibilty] = useState<boolean>(false);
const fetchTimeEntries = async () => {
const res = await reports.get();
if (res.status == 200) {
Expand All @@ -20,57 +27,13 @@ const Reports = () => {
}, []);

return (
<>
<div className="flex flex-col">
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
<div className="overflow-hidden border-miru-gray-200">
<table className="min-w-full divide-y divide-gray-200 mt-4">
<thead>
<tr className="flex flex-row items-center">
<th
scope="col"
className="w-full px-6 py-5 text-left text-xs font-normal text-miru-dark-purple-600 tracking-widest"
>
PROJECT/
<br />
CLIENT
</th>
<th
scope="col"
className="w-full px-6 py-5 text-left text-xs font-normal text-miru-dark-purple-600 tracking-widest"
>
NOTE
</th>
<th
scope="col"
className="w-full px-6 py-5 text-left text-xs font-normal text-miru-dark-purple-600 tracking-widest"
>
TEAM MEMBER/
<br />
DATE
</th>
<th
scope="col"
className="w-full px-6 py-5 text-left text-xs font-normal text-miru-dark-purple-600 tracking-widest"
>
HOURS
<br />
LOGGED
</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{timeEntries.map((timeEntry, index) => (
<TimeEntry key={index} {...timeEntry} />
))}
</tbody>
</table>
</div>
</div>
</div>
</div>
</>
<div>
<EntryContext.Provider value={{ entries: timeEntries }}>
<Header setFilterVisibilty={setFilterVisibilty} isFilterVisible={isFilterVisible} />
<Container />
{isFilterVisible && <Filters setFilterVisibilty={setFilterVisibilty} />}
</EntryContext.Provider>
</div>
);
};

Expand Down
9 changes: 9 additions & 0 deletions app/javascript/src/components/Reports/interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export interface ITimeEntry {
id: number;
project: string;
client: string;
note: string;
teamMember: string;
workDate: string;
duration: number;
}
8 changes: 8 additions & 0 deletions app/javascript/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,14 @@
}


.filter {
&__counter {
@apply absolute right-0 block rounded-lg text-white bg-miru-han-purple-600;
top: 4px;
padding: 7px 5px;
}
}

body {
font-family: "Manrope", "sans-serif";
}
Expand Down
Loading

0 comments on commit 677f462

Please sign in to comment.