fix: use robust date parsing utility to handle varying n8n date formats
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m26s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m26s
This commit is contained in:
@@ -52,3 +52,20 @@ export const fetchData = async (): Promise<OrderData[]> => {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const parseOrderDate = (dateStr: string): Date => {
|
||||||
|
if (!dateStr) return new Date(0);
|
||||||
|
if (dateStr.includes('T')) return new Date(dateStr);
|
||||||
|
const parts = dateStr.split(/[-/]/);
|
||||||
|
if (parts.length === 3) {
|
||||||
|
if (parts[0].length === 4) {
|
||||||
|
// YYYY-MM-DD
|
||||||
|
return new Date(Number(parts[0]), Number(parts[1]) - 1, Number(parts[2]));
|
||||||
|
} else {
|
||||||
|
// DD-MM-YYYY
|
||||||
|
return new Date(Number(parts[2]), Number(parts[1]) - 1, Number(parts[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const fallback = new Date(dateStr);
|
||||||
|
return isNaN(fallback.getTime()) ? new Date(0) : fallback;
|
||||||
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useMemo, useState } from 'react';
|
|||||||
import { Link, useOutletContext } from 'react-router-dom';
|
import { Link, useOutletContext } from 'react-router-dom';
|
||||||
import { Search, ChevronRight, Filter } from 'lucide-react';
|
import { Search, ChevronRight, Filter } from 'lucide-react';
|
||||||
import type { OrderData } from '../types';
|
import type { OrderData } from '../types';
|
||||||
|
import { parseOrderDate } from '../dataService';
|
||||||
|
|
||||||
type SortOption = 'recent' | 'spent_desc' | 'spent_asc' | 'items_desc' | 'items_asc';
|
type SortOption = 'recent' | 'spent_desc' | 'spent_asc' | 'items_desc' | 'items_asc';
|
||||||
|
|
||||||
@@ -26,8 +27,7 @@ const Clients = () => {
|
|||||||
clientMap[clientName].totalItems += order.Quantidade;
|
clientMap[clientName].totalItems += order.Quantidade;
|
||||||
clientMap[clientName].uniqueOrders.add(`${order.Data_Pedido}_${order.Valor_Pedido}`);
|
clientMap[clientName].uniqueOrders.add(`${order.Data_Pedido}_${order.Valor_Pedido}`);
|
||||||
|
|
||||||
const [day, month, year] = order.Data_Pedido.split('-').map(Number);
|
const orderTime = parseOrderDate(order.Data_Pedido).getTime();
|
||||||
const orderTime = new Date(year, month - 1, day).getTime();
|
|
||||||
|
|
||||||
if (orderTime > clientMap[clientName].lastPurchase) {
|
if (orderTime > clientMap[clientName].lastPurchase) {
|
||||||
clientMap[clientName].lastPurchase = orderTime;
|
clientMap[clientName].lastPurchase = orderTime;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContaine
|
|||||||
import { DollarSign, ShoppingCart, TrendingUp } from 'lucide-react';
|
import { DollarSign, ShoppingCart, TrendingUp } from 'lucide-react';
|
||||||
import DateRangePicker from '../components/DateRangePicker';
|
import DateRangePicker from '../components/DateRangePicker';
|
||||||
import type { OrderData, DateRange } from '../types';
|
import type { OrderData, DateRange } from '../types';
|
||||||
|
import { parseOrderDate } from '../dataService';
|
||||||
|
|
||||||
const COLORS = [
|
const COLORS = [
|
||||||
'#10b981', '#3b82f6', '#8b5cf6', '#f43f5e', '#f97316',
|
'#10b981', '#3b82f6', '#8b5cf6', '#f43f5e', '#f97316',
|
||||||
@@ -16,8 +17,7 @@ const Dashboard = () => {
|
|||||||
const filteredData = useMemo(() => {
|
const filteredData = useMemo(() => {
|
||||||
const orders = ordersData;
|
const orders = ordersData;
|
||||||
return orders.filter(order => {
|
return orders.filter(order => {
|
||||||
const [day, month, year] = order.Data_Pedido.split('-').map(Number);
|
const orderDate = parseOrderDate(order.Data_Pedido);
|
||||||
const orderDate = new Date(year, month - 1, day);
|
|
||||||
return orderDate >= dateRange.start && orderDate <= dateRange.end;
|
return orderDate >= dateRange.start && orderDate <= dateRange.end;
|
||||||
});
|
});
|
||||||
}, [dateRange, ordersData]);
|
}, [dateRange, ordersData]);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { ArrowLeft, Package, DollarSign } from 'lucide-react';
|
|||||||
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
|
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
|
||||||
import DateRangePicker from '../components/DateRangePicker';
|
import DateRangePicker from '../components/DateRangePicker';
|
||||||
import type { OrderData, DateRange } from '../types';
|
import type { OrderData, DateRange } from '../types';
|
||||||
|
import { parseOrderDate } from '../dataService';
|
||||||
|
|
||||||
const ProductDetails = () => {
|
const ProductDetails = () => {
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
@@ -25,11 +26,9 @@ const ProductDetails = () => {
|
|||||||
let revenue = 0;
|
let revenue = 0;
|
||||||
|
|
||||||
orders.forEach(order => {
|
orders.forEach(order => {
|
||||||
const [day, month, year] = order.Data_Pedido.split('-').map(Number);
|
const orderDate = parseOrderDate(order.Data_Pedido);
|
||||||
const orderDate = new Date(year, month - 1, day);
|
|
||||||
|
|
||||||
if (orderDate >= dateRange.start && orderDate <= dateRange.end) {
|
if (orderDate >= dateRange.start && orderDate <= dateRange.end) { const dateStr = order.Data_Pedido;
|
||||||
const dateStr = order.Data_Pedido;
|
|
||||||
salesByDate[dateStr] = (salesByDate[dateStr] || 0) + order.Quantidade;
|
salesByDate[dateStr] = (salesByDate[dateStr] || 0) + order.Quantidade;
|
||||||
sold += order.Quantidade;
|
sold += order.Quantidade;
|
||||||
revenue += (order.Quantidade * order.Valor_Unitario);
|
revenue += (order.Quantidade * order.Valor_Unitario);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Link, useOutletContext } from 'react-router-dom';
|
|||||||
import { Search, Package, TrendingUp } from 'lucide-react';
|
import { Search, Package, TrendingUp } from 'lucide-react';
|
||||||
import DateRangePicker from '../components/DateRangePicker';
|
import DateRangePicker from '../components/DateRangePicker';
|
||||||
import type { OrderData, DateRange } from '../types';
|
import type { OrderData, DateRange } from '../types';
|
||||||
|
import { parseOrderDate } from '../dataService';
|
||||||
|
|
||||||
const Products = () => {
|
const Products = () => {
|
||||||
const { dateRange, setDateRange, ordersData } = useOutletContext<{ dateRange: DateRange, setDateRange: (range: DateRange) => void, ordersData: OrderData[] }>();
|
const { dateRange, setDateRange, ordersData } = useOutletContext<{ dateRange: DateRange, setDateRange: (range: DateRange) => void, ordersData: OrderData[] }>();
|
||||||
@@ -13,8 +14,7 @@ const Products = () => {
|
|||||||
const productMap: Record<string, { id: string, name: string, totalSold: number, revenue: number, lastPrice: number }> = {};
|
const productMap: Record<string, { id: string, name: string, totalSold: number, revenue: number, lastPrice: number }> = {};
|
||||||
|
|
||||||
orders.forEach(order => {
|
orders.forEach(order => {
|
||||||
const [day, month, year] = order.Data_Pedido.split('-').map(Number);
|
const orderDate = parseOrderDate(order.Data_Pedido);
|
||||||
const orderDate = new Date(year, month - 1, day);
|
|
||||||
if (orderDate < dateRange.start || orderDate > dateRange.end) return;
|
if (orderDate < dateRange.start || orderDate > dateRange.end) return;
|
||||||
|
|
||||||
if (!productMap[order.ID_Produto]) {
|
if (!productMap[order.ID_Produto]) {
|
||||||
|
|||||||
@@ -13,5 +13,14 @@ export default defineConfig({
|
|||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
preview: {
|
||||||
|
port: 3000,
|
||||||
|
proxy: {
|
||||||
|
'/api': {
|
||||||
|
target: 'http://localhost:3004',
|
||||||
|
changeOrigin: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user