fixed compare
This commit is contained in:
@@ -11,12 +11,14 @@ import {
|
|||||||
|
|
||||||
import LatestItemsList, { LatestItem } from "./components/LatestItemsList";
|
import LatestItemsList, { LatestItem } from "./components/LatestItemsList";
|
||||||
import HistoryChart from "./components/HistoryChart";
|
import HistoryChart from "./components/HistoryChart";
|
||||||
|
import {
|
||||||
|
AggregatedDashboardData,
|
||||||
|
} from "./components/HistoryChart";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
fetchLatestTransactions,
|
fetchLatestTransactions,
|
||||||
fetchAggregatedExpenses,
|
fetchAggregatedExpenses,
|
||||||
fetchAggregatedIncome,
|
fetchAggregatedIncome,
|
||||||
AggregatedDashboardData
|
|
||||||
} from "./utils/dashboardLoader";
|
} from "./utils/dashboardLoader";
|
||||||
|
|
||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
|
|||||||
@@ -31,6 +31,13 @@ export interface HistoryChartProps {
|
|||||||
setComparison: (mode: boolean) => void;
|
setComparison: (mode: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AggregatedDashboardData {
|
||||||
|
chartData: ChartData;
|
||||||
|
totalAmount: number;
|
||||||
|
topPayees: Array<{ payeeName: string; amount: number }>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export default function HistoryChart({
|
export default function HistoryChart({
|
||||||
header,
|
header,
|
||||||
summary,
|
summary,
|
||||||
|
|||||||
@@ -4,38 +4,18 @@ import { ChartDataPoint } from "../components/HistoryChart";
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import MonetizationOnIcon from "@mui/icons-material/MonetizationOn";
|
import MonetizationOnIcon from "@mui/icons-material/MonetizationOn";
|
||||||
|
|
||||||
// ---------------- ICON ----------------
|
import {
|
||||||
|
buildDailyBuckets,
|
||||||
|
buildWeeklyRolling,
|
||||||
|
buildWeeklyCalendar,
|
||||||
|
buildMonthlyRolling,
|
||||||
|
buildMonthlyCalendar
|
||||||
|
} from "./periodBuilders";
|
||||||
|
|
||||||
const DEFAULT_ICON = React.createElement(MonetizationOnIcon, {
|
const DEFAULT_ICON = React.createElement(MonetizationOnIcon, {
|
||||||
sx: { color: "#388e3c" }
|
sx: { color: "#388e3c" }
|
||||||
});
|
});
|
||||||
|
|
||||||
// ---------------- HELPERS ----------------
|
|
||||||
const format = (d: Date) =>
|
|
||||||
`${d.getDate()} ${d.toLocaleString("default", { month: "short" })}`;
|
|
||||||
|
|
||||||
const startOfDay = (d: Date) => {
|
|
||||||
const x = new Date(d);
|
|
||||||
x.setHours(0, 0, 0, 0);
|
|
||||||
return x;
|
|
||||||
};
|
|
||||||
|
|
||||||
const endOfDay = (d: Date) => {
|
|
||||||
const x = new Date(d);
|
|
||||||
x.setHours(23, 59, 59, 999);
|
|
||||||
return x;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getStartOfWeek = (d: Date) => {
|
|
||||||
const date = new Date(d);
|
|
||||||
const day = date.getDay() || 7;
|
|
||||||
if (day !== 1) date.setDate(date.getDate() - (day - 1));
|
|
||||||
return startOfDay(date);
|
|
||||||
};
|
|
||||||
|
|
||||||
const shiftDate = (d: Date, days: number) =>
|
|
||||||
new Date(d.getTime() + days * 86400000);
|
|
||||||
|
|
||||||
// ---------------- LATEST ----------------
|
|
||||||
export async function fetchLatestTransactions(
|
export async function fetchLatestTransactions(
|
||||||
type: "expense" | "income"
|
type: "expense" | "income"
|
||||||
): Promise<LatestItem[]> {
|
): Promise<LatestItem[]> {
|
||||||
@@ -66,35 +46,17 @@ export async function fetchLatestTransactions(
|
|||||||
iconBgColor:
|
iconBgColor:
|
||||||
type === "expense" ? "#ffebee" : "#e8f5e9",
|
type === "expense" ? "#ffebee" : "#e8f5e9",
|
||||||
title: exp.payee?.name || exp.payee || "Unknown Payee",
|
title: exp.payee?.name || exp.payee || "Unknown Payee",
|
||||||
subtitle: exp.category?.name || exp.account?.name || "Transaction",
|
subtitle:
|
||||||
|
exp.category?.name || exp.account?.name || "Transaction",
|
||||||
amount: `Rs ${Math.abs(exp.amount || 0)}`,
|
amount: `Rs ${Math.abs(exp.amount || 0)}`,
|
||||||
timeAgo: diffDays === 0 ? "Today" : `${diffDays} days ago`
|
timeAgo: diffDays === 0 ? "Today" : `${diffDays} days ago`
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------- TYPES ----------------
|
|
||||||
export interface ChartSeries {
|
|
||||||
rolling: ChartDataPoint[];
|
|
||||||
calendar: ChartDataPoint[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ChartData {
|
|
||||||
daily: ChartDataPoint[];
|
|
||||||
weekly: ChartSeries;
|
|
||||||
monthly: ChartSeries;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AggregatedDashboardData {
|
|
||||||
chartData: ChartData;
|
|
||||||
totalAmount: number;
|
|
||||||
topPayees: Array<{ payeeName: string; amount: number }>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------- AGGREGATION ----------------
|
|
||||||
export async function fetchAggregatedData(
|
export async function fetchAggregatedData(
|
||||||
type: "expense" | "income"
|
type: "expense" | "income"
|
||||||
): Promise<AggregatedDashboardData> {
|
) {
|
||||||
const res = await api.get("/expenses", { params: { limit: 0 } });
|
const res = await api.get("/expenses", { params: { limit: 0 } });
|
||||||
const all: any[] = res.data?.items || res.data || [];
|
const all: any[] = res.data?.items || res.data || [];
|
||||||
|
|
||||||
@@ -108,126 +70,19 @@ export async function fetchAggregatedData(
|
|||||||
|
|
||||||
const normalize = (amt: number) => Math.abs(amt);
|
const normalize = (amt: number) => Math.abs(amt);
|
||||||
|
|
||||||
// ---------------- DAILY ----------------
|
const {
|
||||||
const dailyBuckets: Record<string, any> = {
|
buckets: dailyBuckets,
|
||||||
Mon: { amount: 0, compare: 0 },
|
weekStart,
|
||||||
Tue: { amount: 0, compare: 0 },
|
weekEnd,
|
||||||
Wed: { amount: 0, compare: 0 },
|
prevWeekStart,
|
||||||
Thu: { amount: 0, compare: 0 },
|
prevWeekEnd
|
||||||
Fri: { amount: 0, compare: 0 },
|
} = buildDailyBuckets(now);
|
||||||
Sat: { amount: 0, compare: 0 },
|
|
||||||
Sun: { amount: 0, compare: 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
const weekStart = getStartOfWeek(now);
|
const weeklyRolling = buildWeeklyRolling(now);
|
||||||
const weekEnd = endOfDay(new Date(weekStart.getTime() + 6 * 86400000));
|
const weeklyCalendar = buildWeeklyCalendar(now);
|
||||||
const prevWeekStart = shiftDate(weekStart, -7);
|
const monthlyRolling = buildMonthlyRolling(now);
|
||||||
const prevWeekEnd = shiftDate(weekEnd, -7);
|
const monthlyCalendar = buildMonthlyCalendar(now);
|
||||||
|
|
||||||
// ---------------- WEEKLY ----------------
|
|
||||||
const weeklyRolling: any[] = [];
|
|
||||||
const weeklyCalendar: any[] = [];
|
|
||||||
|
|
||||||
const currentWeekStart = getStartOfWeek(now);
|
|
||||||
|
|
||||||
// rolling (last 5 weeks)
|
|
||||||
for (let i = 4; i >= 0; i--) {
|
|
||||||
const start = new Date(currentWeekStart.getTime() - i * 7 * 86400000);
|
|
||||||
const end = endOfDay(new Date(start.getTime() + 6 * 86400000));
|
|
||||||
|
|
||||||
weeklyRolling.push({
|
|
||||||
label: `${format(start)} - ${format(end)}`,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
amount: 0,
|
|
||||||
compare: 0,
|
|
||||||
prevStart: shiftDate(start, -7),
|
|
||||||
prevEnd: shiftDate(end, -7)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// calendar weeks
|
|
||||||
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
|
|
||||||
const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0);
|
|
||||||
|
|
||||||
const firstWeekStart = getStartOfWeek(startOfMonth);
|
|
||||||
|
|
||||||
const totalWeeks = Math.ceil(
|
|
||||||
(endOfMonth.getTime() - firstWeekStart.getTime()) / (7 * 86400000)
|
|
||||||
) + 1;
|
|
||||||
|
|
||||||
for (let i = 0; i < totalWeeks; i++) {
|
|
||||||
const start = new Date(firstWeekStart.getTime() + i * 7 * 86400000);
|
|
||||||
const end = endOfDay(new Date(start.getTime() + 6 * 86400000));
|
|
||||||
|
|
||||||
weeklyCalendar.push({
|
|
||||||
label: `${format(start)} - ${format(end)}`,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
amount: 0,
|
|
||||||
compare: 0,
|
|
||||||
prevStart: shiftDate(start, -7),
|
|
||||||
prevEnd: shiftDate(end, -7)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------- MONTHLY ----------------
|
|
||||||
const monthlyRolling: any[] = [];
|
|
||||||
const monthlyCalendar: any[] = [];
|
|
||||||
|
|
||||||
// rolling (last 12 months)
|
|
||||||
for (let i = 11; i >= 0; i--) {
|
|
||||||
const d = new Date(now);
|
|
||||||
d.setMonth(d.getMonth() - i);
|
|
||||||
|
|
||||||
const start = new Date(d.getFullYear(), d.getMonth(), 1);
|
|
||||||
const end =
|
|
||||||
i === 0
|
|
||||||
? endOfDay(now)
|
|
||||||
: endOfDay(new Date(d.getFullYear(), d.getMonth() + 1, 0));
|
|
||||||
|
|
||||||
const prevStart = new Date(start);
|
|
||||||
prevStart.setMonth(prevStart.getMonth() - 1);
|
|
||||||
const prevEnd = new Date(end);
|
|
||||||
prevEnd.setMonth(prevEnd.getMonth() - 1);
|
|
||||||
|
|
||||||
monthlyRolling.push({
|
|
||||||
label: `${d.toLocaleString("default", { month: "short" })}-${String(
|
|
||||||
d.getFullYear()
|
|
||||||
).slice(2)}`,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
amount: 0,
|
|
||||||
compare: 0,
|
|
||||||
prevStart,
|
|
||||||
prevEnd
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// calendar (Jan–Dec)
|
|
||||||
for (let i = 0; i < 12; i++) {
|
|
||||||
const start = new Date(now.getFullYear(), i, 1);
|
|
||||||
const end = endOfDay(new Date(now.getFullYear(), i + 1, 0));
|
|
||||||
|
|
||||||
const prevStart = new Date(start);
|
|
||||||
prevStart.setFullYear(prevStart.getFullYear() - 1);
|
|
||||||
const prevEnd = new Date(end);
|
|
||||||
prevEnd.setFullYear(prevEnd.getFullYear() - 1);
|
|
||||||
|
|
||||||
monthlyCalendar.push({
|
|
||||||
label: `${start.toLocaleString("default", { month: "short" })}-${String(
|
|
||||||
start.getFullYear()
|
|
||||||
).slice(2)}`,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
amount: 0,
|
|
||||||
compare: 0,
|
|
||||||
prevStart,
|
|
||||||
prevEnd
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------- LOOP ----------------
|
|
||||||
for (const item of all) {
|
for (const item of all) {
|
||||||
const d = new Date(
|
const d = new Date(
|
||||||
item.occurred_at || item.created_at || Date.now()
|
item.occurred_at || item.created_at || Date.now()
|
||||||
@@ -237,46 +92,37 @@ export async function fetchAggregatedData(
|
|||||||
if (!isValid(amtRaw)) continue;
|
if (!isValid(amtRaw)) continue;
|
||||||
|
|
||||||
const amt = normalize(amtRaw);
|
const amt = normalize(amtRaw);
|
||||||
|
|
||||||
totalAmount += amt;
|
totalAmount += amt;
|
||||||
|
|
||||||
const payee = item.payee?.name || item.payee || "Unknown";
|
const payee = item.payee?.name || item.payee || "Unknown";
|
||||||
payeeMap[payee] = (payeeMap[payee] || 0) + amt;
|
payeeMap[payee] = (payeeMap[payee] || 0) + amt;
|
||||||
|
|
||||||
// DAILY
|
const day = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][d.getDay()];
|
||||||
|
|
||||||
if (d >= weekStart && d <= weekEnd) {
|
if (d >= weekStart && d <= weekEnd) {
|
||||||
const day = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][d.getDay()];
|
|
||||||
if (dailyBuckets[day]) {
|
if (dailyBuckets[day]) {
|
||||||
dailyBuckets[day].amount += amt;
|
dailyBuckets[day].amount += amt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d >= prevWeekStart && d <= prevWeekEnd) {
|
if (d >= prevWeekStart && d <= prevWeekEnd) {
|
||||||
const day = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][d.getDay()];
|
|
||||||
if (dailyBuckets[day]) {
|
if (dailyBuckets[day]) {
|
||||||
dailyBuckets[day].compare += amt;
|
dailyBuckets[day].compare += amt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WEEKLY
|
const apply = (arr: any[]) => {
|
||||||
for (const b of weeklyRolling) {
|
for (const b of arr) {
|
||||||
if (d >= b.start && d <= b.end) b.amount += amt;
|
if (d >= b.start && d <= b.end) b.amount += amt;
|
||||||
if (d >= b.prevStart && d <= b.prevEnd) b.compare += amt;
|
if (d >= b.prevStart && d <= b.prevEnd)
|
||||||
}
|
b.compare += amt;
|
||||||
for (const b of weeklyCalendar) {
|
}
|
||||||
if (d >= b.start && d <= b.end) b.amount += amt;
|
};
|
||||||
if (d >= b.prevStart && d <= b.prevEnd) b.compare += amt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// MONTHLY
|
apply(weeklyRolling);
|
||||||
for (const b of monthlyRolling) {
|
apply(weeklyCalendar);
|
||||||
if (d >= b.start && d <= b.end) b.amount += amt;
|
apply(monthlyRolling);
|
||||||
if (d >= b.prevStart && d <= b.prevEnd) b.compare += amt;
|
apply(monthlyCalendar);
|
||||||
}
|
|
||||||
for (const b of monthlyCalendar) {
|
|
||||||
if (d >= b.start && d <= b.end) b.amount += amt;
|
|
||||||
if (d >= b.prevStart && d <= b.prevEnd) b.compare += amt;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const toPoints = (arr: any[]): ChartDataPoint[] =>
|
const toPoints = (arr: any[]): ChartDataPoint[] =>
|
||||||
@@ -286,7 +132,7 @@ export async function fetchAggregatedData(
|
|||||||
compareAmount: x.compare
|
compareAmount: x.compare
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const chartData: ChartData = {
|
const chartData = {
|
||||||
daily: Object.entries(dailyBuckets).map(([k, v]: any) => ({
|
daily: Object.entries(dailyBuckets).map(([k, v]: any) => ({
|
||||||
id: k,
|
id: k,
|
||||||
amount: v.amount,
|
amount: v.amount,
|
||||||
@@ -302,7 +148,6 @@ export async function fetchAggregatedData(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// highlight max (current only)
|
|
||||||
Object.values(chartData).forEach((group: any) => {
|
Object.values(chartData).forEach((group: any) => {
|
||||||
const arr = Array.isArray(group) ? group : group.rolling;
|
const arr = Array.isArray(group) ? group : group.rolling;
|
||||||
if (!arr?.length) return;
|
if (!arr?.length) return;
|
||||||
@@ -322,7 +167,6 @@ export async function fetchAggregatedData(
|
|||||||
return { chartData, totalAmount, topPayees };
|
return { chartData, totalAmount, topPayees };
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------- EXPORTS ----------------
|
|
||||||
export const fetchAggregatedExpenses = () =>
|
export const fetchAggregatedExpenses = () =>
|
||||||
fetchAggregatedData("expense");
|
fetchAggregatedData("expense");
|
||||||
|
|
||||||
|
|||||||
33
src/utils/dateUtils.ts
Normal file
33
src/utils/dateUtils.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
export const format = (d: Date) =>
|
||||||
|
`${d.getDate()} ${d.toLocaleString("default", { month: "short" })}`;
|
||||||
|
|
||||||
|
export const startOfDay = (d: Date) => {
|
||||||
|
const x = new Date(d);
|
||||||
|
x.setHours(0, 0, 0, 0);
|
||||||
|
return x;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const endOfDay = (d: Date) => {
|
||||||
|
const x = new Date(d);
|
||||||
|
x.setHours(23, 59, 59, 999);
|
||||||
|
return x;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStartOfWeek = (d: Date) => {
|
||||||
|
const date = new Date(d);
|
||||||
|
const day = date.getDay() || 7;
|
||||||
|
if (day !== 1) date.setDate(date.getDate() - (day - 1));
|
||||||
|
return startOfDay(date);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const shiftDate = (d: Date, days: number) =>
|
||||||
|
new Date(d.getTime() + days * 86400000);
|
||||||
|
|
||||||
|
export const getWeekIndex = (date: Date) => {
|
||||||
|
const firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
|
||||||
|
const firstWeekStart = getStartOfWeek(firstDay);
|
||||||
|
return Math.floor(
|
||||||
|
(startOfDay(date).getTime() - firstWeekStart.getTime()) /
|
||||||
|
(7 * 86400000)
|
||||||
|
);
|
||||||
|
};
|
||||||
178
src/utils/periodBuilders.ts
Normal file
178
src/utils/periodBuilders.ts
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
import {
|
||||||
|
format,
|
||||||
|
endOfDay,
|
||||||
|
getStartOfWeek,
|
||||||
|
shiftDate,
|
||||||
|
getWeekIndex
|
||||||
|
} from "./dateUtils";
|
||||||
|
|
||||||
|
export const buildDailyBuckets = (now: Date) => {
|
||||||
|
const buckets: Record<string, any> = {
|
||||||
|
Mon: { amount: 0, compare: 0 },
|
||||||
|
Tue: { amount: 0, compare: 0 },
|
||||||
|
Wed: { amount: 0, compare: 0 },
|
||||||
|
Thu: { amount: 0, compare: 0 },
|
||||||
|
Fri: { amount: 0, compare: 0 },
|
||||||
|
Sat: { amount: 0, compare: 0 },
|
||||||
|
Sun: { amount: 0, compare: 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
const weekStart = getStartOfWeek(now);
|
||||||
|
const weekEnd = endOfDay(new Date(weekStart.getTime() + 6 * 86400000));
|
||||||
|
const prevWeekStart = shiftDate(weekStart, -7);
|
||||||
|
const prevWeekEnd = shiftDate(weekEnd, -7);
|
||||||
|
|
||||||
|
return { buckets, weekStart, weekEnd, prevWeekStart, prevWeekEnd };
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPrevMonthWeek = (start: Date) => {
|
||||||
|
const prevMonthDate = new Date(start);
|
||||||
|
prevMonthDate.setMonth(prevMonthDate.getMonth() - 1);
|
||||||
|
|
||||||
|
const prevMonthFirst = new Date(
|
||||||
|
prevMonthDate.getFullYear(),
|
||||||
|
prevMonthDate.getMonth(),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
const prevFirstWeekStart = getStartOfWeek(prevMonthFirst);
|
||||||
|
const weekIndex = getWeekIndex(start);
|
||||||
|
|
||||||
|
const prevStart = new Date(
|
||||||
|
prevFirstWeekStart.getTime() + weekIndex * 7 * 86400000
|
||||||
|
);
|
||||||
|
const prevEnd = endOfDay(new Date(prevStart.getTime() + 6 * 86400000));
|
||||||
|
|
||||||
|
return { prevStart, prevEnd };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const buildWeeklyRolling = (now: Date) => {
|
||||||
|
const arr: any[] = [];
|
||||||
|
const currentWeekStart = getStartOfWeek(now);
|
||||||
|
|
||||||
|
for (let i = 4; i >= 0; i--) {
|
||||||
|
const start = new Date(
|
||||||
|
currentWeekStart.getTime() - i * 7 * 86400000
|
||||||
|
);
|
||||||
|
const end = endOfDay(new Date(start.getTime() + 6 * 86400000));
|
||||||
|
|
||||||
|
const { prevStart, prevEnd } = getPrevMonthWeek(start);
|
||||||
|
|
||||||
|
arr.push({
|
||||||
|
label: `${format(start)} - ${format(end)}`,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
amount: 0,
|
||||||
|
compare: 0,
|
||||||
|
prevStart,
|
||||||
|
prevEnd
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const buildWeeklyCalendar = (now: Date) => {
|
||||||
|
const arr: any[] = [];
|
||||||
|
|
||||||
|
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
|
||||||
|
const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0);
|
||||||
|
const firstWeekStart = getStartOfWeek(startOfMonth);
|
||||||
|
|
||||||
|
const totalWeeks =
|
||||||
|
Math.ceil(
|
||||||
|
(endOfMonth.getTime() - firstWeekStart.getTime()) /
|
||||||
|
(7 * 86400000)
|
||||||
|
) + 1;
|
||||||
|
|
||||||
|
for (let i = 0; i < totalWeeks; i++) {
|
||||||
|
const start = new Date(
|
||||||
|
firstWeekStart.getTime() + i * 7 * 86400000
|
||||||
|
);
|
||||||
|
const end = endOfDay(new Date(start.getTime() + 6 * 86400000));
|
||||||
|
|
||||||
|
const { prevStart, prevEnd } = getPrevMonthWeek(start);
|
||||||
|
|
||||||
|
arr.push({
|
||||||
|
label: `${format(start)} - ${format(end)}`,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
amount: 0,
|
||||||
|
compare: 0,
|
||||||
|
prevStart,
|
||||||
|
prevEnd
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const buildMonthlyRolling = (now: Date) => {
|
||||||
|
const arr: any[] = [];
|
||||||
|
|
||||||
|
for (let i = 11; i >= 0; i--) {
|
||||||
|
const d = new Date(now);
|
||||||
|
d.setMonth(d.getMonth() - i);
|
||||||
|
|
||||||
|
const start = new Date(d.getFullYear(), d.getMonth(), 1);
|
||||||
|
const end =
|
||||||
|
i === 0
|
||||||
|
? endOfDay(now)
|
||||||
|
: endOfDay(new Date(d.getFullYear(), d.getMonth() + 1, 0));
|
||||||
|
|
||||||
|
const prevStart = new Date(start);
|
||||||
|
prevStart.setFullYear(prevStart.getFullYear() - 1);
|
||||||
|
|
||||||
|
let prevEnd = new Date(end);
|
||||||
|
prevEnd.setFullYear(prevEnd.getFullYear() - 1);
|
||||||
|
|
||||||
|
if (i === 0) {
|
||||||
|
prevEnd = new Date(prevStart);
|
||||||
|
prevEnd.setDate(now.getDate());
|
||||||
|
prevEnd = endOfDay(prevEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
arr.push({
|
||||||
|
label: `${d.toLocaleString("default", {
|
||||||
|
month: "short"
|
||||||
|
})}-${String(d.getFullYear()).slice(2)}`,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
amount: 0,
|
||||||
|
compare: 0,
|
||||||
|
prevStart,
|
||||||
|
prevEnd
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const buildMonthlyCalendar = (now: Date) => {
|
||||||
|
const arr: any[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < 12; i++) {
|
||||||
|
const start = new Date(now.getFullYear(), i, 1);
|
||||||
|
const end = endOfDay(new Date(now.getFullYear(), i + 1, 0));
|
||||||
|
|
||||||
|
const prevStart = new Date(start);
|
||||||
|
prevStart.setFullYear(prevStart.getFullYear() - 1);
|
||||||
|
|
||||||
|
const prevEnd = new Date(end);
|
||||||
|
prevEnd.setFullYear(prevEnd.getFullYear() - 1);
|
||||||
|
|
||||||
|
arr.push({
|
||||||
|
label: `${start.toLocaleString("default", {
|
||||||
|
month: "short"
|
||||||
|
})}-${String(start.getFullYear()).slice(2)}`,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
amount: 0,
|
||||||
|
compare: 0,
|
||||||
|
prevStart,
|
||||||
|
prevEnd
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user