diff --git a/src/popup/App.tsx b/src/popup/App.tsx index 2ae1a26..79339b5 100644 --- a/src/popup/App.tsx +++ b/src/popup/App.tsx @@ -63,7 +63,7 @@ export const PopupApp: React.FC = () => { activePage.tab === tab && 'bg-neutral-300 text-neutral-800 dark:bg-neutral-900 dark:text-neutral-200', activePage.tab !== tab && - 'hover:bg-neutral-100 text-neutral-400 dark:hover:bg-neutral-900 dark:text-neutral-400', + 'hover:bg-neutral-100 text-[#737373] dark:hover:bg-neutral-900 dark:text-neutral-400', tab === Pages.Preferences && 'max-w-[75px]', )} key={tab} @@ -83,9 +83,9 @@ export const PopupApp: React.FC = () => { return (
-
+
- Codealike + Codealike
{tabs} diff --git a/src/popup/components/ActivityDatePicker/index.tsx b/src/popup/components/ActivityDatePicker/index.tsx index 9b50ddc..8e82d92 100644 --- a/src/popup/components/ActivityDatePicker/index.tsx +++ b/src/popup/components/ActivityDatePicker/index.tsx @@ -38,6 +38,7 @@ export const ActivityDatePicker: React.FC = ({ @@ -50,6 +51,7 @@ export const ActivityDatePicker: React.FC = ({ diff --git a/src/popup/components/ActivityPageDailyActivityTab/ActivityPageDailyActivityTab.tsx b/src/popup/components/ActivityPageDailyActivityTab/ActivityPageDailyActivityTab.tsx index 2886de9..5f54150 100644 --- a/src/popup/components/ActivityPageDailyActivityTab/ActivityPageDailyActivityTab.tsx +++ b/src/popup/components/ActivityPageDailyActivityTab/ActivityPageDailyActivityTab.tsx @@ -67,6 +67,7 @@ export const DailyActivityTab: React.FC = ({ title="Activity Timeline" activityTimeline={activityTimeline} filteredHostname={filteredHostname} + description="Your web activity timeline." />
= + ({ store, sundayDate }) => { + const [pickedDomain, setPickedDomain] = React.useState(null); + const scrollToRef = React.useRef(null); + + const handleDomainRowClick = React.useCallback((domain: string) => { + setPickedDomain(domain); + scrollToRef.current?.scrollIntoView({ behavior: 'smooth' }); + }, []); + + const allMonthlyActivity = React.useMemo( + () => + get30DaysPriorDate(sundayDate).reduce((acc, date) => { + const isoDate = getIsoDate(date); + acc[isoDate] = store[isoDate] || {}; + + return acc; + }, {} as TimeStore), + [store, sundayDate] + ); + + const filteredWebsiteMonthActivity = React.useMemo(() => { + if (pickedDomain === null) { + return allMonthlyActivity; + } + + return Object.entries(allMonthlyActivity).reduce( + (acc, [date, dateWebsitesUsage]) => { + acc[date] = { + [pickedDomain]: dateWebsitesUsage[pickedDomain] || 0, + }; + + return acc; + }, + {} as typeof allMonthlyActivity + ); + }, [allMonthlyActivity, pickedDomain]); + + const totalWebsiteMonthlyActivity = React.useMemo( + () => + Object.values(allMonthlyActivity).reduce((acc, dailyUsage) => { + Object.entries(dailyUsage).forEach(([key, value]) => { + acc[key] ??= 0; + acc[key] += value; + }); + + return acc; + }, {} as Record), + [allMonthlyActivity] + ); + + const averageMonthlyActivity = React.useMemo(() => { + const averageMonthly = + getTotalMonthlyActivity(filteredWebsiteMonthActivity, sundayDate) / 7; + return averageMonthly; + }, [filteredWebsiteMonthActivity, sundayDate]); + + const presentedPickedDomain = pickedDomain ?? 'All Websites'; + + return ( +
+ +
+ + `Activity on ${presentedPickedDomain} per day` + } + /> +
+ +
+ ); + }; diff --git a/src/popup/components/ActivityPageMonthlyActivityTab/types.ts b/src/popup/components/ActivityPageMonthlyActivityTab/types.ts new file mode 100644 index 0000000..0fb681e --- /dev/null +++ b/src/popup/components/ActivityPageMonthlyActivityTab/types.ts @@ -0,0 +1,6 @@ +import { TimeStore } from '../../hooks/useTimeStore'; + +export interface ActivityPageMonthlyActivityTabProps { + store: TimeStore; + sundayDate: Date; +} diff --git a/src/popup/components/GeneralTimeline/GeneralTimeline.tsx b/src/popup/components/GeneralTimeline/GeneralTimeline.tsx index c4e0039..0863e71 100644 --- a/src/popup/components/GeneralTimeline/GeneralTimeline.tsx +++ b/src/popup/components/GeneralTimeline/GeneralTimeline.tsx @@ -13,6 +13,7 @@ const GeneralTimelineFC: React.FC = ({ activityTimeline, title, emptyHoursMarginCount = 2, + description, }) => { return ( @@ -20,6 +21,7 @@ const GeneralTimelineFC: React.FC = ({ {title} {filteredHostname ? ` On ${filteredHostname}` : ''} + ({description}) = ({ }) => { const calendarRef = React.useRef(null); + const theme = getAppTheme(); + + if (theme === 'light') { + INACTIVE_DAY_COLOR = '#F0F0F0'; + LOW_ACTIVITY_DAY_COLOR = '#FFE0B2'; + MEDIUM_ACTIVITY_DAY_COLOR = '#FFB74D'; + HIGH_ACTIVITY_DAY_COLOR = '#FFA744'; + + COLORS = [ + INACTIVE_DAY_COLOR, + LOW_ACTIVITY_DAY_COLOR, + MEDIUM_ACTIVITY_DAY_COLOR, + HIGH_ACTIVITY_DAY_COLOR, + ] + } + + if (theme === 'dark') { + INACTIVE_DAY_COLOR = '#2C2C2C'; + LOW_ACTIVITY_DAY_COLOR = '#5C3B1A'; + MEDIUM_ACTIVITY_DAY_COLOR = '#AB6C33'; + HIGH_ACTIVITY_DAY_COLOR = '#FFA744'; + + COLORS = [ + INACTIVE_DAY_COLOR, + LOW_ACTIVITY_DAY_COLOR, + MEDIUM_ACTIVITY_DAY_COLOR, + HIGH_ACTIVITY_DAY_COLOR, + ] + } + React.useEffect(() => { if (!calendarRef.current) { return; @@ -82,6 +113,14 @@ export const GithubCalendarWrapper: React.FC = ({
{/* @ts-expect-error -- expected, this element does have props */} +
+ Less +
+
+
+
+ More +
{ settings.ignoredHosts ); const [domainToIgnore, setDomainToIgnore] = React.useState(''); - const [isDomainsListExpanded, setDomainsListExpanded] = - React.useState(false); + const [state, setState] = React.useState<{ + status: boolean, + statusText: string, + }>({ + status: false, + statusText: '', + }); const handleAddIgnoredDomain = React.useCallback(() => { try { - assertDomainIsValid(domainToIgnore); - setIgnoredDomains((prev) => { - const newIgnoredHostList = Array.from( - new Set([...prev, domainToIgnore]) - ); - - updateSettings({ - ignoredHosts: newIgnoredHostList, + const ignoredHostsList = domainToIgnore.split(',') + for (const host of ignoredHostsList) { + assertDomainIsValid(host.trim()); + setIgnoredDomains((prev) => { + const newIgnoredHostList = Array.from( + new Set([...prev, host.trim()]) + ); + + updateSettings({ + ignoredHosts: newIgnoredHostList, + }); + + return newIgnoredHostList; }); + } - return newIgnoredHostList; - }); - + setState((prev) => ({ + ...prev, + status: false, + statusText: '' + })); setDomainToIgnore(''); - } catch (_) { - // + } catch (error) { + const errorMessage = (error as Error)?.message; + + setState((prev) => ({ + ...prev, + status: true, + statusText: errorMessage + })); } }, [domainToIgnore, updateSettings]); @@ -54,16 +72,20 @@ export const IgnoredDomainSetting: React.FC = () => { ); const handleDomainToIgnoreChange = React.useCallback( - (e: React.ChangeEvent) => { + (e: React.ChangeEvent) => { setDomainToIgnore(e.target.value); }, [] ); - const handleToggleDomainsListExpanded = React.useCallback(() => { - setDomainsListExpanded((prev) => !prev); - }, [setDomainsListExpanded]); + const handleKeyDown = ((event: React.KeyboardEvent) => { + if(event.key === 'Enter') { + event.preventDefault(); + handleAddIgnoredDomain() + } + }) + const { status, statusText } = state; return (
@@ -71,10 +93,11 @@ export const IgnoredDomainSetting: React.FC = () => {
+
+ {status + && (

{statusText}

) + } +
- - View all blacklisted domains - -
+
{!ignoredDomains.length && (

No blacklisted domains

)} @@ -101,7 +122,7 @@ export const IgnoredDomainSetting: React.FC = () => {
handleRemoveIgnoredDomain(domain)} /> {domain} diff --git a/src/popup/components/LimitsSetting/LimitsSetting.tsx b/src/popup/components/LimitsSetting/LimitsSetting.tsx index b3ba1cb..4f87c73 100644 --- a/src/popup/components/LimitsSetting/LimitsSetting.tsx +++ b/src/popup/components/LimitsSetting/LimitsSetting.tsx @@ -114,7 +114,7 @@ export const LimitsSetting: React.FC = () => { > handleLimitRemove(domain)} /> {domain} diff --git a/src/popup/components/MonthDatePicker/MonthDatePicker.tsx b/src/popup/components/MonthDatePicker/MonthDatePicker.tsx new file mode 100644 index 0000000..dd35810 --- /dev/null +++ b/src/popup/components/MonthDatePicker/MonthDatePicker.tsx @@ -0,0 +1,49 @@ +import * as React from 'react'; + +import { Button, ButtonType } from '../../../blocks/Button'; +import { Icon, IconType } from '../../../blocks/Icon'; +import { getIsoDate } from '../../../shared/utils/dates-helper'; + +import { MonthDatePickerProps } from './types'; + +export const MonthDatePicker: React.FC = ({ + onMonthChange, + sundayDate, +}) => { + const monthStartDate = new Date(); + monthStartDate.setDate(sundayDate.getDate() - 30); + + const handleChangeWeekButtonClick = React.useCallback( + (direction) => { + const newWeekEndDate = new Date(sundayDate); + newWeekEndDate.setDate(sundayDate.getDate() + direction * 30); + + onMonthChange(newWeekEndDate); + }, + [sundayDate, onMonthChange] + ); + + return ( +
+ +
+ {getIsoDate(monthStartDate)} +
+ {getIsoDate(sundayDate)} +
+ +
+ ); +}; diff --git a/src/popup/components/MonthDatePicker/types.ts b/src/popup/components/MonthDatePicker/types.ts new file mode 100644 index 0000000..f095de5 --- /dev/null +++ b/src/popup/components/MonthDatePicker/types.ts @@ -0,0 +1,4 @@ +export interface MonthDatePickerProps { + sundayDate: Date; + onMonthChange: (weekEndDate: Date) => void; +} diff --git a/src/popup/components/MonthlyWebsiteActivityChart/MonthlyWebsiteActivityChart.tsx b/src/popup/components/MonthlyWebsiteActivityChart/MonthlyWebsiteActivityChart.tsx new file mode 100644 index 0000000..3d83da5 --- /dev/null +++ b/src/popup/components/MonthlyWebsiteActivityChart/MonthlyWebsiteActivityChart.tsx @@ -0,0 +1,129 @@ +import { Icon, IconType } from '../../../blocks/Icon'; +import { Panel, PanelHeader } from '../../../blocks/Panel'; +import { + get30DaysPriorDate, + getHoursInMs, + getIsoDate, + getTimeFromMs, + getTimeWithoutSeconds, +} from '../../../shared/utils/dates-helper'; +import { useIsDarkMode } from '../../hooks/useTheme'; +import { getTotalDailyActivity } from '../../selectors/get-total-daily-activity'; +import { MonthlyWebsiteActivityChartProps } from './types'; +import * as React from 'react'; +import { Bar } from 'react-chartjs-2'; + +const HOUR_IN_MS = getHoursInMs(1); + +const BAR_OPTIONS = { + plugins: { + legend: { + display: false, + }, + tooltip: { + callbacks: { + label: (item: any) => { + return ( + ' ' + getTimeFromMs(Number(item.formattedValue || 0) * HOUR_IN_MS) + ); + }, + title: ([item]: any) => { + return `${item?.label}`; + }, + }, + }, + }, + responsive: true, + scales: { + x: { + ticks: { + color: '#222', + }, + }, + y: { + ticks: { + callback: (value: number) => { + return getTimeWithoutSeconds(value * HOUR_IN_MS); + }, + color: '#222', + }, + }, + }, +}; + +const DARK_MODE_BAR_OPTIONS = { + ...BAR_OPTIONS, + scales: { + ...BAR_OPTIONS.scales, + x: { + ...BAR_OPTIONS.scales.x, + grid: { + color: '#444444', + }, + ticks: { + ...BAR_OPTIONS.scales.x.ticks, + color: '#e5e5e5', + }, + }, + y: { + ...BAR_OPTIONS.scales.y, + grid: { + color: '#444444', + }, + ticks: { + ...BAR_OPTIONS.scales.y.ticks, + color: '#e5e5e5', + }, + }, + }, +}; + +export const MonthlyWebsiteActivityChart: React.FC< + MonthlyWebsiteActivityChartProps +> = ({ store, sundayDate, presentChartTitle }) => { + const isDarkMode = useIsDarkMode(); + + const [labels, data] = React.useMemo(() => { + const month = get30DaysPriorDate(sundayDate).reverse(); + const labels = month.map((date) => getIsoDate(date)); + const data = month.map( + (date) => getTotalDailyActivity(store, date) / HOUR_IN_MS, + ); + + return [labels, data]; + }, [store, sundayDate]); + + const monthName = React.useMemo( + () => `${labels[0]} - ${labels[labels.length - 1]}`, + [labels], + ); + + const chartData = React.useMemo( + () => ({ + datasets: [ + { + backgroundColor: '#4b76e3', + borderRadius: 12, + borderSkipped: false, + data: data, + label: 'Monthly activity', + }, + ], + labels: labels, + }), + [labels, data], + ); + + return ( + + + + {presentChartTitle?.(monthName) ?? monthName} + + + + ); +}; diff --git a/src/popup/components/MonthlyWebsiteActivityChart/types.ts b/src/popup/components/MonthlyWebsiteActivityChart/types.ts new file mode 100644 index 0000000..9d430a9 --- /dev/null +++ b/src/popup/components/MonthlyWebsiteActivityChart/types.ts @@ -0,0 +1,7 @@ +import { TimeStore } from '../../hooks/useTimeStore'; + +export interface MonthlyWebsiteActivityChartProps { + store: TimeStore; + sundayDate: Date; + presentChartTitle?: (weekName: string) => string; +} diff --git a/src/popup/components/OverallActivityCalendar/OverallActivtyCalendar.tsx b/src/popup/components/OverallActivityCalendar/OverallActivtyCalendar.tsx index 0a58f79..03a07c8 100644 --- a/src/popup/components/OverallActivityCalendar/OverallActivtyCalendar.tsx +++ b/src/popup/components/OverallActivityCalendar/OverallActivtyCalendar.tsx @@ -34,7 +34,7 @@ export const OverallActivityCalendarPanel: React.FC - Overall Activity + Overall Activity (Your overall activity timeline.) { const [theme, setTheme] = React.useState(getAppTheme()); @@ -28,38 +28,36 @@ export const ThemeSelector: React.FC = () => { handleThemeChange('auto'); }, [handleThemeChange]); + console.log(theme) return ( -
-

Theme

-
- - - -
-
+ + Change Theme + +

You can change your extension theme from here.

+
+ + + +
+
+
); }; diff --git a/src/popup/components/WebsiteActivityTable/WebsiteActivityTable.tsx b/src/popup/components/WebsiteActivityTable/WebsiteActivityTable.tsx index c277721..79a473c 100644 --- a/src/popup/components/WebsiteActivityTable/WebsiteActivityTable.tsx +++ b/src/popup/components/WebsiteActivityTable/WebsiteActivityTable.tsx @@ -60,7 +60,7 @@ const WebsiteActivityTableFC: React.FC = ({ Click on the website name to view stats for this website.

- Click on the icon to + Click on the icon to hide and ignore this website.

You can always add it in the Ignored domains section.

@@ -73,7 +73,7 @@ const WebsiteActivityTableFC: React.FC = ({ > handleHideDomainClick(domain)} /> = ({ @@ -39,6 +40,7 @@ export const WeekDatePicker: React.FC = ({ diff --git a/src/popup/components/WhitelistDomainsSetting/WhitelistDomainSetting.tsx b/src/popup/components/WhitelistDomainsSetting/WhitelistDomainSetting.tsx index 4892106..38b8387 100644 --- a/src/popup/components/WhitelistDomainsSetting/WhitelistDomainSetting.tsx +++ b/src/popup/components/WhitelistDomainsSetting/WhitelistDomainSetting.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; -import { twMerge } from 'tailwind-merge'; +// import { twMerge } from 'tailwind-merge'; import { Button, ButtonType } from '../../../blocks/Button'; import { Icon, IconType } from '../../../blocks/Icon'; -import { Input } from '../../../blocks/Input'; +import { TextArea } from '../../../blocks/Input'; import { PanelBody } from '../../../blocks/Panel'; import { assertDomainIsValid } from '../../../shared/utils/domains'; import { usePopupContext } from '../../hooks/PopupContext'; @@ -14,27 +14,46 @@ export const WhitelistDomainSetting: React.FC = () => { settings.allowedHosts ?? [] ); const [ newAllowedHost, setNewAllowedHost] = React.useState(''); - const [isAllowedHostsListExpanded, setAllowedHostListExpanded] = - React.useState(false); + const [state, setState] = React.useState<{ + status: boolean, + statusText: string, + }>({ + status: false, + statusText: '', + }); const handleAddWhitelistDomain = React.useCallback(() => { try { - assertDomainIsValid(newAllowedHost); - setAllowedHosts((prev) => { - const newAllowedHostList = Array.from( - new Set([...prev, newAllowedHost]) - ); - - updateSettings({ - allowedHosts: newAllowedHostList, + const allowedHostsList = newAllowedHost.split(',') + for (const host of allowedHostsList) { + assertDomainIsValid(host.trim()); + setAllowedHosts((prev) => { + const newAllowedHostList = Array.from( + new Set([...prev, host.trim()]) + ); + + updateSettings({ + allowedHosts: newAllowedHostList, + }); + + return newAllowedHostList; }); - - return newAllowedHostList; - }); + } setNewAllowedHost(''); - } catch (_) { - // + setState((prev) => ({ + ...prev, + status: false, + statusText: '' + })); + } catch (error) { + const errorMessage = (error as Error)?.message; + + setState((prev) => ({ + ...prev, + status: true, + statusText: errorMessage + })); } }, [newAllowedHost, updateSettings]); @@ -54,16 +73,20 @@ export const WhitelistDomainSetting: React.FC = () => { ); const handleAddtoAllowedHostChange = React.useCallback( - (e: React.ChangeEvent) => { + (e: React.ChangeEvent) => { setNewAllowedHost(e.target.value); }, [] ); - const handleAllowHostsListExpanded = React.useCallback(() => { - setAllowedHostListExpanded((prev) => !prev); - }, [setAllowedHostListExpanded]); + const handleKeyDown = (event: React.KeyboardEvent) => { + if(event.key === 'Enter') { + event.preventDefault(); + handleAddWhitelistDomain() + } + } + const { status, statusText } = state; return (
@@ -71,10 +94,11 @@ export const WhitelistDomainSetting: React.FC = () => {
+
+ {status + && (

{statusText}

) + } +
- - View all whitelisted domains - -
+
{!allowedHosts.length && (

No whitelisted domains

)} @@ -101,7 +123,7 @@ export const WhitelistDomainSetting: React.FC = () => {
handleRemoveAllowedHost(domain)} /> {domain} diff --git a/src/popup/pages/ActivityPage.tsx b/src/popup/pages/ActivityPage.tsx index 0df9882..fbd2bec 100644 --- a/src/popup/pages/ActivityPage.tsx +++ b/src/popup/pages/ActivityPage.tsx @@ -12,6 +12,8 @@ import { DailyActivityTab } from '../components/ActivityPageDailyActivityTab/Act import { ActivityPageWeeklyActivityTab } from '../components/ActivityPageWeeklyActivityTab/ActivityPageWeeklyActivityTab'; import { WeekDatePicker } from '../components/WeekDatePicker/WeekDatePicker'; import { usePopupContext } from '../hooks/PopupContext'; +import { MonthDatePicker } from '../components/MonthDatePicker/MonthDatePicker'; +import { ActivityPageMonthlyActivityTab } from '../components/ActivityPageMonthlyActivityTab/ActivityPageMonthlyActivityTab'; interface ActivityPageProps { date?: string; @@ -20,6 +22,7 @@ interface ActivityPageProps { enum ActivityPageTabs { Daily, Weekly, + Monthly } export const ActivityPage: React.FC = ({ @@ -46,6 +49,7 @@ export const ActivityPage: React.FC = ({ buttonType={ activeTab === value ? ButtonType.Primary : ButtonType.Secondary } + className='px-2' onClick={() => setActiveTab(value)} key={key} > @@ -71,6 +75,12 @@ export const ActivityPage: React.FC = ({ onWeekChange={setPickedSunday} /> )} + {activeTab === ActivityPageTabs.Monthly && ( + + )} {activeTab === ActivityPageTabs.Daily && ( @@ -83,6 +93,12 @@ export const ActivityPage: React.FC = ({ sundayDate={pickedSunday} /> )} + {activeTab === ActivityPageTabs.Monthly && ( + + )} ); }; diff --git a/src/popup/pages/OverallPage.tsx b/src/popup/pages/OverallPage.tsx index 77bfb7f..1614aea 100644 --- a/src/popup/pages/OverallPage.tsx +++ b/src/popup/pages/OverallPage.tsx @@ -54,6 +54,7 @@ export const OverallPage: React.FC = ({ activityTimeline={timelineEvents} filteredHostname={null} emptyHoursMarginCount={0} + description="Your web activity in last 6 hours." />
); diff --git a/src/popup/pages/PreferencesPage.tsx b/src/popup/pages/PreferencesPage.tsx index 4633116..2cd4974 100644 --- a/src/popup/pages/PreferencesPage.tsx +++ b/src/popup/pages/PreferencesPage.tsx @@ -8,6 +8,7 @@ import { Input } from './../../blocks/Input'; import {IgnoredDomainSetting} from '../components/IgnoredDomainsSetting/IgnoredDomainSetting'; import { WhitelistDomainSetting } from '../components/WhitelistDomainsSetting/WhitelistDomainSetting'; import {UserTokenSetting} from "../components/UserTokenSetting/UserTokenSetting"; +import { ThemeSelector } from '../components/ThemeSelector'; export const PreferencesPage: FC = () => { const [isWhitelistShown, hideWhitelist] = React.useState(true); @@ -45,6 +46,7 @@ export const PreferencesPage: FC = () => { {(isWhitelistShown ? : )} +
); }; diff --git a/src/popup/selectors/get-total-monthly-activity.ts b/src/popup/selectors/get-total-monthly-activity.ts new file mode 100644 index 0000000..62508a5 --- /dev/null +++ b/src/popup/selectors/get-total-monthly-activity.ts @@ -0,0 +1,10 @@ +import { get30DaysPriorDate } from '../../shared/utils/dates-helper'; + +import { TimeStore } from '../hooks/useTimeStore'; + +import { getTotalDailyActivity } from './get-total-daily-activity'; + +export const getTotalMonthlyActivity = (store: TimeStore, date = new Date()) => + get30DaysPriorDate(date).reduce((sum, date) => { + return sum + getTotalDailyActivity(store, date); + }, 0); diff --git a/src/shared/utils/dates-helper.ts b/src/shared/utils/dates-helper.ts index 72759ad..ada73fb 100644 --- a/src/shared/utils/dates-helper.ts +++ b/src/shared/utils/dates-helper.ts @@ -61,6 +61,22 @@ export const get7DaysPriorDate = < }); }; +export const get30DaysPriorDate = < + T extends (date: Date) => any = (date: Date) => Date +>( + date: Date, + map?: T +): ReturnType[] => { + const defaultMap = (date: Date) => new Date(date); + const monthEndDate = new Date(date); + + return new Array(30).fill(0).map((_, index) => { + monthEndDate.setDate(monthEndDate.getDate() - Number(index > 0)); + + return map?.(monthEndDate) ?? defaultMap(monthEndDate); + }); +}; + export const getDatesWeekSundayDate = (date: Date = new Date()) => { date.setDate(date.getDate() + date.getDay());