From 1e5bcff24073738fd7e46213c5b77341fc24536d Mon Sep 17 00:00:00 2001 From: Rauno Tegelmann Date: Fri, 23 Aug 2024 17:00:54 +0300 Subject: [PATCH] feat(dashboard): allow configuring all time start from settings (#234) --- .env.example | 1 - README.md | 1 - .../_actions/updateDashboardSettings.ts | 4 ++ .../_components/DashboardSettingsForm.tsx | 7 +++ src/types/dashboard.d.ts | 2 +- src/types/settings.d.ts | 1 + src/utils/constants.ts | 19 +------- src/utils/getPeriod.ts | 43 ++++++++++++++----- 8 files changed, 47 insertions(+), 31 deletions(-) diff --git a/.env.example b/.env.example index 26a9be6e..623b9309 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,3 @@ NEXTAUTH_SECRET= NEXTAUTH_URL=http://localhost:3000 NEXT_PUBLIC_SITE_URL=http://localhost:3000 -NEXT_PUBLIC_STATISTICS_START_DATE=2018-01-01 diff --git a/README.md b/README.md index 0a553a5f..51ae51c1 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,6 @@ services: - NEXTAUTH_SECRET= # (required) used to encrypt auth JWT token, generate one with `openssl rand -base64 32` - NEXTAUTH_URL=http://localhost:8383 # (required) change to your domain if you are exposing the app to the internet - NEXT_PUBLIC_SITE_URL=http://localhost:8383 # (required) change to your domain if you are exposing the app to the internet - - NEXT_PUBLIC_STATISTICS_START_DATE=2018-01-01 # (optional) starting date for "all time" option (YYYY-MM-DD) volumes: - ./config:/app/config ports: diff --git a/src/app/settings/dashboard/_actions/updateDashboardSettings.ts b/src/app/settings/dashboard/_actions/updateDashboardSettings.ts index ab0b15dc..bea4a70f 100644 --- a/src/app/settings/dashboard/_actions/updateDashboardSettings.ts +++ b/src/app/settings/dashboard/_actions/updateDashboardSettings.ts @@ -33,6 +33,9 @@ const schema = z.object({ ) .optional(), defaultStyle: z.string().optional(), + startDate: z.string().refine((val) => !isNaN(Date.parse(val)), { + message: 'Invalid start date', + }), complete: z.boolean(), }) @@ -57,6 +60,7 @@ export default async function saveDashboardSettings( data.defaultPeriod = formData.get('defaultPeriod') as string data.customPeriod = formData.get('customPeriod') as string data.defaultStyle = formData.get('defaultStyle') as string + data.startDate = formData.get('startDate') as string } return await updateSettings(schema, data, 'dashboard') diff --git a/src/app/settings/dashboard/_components/DashboardSettingsForm.tsx b/src/app/settings/dashboard/_components/DashboardSettingsForm.tsx index fbf15e96..c44a4488 100644 --- a/src/app/settings/dashboard/_components/DashboardSettingsForm.tsx +++ b/src/app/settings/dashboard/_components/DashboardSettingsForm.tsx @@ -1,5 +1,6 @@ 'use client' +import DatePicker from '@/components/DatePicker' import { Settings } from '@/types/settings' import { DEFAULT_SETTINGS } from '@/utils/constants' import { useState } from 'react' @@ -168,6 +169,12 @@ export default function DashboardSettingsForm({ settings }: Props) { /> Custom period + )} diff --git a/src/types/dashboard.d.ts b/src/types/dashboard.d.ts index dac13443..cf6a2b0e 100644 --- a/src/types/dashboard.d.ts +++ b/src/types/dashboard.d.ts @@ -1,4 +1,4 @@ export type DashboardSearchParams = { - period?: '7days' | '30days' | 'thisYear' | 'pastYear' | 'allTime' | 'custom' + period?: '7days' | '30days' | 'pastYear' | 'allTime' | 'custom' personal?: 'true' } diff --git a/src/types/settings.d.ts b/src/types/settings.d.ts index 8325e919..f083588b 100644 --- a/src/types/settings.d.ts +++ b/src/types/settings.d.ts @@ -52,6 +52,7 @@ export type DashboardSettings = { defaultStyle: string defaultPeriod: string customPeriod: string + startDate: string complete: boolean } diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 9dcc0598..1312d632 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -5,13 +5,9 @@ const DAYS_AGO_7: Date = new Date(new Date().setDate(new Date().getDate() - 7)) const DAYS_AGO_30: Date = new Date( new Date().setDate(new Date().getDate() - 30), ) -const CURRENT_YEAR: Date = new Date(new Date().getFullYear(), 0, 1) const PAST_YEAR: Date = new Date( new Date().setFullYear(new Date().getFullYear() - 1), ) -const ALL_TIME: Date = new Date( - env('NEXT_PUBLIC_STATISTICS_START_DATE') || '2018-01-01', -) export type Period = { date: string @@ -30,13 +26,6 @@ export const PERIODS: { [key: string]: Period } = { string: DAYS_AGO_30.toISOString().split('T')[0], daysAgo: 30, }, - thisYear: { - date: CURRENT_YEAR.toISOString(), - string: CURRENT_YEAR.toISOString().split('T')[0], - daysAgo: Math.ceil( - (new Date().getTime() - CURRENT_YEAR.getTime()) / (1000 * 3600 * 24), - ), - }, pastYear: { date: PAST_YEAR.toISOString(), string: PAST_YEAR.toISOString().split('T')[0], @@ -44,13 +33,6 @@ export const PERIODS: { [key: string]: Period } = { (new Date().getTime() - PAST_YEAR.getTime()) / (1000 * 3600 * 24), ), }, - allTime: { - date: ALL_TIME.toISOString(), - string: ALL_TIME.toISOString().split('T')[0], - daysAgo: Math.ceil( - (new Date().getTime() - ALL_TIME.getTime()) / (1000 * 3600 * 24), - ), - }, } export const META_DESCRIPTION: string = @@ -101,6 +83,7 @@ export const DEFAULT_SETTINGS: Settings = { defaultStyle: 'general', defaultPeriod: 'custom', customPeriod: '30', + startDate: '2010-01-01', complete: false, }, } diff --git a/src/utils/getPeriod.ts b/src/utils/getPeriod.ts index c4b8cf37..be8485ac 100644 --- a/src/utils/getPeriod.ts +++ b/src/utils/getPeriod.ts @@ -10,21 +10,44 @@ export default function getPeriod( const defaultPeriod = settings.dashboard.defaultPeriod const customPeriod = parseInt(settings.dashboard.customPeriod) - let period = PERIODS[defaultPeriod] || PERIODS['30days'] + function getCustomPeriod() { + const startDate = new Date(Date.now() - customPeriod * 24 * 60 * 60 * 1000) - if (periodSearchParams && PERIODS[periodSearchParams]) { - period = PERIODS[periodSearchParams] - } else if (defaultPeriod === 'custom' || periodSearchParams === 'custom') { - const DAYS_AGO_CUSTOM: Date = new Date( - new Date().setDate(new Date().getDate() - customPeriod), + return createPeriodObject(startDate, customPeriod) + } + + function getAllTimePeriod() { + const startDate = new Date(settings.dashboard.startDate) + const daysAgo = Math.ceil( + (Date.now() - startDate.getTime()) / (24 * 60 * 60 * 1000), ) - period = { - date: DAYS_AGO_CUSTOM.toISOString(), - string: DAYS_AGO_CUSTOM.toISOString().split('T')[0], - daysAgo: customPeriod, + return createPeriodObject(startDate, daysAgo) + } + + function createPeriodObject(date: Date, daysAgo: number) { + return { + date: date.toISOString(), + string: date.toISOString().split('T')[0], + daysAgo, } } + function getPeriodFromKey(key: string) { + switch (key) { + case 'custom': + return getCustomPeriod() + case 'allTime': + return getAllTimePeriod() + default: + return PERIODS[key] + } + } + + const period = + (periodSearchParams && getPeriodFromKey(periodSearchParams)) || + getPeriodFromKey(defaultPeriod) || + PERIODS[defaultPeriod] + return period }