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
Show all changes
45 commits
Select commit Hold shift + click to select a range
6ee0d94
added width and height properties in tailwind config
onkar-saeloun Jun 28, 2022
257b12e
added reports routes
onkar-saeloun Jun 28, 2022
47ca435
added route conf
onkar-saeloun Jun 28, 2022
8852195
added reports header
onkar-saeloun Jun 28, 2022
8ea07b8
added outstanding amt page
onkar-saeloun Jun 28, 2022
8baba00
added report card component
onkar-saeloun Jun 28, 2022
acfc59f
added report card
onkar-saeloun Jun 28, 2022
0799ffe
added revenue by client page
onkar-saeloun Jun 28, 2022
138c340
added time entry page
onkar-saeloun Jun 28, 2022
720b20e
added total hours logged page
onkar-saeloun Jun 28, 2022
2a1cec0
added routes path for reports
onkar-saeloun Jun 28, 2022
8b780a0
added svgs for report list page
onkar-saeloun Jun 28, 2022
e0ab0aa
added route in navbar
onkar-saeloun Jun 28, 2022
7be19b1
resolved conflicts
onkar-saeloun Jun 28, 2022
70d9c51
Merge branch 'develop' of github.com:saeloun/miru-web into feature/re…
onkar-saeloun Jun 28, 2022
e5589b8
added flag to show the report in list
onkar-saeloun Jun 28, 2022
d093c3a
resolved comment
onkar-saeloun Jun 28, 2022
955d79c
resolved conflict
onkar-saeloun Jun 28, 2022
19013f7
Merge branch 'develop' of github.com:saeloun/miru-web into feature/re…
onkar-saeloun Jun 29, 2022
522e22d
added total header page
onkar-saeloun Jul 1, 2022
3892dde
changed time enty import
onkar-saeloun Jul 1, 2022
cda097f
changed entry context
onkar-saeloun Jul 1, 2022
3f5eeda
added z index
onkar-saeloun Jul 1, 2022
1fbb9b2
added revenue by client context
onkar-saeloun Jul 1, 2022
5de5d14
added time entry context
onkar-saeloun Jul 1, 2022
c909122
added time entry context import
onkar-saeloun Jul 1, 2022
9b1b357
added time entry context
onkar-saeloun Jul 1, 2022
9d286ce
added navigation changes
onkar-saeloun Jul 1, 2022
d93b647
added revenue by client page
onkar-saeloun Jul 1, 2022
1a4d2fa
added header
onkar-saeloun Jul 1, 2022
3407d15
added table
onkar-saeloun Jul 1, 2022
4ee7829
added filter
onkar-saeloun Jul 1, 2022
b98a3ad
added styles
onkar-saeloun Jul 1, 2022
7200e61
added time entry context
onkar-saeloun Jul 1, 2022
5f942e1
added changes in date util
onkar-saeloun Jul 1, 2022
ff52f85
added css
onkar-saeloun Jul 1, 2022
b4d8893
added filter
onkar-saeloun Jul 1, 2022
a3bb8c6
added custom date rage
onkar-saeloun Jul 1, 2022
4d15cd4
Merge branch 'develop' of github.com:saeloun/miru-web into feature/re…
onkar-saeloun Jul 1, 2022
4ebefec
added filter counter
onkar-saeloun Jul 1, 2022
18acb0a
added filte rrelated changes
onkar-saeloun Jul 1, 2022
f0776c8
added interface
onkar-saeloun Jul 1, 2022
7cd0431
added css changes
onkar-saeloun Jul 1, 2022
46fcb40
added css changes
onkar-saeloun Jul 1, 2022
b8d9970
resolved comments
onkar-saeloun Jul 5, 2022
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
127 changes: 127 additions & 0 deletions app/javascript/src/common/CustomDateRangePicker/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/* eslint-disable import/order */
import React, { useEffect, useRef } from "react";
import DatePicker from "react-datepicker";
import { getMonth, getYear } from "date-fns";
import dayjs from "dayjs";
import "react-datepicker/dist/react-datepicker.css";
import { CaretCircleLeft, CaretCircleRight, CaretLeft } from "phosphor-react"; //eslint-disable-line

const CustomDateRangePicker = ({
hideCustomFilter,
handleSelectDate,
onClickInput,
selectedInput,
dateRange
}) => {
const fromInput = "from-input";
const toInput = "to-input";

const range = (start, end) => Array.from({ length: (end - start) }, (v, k) => k + start);

const years = range(1990, getYear(new Date()) + 1);
const months = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
];

const textInput = useRef(null);
useEffect(() => {
textInput.current.focus();
}, []);

return (
<DatePicker
wrapperClassName="datePicker absolute"
inline
calendarClassName="miru-calendar-date-range"
minDate={(selectedInput === toInput && dateRange.from) ? new Date(dateRange.from) : null}
maxDate={(selectedInput === fromInput && dateRange.to) ? new Date(dateRange.to) : null}
renderCustomHeader={({
date,
changeYear,
changeMonth,
decreaseMonth,
increaseMonth,
prevMonthButtonDisabled,
nextMonthButtonDisabled
}) => (
<div className="bg-miru-white-1000 ">
<div className="flex justify-start mt-2">
<button onClick={hideCustomFilter}>
<CaretLeft color="#5b34ea" size={10} />
</button>
<p className="text-sm font-medium ml-2"> Custom Date Range </p>
</div>
<div className="flex flex-row mt-4">
<input
type={"text"}
placeholder={" From "}
value={dateRange.from ? dayjs(dateRange.from).format("DD MMM YYYY") : null}
ref={textInput}
className={`bg-miru-gray-100 h-8 w-32 mr-1 rounded p-1 ${selectedInput === fromInput && "border-2 border-miru-han-purple-1000"}`}
onClick={onClickInput}
id={fromInput}
name={fromInput}
/>
<input
type={"text"}
placeholder={" To "}
value={dateRange.to ? dayjs(dateRange.to).format("DD MMM YYYY") : null}
className={`bg-miru-gray-100 h-8 w-32 ml-1 rounded p-1 ${selectedInput === toInput && "border-2 border-miru-han-purple-1000"}`}
onClick={onClickInput}
id={toInput}
name={toInput}
/>
</div>
<div
className="headerWrapper mt-4"
>
<button onClick={decreaseMonth} disabled={prevMonthButtonDisabled}>
<CaretCircleLeft color="#5b34ea" size={16} />
</button>
<div>
<select
value={months[getMonth(date)]}
onChange={({ target: { value } }) =>
changeMonth(months.indexOf(value))
}
>
{months.map((option) => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
<select
value={getYear(date)}
onChange={({ target: { value } }) => changeYear(value)}
>
{years.map((option) => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
</div>
<button onClick={increaseMonth} disabled={nextMonthButtonDisabled}>
<CaretCircleRight color="#5b34ea" size={16} />
</button>
</div>
</div>
)}
onChange={handleSelectDate}
/>
);
};

export default CustomDateRangePicker;
42 changes: 42 additions & 0 deletions app/javascript/src/common/TotalHeader/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from "react";

const TotalHeader = ({
firstTitle,
firstAmount,
secondTitle,
secondAmount,
thirdTitle,
thirdAmount

}) => (
<div className="px-10 py-10 mt-6 bg-miru-gray-100">
<ul className="mt-0 border-t-0 page-display__wrap">
<li className="page-display__box">
<p className="text-sm font-normal tracking-widest uppercase">
{firstTitle}
</p>
<p className="mt-3 text-5xl font-normal tracking-widest">
{firstAmount}
</p>
</li>
<li className="page-display__box">
<p className="text-sm font-normal tracking-widest uppercase">
{secondTitle}
</p>
<p className="mt-3 text-5xl font-normal tracking-widest">
{secondAmount}
</p>
</li>
<li className="page-display__box">
<p className="text-sm font-normal tracking-widest uppercase">
{thirdTitle}
</p>
<p className="mt-3 text-5xl font-normal tracking-widest">
{thirdAmount}
</p>
</li>
</ul>
</div>
);

export default TotalHeader;
4 changes: 2 additions & 2 deletions app/javascript/src/components/Reports/Container/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const TableHeader = () => (
);

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

const getEntryList = (entries) =>
entries.map((timeEntry, index) => (
Expand All @@ -50,7 +50,7 @@ const Container = () => {
return (
<Fragment>
{
reports.map((report, index) => (
timeEntryReport.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">
Expand Down
8 changes: 4 additions & 4 deletions app/javascript/src/components/Reports/Filters/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ const FilterSideBar = ({
handleApplyFilter
}) => {

const { filterOptions, selectedFilter } = useEntry();
const [filters, setFilters] = useState(selectedFilter);
const { timeEntryReport } = useEntry();
const [filters, setFilters] = useState(timeEntryReport.selectedFilter);

const handleSelectFilter = (selectedValue, field) => {
if (Array.isArray(selectedValue)) {
Expand Down Expand Up @@ -75,11 +75,11 @@ const FilterSideBar = ({
</li>
<li className="px-5 pb-5">
<h5 className="text-xs font-normal">Clients</h5>
<Select isMulti={true} value={filters.clients} classNamePrefix="react-select-filter" name="clients" onChange={handleSelectFilter} styles={customStyles} options={filterOptions.clients} />
<Select isMulti={true} value={filters.clients} classNamePrefix="react-select-filter" name="clients" onChange={handleSelectFilter} styles={customStyles} options={timeEntryReport.filterOptions.clients} />
</li>
<li className="px-5 pb-5">
<h5 className="text-xs font-normal">Team Members</h5>
<Select isMulti={true} value={filters.teamMember} classNamePrefix="react-select-filter" name="teamMember" onChange={handleSelectFilter} styles={customStyles} options={filterOptions.teamMembers} />
<Select isMulti={true} value={filters.teamMember} classNamePrefix="react-select-filter" name="teamMember" onChange={handleSelectFilter} styles={customStyles} options={timeEntryReport.filterOptions.teamMembers} />
</li>
<li className="px-5 pb-5">
<h5 className="text-xs font-normal">Status</h5>
Expand Down
20 changes: 16 additions & 4 deletions app/javascript/src/components/Reports/Header/NavigationFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,32 @@ import { X } from "phosphor-react";
import { useEntry } from "../context/EntryContext";

const NavigationFilter = () => {
const { selectedFilter, handleRemoveSingleFilter } = useEntry();
const { revenueByClientReport, currentReport, timeEntryReport } = useEntry();
const getReport = (currentReport) => {
switch (currentReport) {
case "RevenueByClientReport":
return revenueByClientReport;
case "TimeEntryReport":
return timeEntryReport;
default:
break;
}
};

const selectedReport = getReport(currentReport);

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>{filterKey === "groupBy" && "Group By:"} {value}</span>
<button onClick={() => handleRemoveSingleFilter(filterKey, value)} className="inline-block ml-1">
<button onClick={() => selectedReport.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) {
const filterValue = selectedFilter[filterKey];
for (const filterKey in selectedReport.selectedFilter) {
const filterValue = selectedReport.selectedFilter[filterKey];
if (Array.isArray(filterValue)) {
filterOptions = [...filterOptions, filterValue.map((item, index) => filterHtml(item.label, `${item}-${index}`, filterKey))];
}
Expand Down
19 changes: 16 additions & 3 deletions app/javascript/src/components/Reports/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,20 @@ const Header = ({
handleDownload,
type
}) => {
const { filterCounter } = useEntry();
const { timeEntryReport, revenueByClientReport, currentReport } = useEntry();
const getReport = (currentReport) => {
switch (currentReport) {
case "RevenueByClientReport":
return revenueByClientReport;
case "TimeEntryReport":
return timeEntryReport;
default:
break;
}
};
Comment on lines +28 to +37
Copy link
Contributor

Choose a reason for hiding this comment

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

DRY the function. we are defining the same function in
app/javascript/src/components/Reports/Header/NavigationFilter.tsx:7 aswell

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@harshaanNihal This refactoring is already done in API integration branch will raise separate PR for this.


const selectedReport = getReport(currentReport);

const [showExportOptions, setShowExportOptions] = useState<boolean>(false);

return (
Expand All @@ -42,7 +55,7 @@ const Header = ({
</h2>
<button className="ml-7 p-3 rounded hover:bg-miru-gray-1000 relative" onClick={() => { setFilterVisibilty(!isFilterVisible); }}>
<Funnel size={16} color="#7C5DEE" />
{filterCounter > 0 && <sup className="filter__counter">{filterCounter}</sup>}
{selectedReport.filterCounter > 0 && <sup className="filter__counter">{selectedReport.filterCounter}</sup>}
</button>
</div>
<div className="inline-flex">
Expand Down Expand Up @@ -106,7 +119,7 @@ const Header = ({
<ul className="flex">
<NavigationFilter />
{
filterCounter > 0 && <li key={"clear_all"} className="flex px-2 mr-4 py-1 px-1 ">
selectedReport.filterCounter > 0 && <li key={"clear_all"} className="flex px-2 mr-4 py-1 px-1 ">
<button onClick={resetFilter} className="inline-block ml-1 flex items-center">
<X size={12} color="#5B34EA" className="inline-block" weight="bold" />
<span className="text-miru-han-purple-1000 ml-1 text-xs tracking-widest font-bold">CLEAR ALL</span>
Expand Down
19 changes: 5 additions & 14 deletions app/javascript/src/components/Reports/context/EntryContext.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
import { createContext, useContext } from "react";
import RevenueByClientReportContext from "./RevenueByClientContext";
import TimeEntryReportContext from "./TimeEntryReportContext";

const EntryContext = createContext(({
reports: [],
selectedFilter: {
dateRange: { label: "All", value: "" },
clients: [],
teamMember: [],
status: [],
groupBy: { label: "None", value: "" }
},
filterOptions: {
clients: [],
teamMembers: []
},
filterCounter: 0,
handleRemoveSingleFilter: (key, value) => { }, //eslint-disable-line
currentReport: "",
revenueByClientReport: RevenueByClientReportContext,
timeEntryReport: TimeEntryReportContext
}));

export const useEntry = () => useContext(EntryContext);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const RevenueByClientReportContext = {
filterOptions: {
clients: []
},
selectedFilter: {
dateRange: { label: "All", value: "" },
clients: []
},
customDateFilter: {
from: "",
to: ""
},
filterCounter: 0,
handleRemoveSingleFilter: (key, value) => { }, //eslint-disable-line
};

export default RevenueByClientReportContext;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const TimeEntryReportContext = {
reports: [],
selectedFilter: {
dateRange: { label: "All", value: "" },
clients: [],
teamMember: [],
status: [],
groupBy: { label: "None", value: "" }
},
filterOptions: {
clients: [],
teamMembers: []
},
filterCounter: 0,
handleRemoveSingleFilter: (key, value) => { }, //eslint-disable-line
};

export default TimeEntryReportContext;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from "react";

import { RevenueByClients } from "../interface";

const TableRow = ({
id,
name,
unpaidAmt,
paidAmt,
total
}: RevenueByClients) => (

<tr key={id} className="flex flex-row items-center">
<td className="w-3/5 pr-6 py-4 text-left whitespace-nowrap">
<p className="font-normal whitespace-normal text-base text-miru-dark-purple-1000">
{name}
</p>
</td>
<td className="w-2/5 px-6 py-4 text-left text-base font-normal text-miru-dark-purple-1000 whitespace-pre-wrap">
{unpaidAmt}
</td>
<td className="w-1/5 px-6 py-4 text-left whitespace-nowrap">
<p className="font-normal text-base text-miru-dark-purple-1000">
{paidAmt}
</p>
</td>
<td className="w-1/5 pl-6 py-4 text-xl text-right whitespace-nowrap font-bold text-miru-dark-purple-1000">
{total}
</td>
</tr>
);

export default TableRow;
Loading