Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions app/javascript/src/components/Reports/Container/TableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ const TableRow = ({
}: ITimeEntry) => (

<tr key={id} className="flex flex-row items-center">
<td className="w-1/5 px-6 py-4 text-left whitespace-nowrap">
<p className="font-semibold text-base text-miru-dark-purple-1000">
<td className="w-2/5 pr-6 py-4 text-left whitespace-nowrap">
<p className="font-semibold whitespace-normal 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-3/5 px-6 py-4 text-left text-xs font-normal text-miru-dark-purple-1000 whitespace-pre-wrap">
<td className="w-2/5 px-6 py-4 text-left text-xs font-normal text-miru-dark-purple-1000 whitespace-pre-wrap">
{note}
</td>
<td className="w-1/5 px-6 py-4 text-left whitespace-nowrap">
Expand All @@ -32,7 +32,7 @@ const TableRow = ({
{workDate}
</p>
</td>
<td className="w-1/5 px-6 py-4 text-xl text-right whitespace-nowrap font-bold text-miru-dark-purple-1000">
<td className="w-1/5 pl-6 py-4 text-xl text-right whitespace-nowrap font-bold text-miru-dark-purple-1000">
{minutesToHHMM(duration)}
</td>
</tr>
Expand Down
106 changes: 58 additions & 48 deletions app/javascript/src/components/Reports/Container/index.tsx
Original file line number Diff line number Diff line change
@@ -1,58 +1,68 @@
import React from "react";
import React, { Fragment } from "react";
import TableRow from "./TableRow";
import { useEntry } from "../context/EntryContext";

const TableHeader = () => (
<thead>
<tr className="flex flex-row items-center">
<th
scope="col"
className="w-2/5 pr-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-2/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="w-1/5 pl-6 py-5 text-right text-xs font-normal text-miru-dark-purple-600 tracking-widest"
>
HOURS
<br />
LOGGED
</th>
</tr>
</thead>
);

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

const getEntryList = () => {
if (entries.length > 0) {
return entries.map((timeEntry, index) => (
<TableRow key={index} {...timeEntry} />
));
}
};
const getEntryList = (entries) =>
entries.map((timeEntry, index) => (
<TableRow key={`${timeEntry.client}-${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-1/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="w-1/5 px-6 py-5 text-right text-xs font-normal text-miru-dark-purple-600 tracking-widest"
>
HOURS
<br />
LOGGED
</th>
</tr>
</thead>
<tbody className="">
{getEntryList()}
</tbody>
</table>
<Fragment>
{
reports.map((report, index) => (
<Fragment key={index}>
{report.label !== "" && <h1 className="text-miru-han-purple-1000 font-bold text-xl py-5 border-b border-miru-han-purple-1000">{report.label}</h1>}
<table className="min-w-full divide-y divide-gray-200 mt-4">
<TableHeader />
<tbody className="bg-white divide-y divide-gray-200">
{report.entries.length > 0 && getEntryList(report.entries)}
</tbody>
</table>
</Fragment>
))
}
</Fragment>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ const getDateRangeOptions = () => {
};

const dateRangeOptions = [
{ value: "", label: "All" },
...getDateRangeOptions()
];

Expand All @@ -58,11 +57,12 @@ const groupBy = [
{ value: "team_member", label: "Team member" },
{ value: "client", label: "Client" },
{ value: "project", label: "Project" },
{ value: "Week", label: "Week" }
{ value: "week", label: "Week" }
];

export {
dateRangeOptions,
statusOption,
groupBy
groupBy,
getMonth
};
7 changes: 4 additions & 3 deletions app/javascript/src/components/Reports/Filters/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import Select from "react-select";
import { X } from "phosphor-react";
import {
dateRangeOptions,
statusOption
statusOption,
groupBy
} from "./filterOptions";
import { customStyles } from "./style";
import getStatusCssClass from "../../../utils/getStatusTag";
Expand Down Expand Up @@ -84,7 +85,7 @@ const FilterSideBar = ({
<h5 className="text-xs font-normal">Status</h5>
<Select isMulti={true} value={filters.status} classNamePrefix="react-select-filter" name="status" onChange={handleSelectFilter} styles={customStyles} options={statusOption} components={{ Option: CustomOption }} />
</li>
{/* <li className="px-5 pb-5">
<li className="px-5 pb-5">
<h5 className="text-xs font-normal">Group By</h5>
<Select
classNamePrefix="react-select-filter"
Expand All @@ -94,7 +95,7 @@ const FilterSideBar = ({
onChange={handleSelectFilter}
options={groupBy}
/>
</li> */}
</li>
</ul>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ const NavigationFilter = () => {

const filterHtml = (value, key, filterKey) => (
<li key={key} className="flex px-2 mr-4 py-1 rounded-xl tracking-widest font-semibold px-1 text-xs tracking-widest bg-miru-gray-400 text-miru-dark-purple-1000">
<span>{value}</span>
<span>{filterKey === "groupBy" && "Group By:"} {value}</span>
<button onClick={() => handleRemoveSingleFilter(filterKey, value)} className="inline-block ml-1">
<X size={11} color="#1D1A31" className="inline-block" weight="bold" />
</button>
</li>
);

const getFilterValues = () => {
let filterOptions = [];
for (const filterKey in selectedFilter) {
Expand Down
9 changes: 6 additions & 3 deletions app/javascript/src/components/Reports/api/applyFilter.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import reports from "apis/reports";
import { unmapper } from "../../../mapper/report.mapper";

const isValuePresent = (filterValue) => filterValue.value && filterValue.value !== "";
const isNotEmptyArray = (value) => value && value.length > 0;

const apiKeys = {
clients: "client",
dateRange: "date_range",
groupBy: "groupBy",
groupBy: "group_by",
status: "status",
teamMember: "team_member"
};
Expand All @@ -27,12 +28,14 @@ const getQueryParams = (selectedFilter) => {
return params;
};

const applyFilter = async (selectedFilter, setTimeEntries, setNavFilters, setFilterVisibilty) => {
const applyFilter = async (selectedFilter, setTimeEntries, setNavFilters, setFilterVisibilty, getFilterOptions) => {
const queryParams = getQueryParams(selectedFilter);
const sanitizedParam = queryParams.substring(1);
const sanitizedQuery = `?${sanitizedParam}`;
const res = await reports.get(sanitizedQuery);
setTimeEntries(res.data.entries);
const sanitizedData = unmapper(res.data);
setTimeEntries(sanitizedData.reports);
getFilterOptions(sanitizedData.filterOptions);
setNavFilters(true);
setFilterVisibilty(false);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createContext, useContext } from "react";

const EntryContext = createContext(({
entries: [],
reports: [],
selectedFilter: {
dateRange: { label: "All", value: "" },
clients: [],
Expand Down
18 changes: 4 additions & 14 deletions app/javascript/src/components/Reports/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import React, { useState, useEffect } from "react";

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

import Filters from "./Filters";
import { getMonth } from "./Filters/filterOptions";
import Header from "./Header";

import { ITimeEntry } from "./interface";

const Reports = () => {
const filterIntialValues = {
dateRange: { label: "All", value: "" },
dateRange: { label: getMonth(true), value: "this_week" },
clients: [],
teamMember: [],
status: [],
Expand All @@ -30,18 +30,9 @@ const Reports = () => {
const [showNavFilters, setNavFilters] = useState<boolean>(false);
const [filterCounter, setFilterCounter] = useState(0);

const fetchTimeEntries = async () => {
const res = await reports.get("");
if (res.status == 200) {
setTimeEntries(res.data.entries);
getFilterOptions(res.data.filterOptions);
}
};

useEffect(() => {
setAuthHeaders();
registerIntercepts();
fetchTimeEntries();
}, []);

const updateFilterCounter = async () => {
Expand All @@ -61,11 +52,11 @@ const Reports = () => {

useEffect(() => {
updateFilterCounter();
applyFilter(selectedFilter, setTimeEntries, setNavFilters, setFilterVisibilty);
applyFilter(selectedFilter, setTimeEntries, setNavFilters, setFilterVisibilty, getFilterOptions);
}, [selectedFilter]);

const contextValues = {
entries: timeEntries,
reports: timeEntries,
filterOptions,
selectedFilter,
filterCounter
Expand All @@ -77,7 +68,6 @@ const Reports = () => {

const resetFilter = () => {
setSelectedFilter(filterIntialValues);
fetchTimeEntries();
setFilterVisibilty(false);
setNavFilters(false);
};
Expand Down
14 changes: 14 additions & 0 deletions app/javascript/src/mapper/report.mapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const unmapper = (input) => {
const {
reports,
filterOptions
} = input;
return {
reports,
filterOptions
};
};

export {
unmapper
};