Skip to content

Commit

Permalink
fix graph
Browse files Browse the repository at this point in the history
  • Loading branch information
Bibiing committed Dec 11, 2024
1 parent 12acdfc commit 8f938de
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 136 deletions.
10 changes: 3 additions & 7 deletions src/components/PlayBack/ImageDisplay.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@ import ImageUploadStats from "./ImageUploadStats";

const ImageDisplay = ({ images, error, viewMode, onImageClick }) => {
return (
<div className="w-full max-w-7xl bg-[#f0faff] rounded-lg shadow-md mb-8">
{/* Statistics View */}
<div className="w-full max-w-7xl xl:max-w-[1800px] bg-[#f0faff] rounded-lg shadow-md mb-8">
{viewMode === "list" && <ImageUploadStats images={images} />}

{/* Grid View */}
{viewMode === "grid" && (
<div className="p-4">
{/* Error and Empty State Handling */}
<div className="p-4 bg-purple-30 h-[610px] overflow-y-auto ">
{error && (
<div className="text-center text-red-500 p-4 bg-red-50 rounded-lg">
<div className="text-center text-red-500 p-4 bg-red-50 rounded-lg mb-4">
Error: {error}
</div>
)}
Expand All @@ -24,7 +21,6 @@ const ImageDisplay = ({ images, error, viewMode, onImageClick }) => {
</div>
)}

{/* Grid Layout */}
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4">
{images.map((image, index) => (
<div
Expand Down
202 changes: 91 additions & 111 deletions src/components/PlayBack/ImageUploadStats.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,125 +6,115 @@ import {
YAxis,
CartesianGrid,
Tooltip,
Legend,
ResponsiveContainer,
} from "recharts";

const ImageUploadStats = ({ images }) => {
// Group images by date and count uploads with optional filtering
const processImageData = () => {
const uploadCounts = {};
// Generate 24-hour data points
const generate24HourData = () => {
return Array.from({ length: 24 }, (_, hour) => ({
hour: `${hour.toString().padStart(2, "0")}:00`,
uploads: 0,
}));
};

// Process images and apply filters
const processImageData = (images) => {
// Create base 24-hour data
const hourlyData = generate24HourData();

// Filter and count uploads
images.forEach((image) => {
if (image.date) {
uploadCounts[image.date] = (uploadCounts[image.date] || 0) + 1;
if (image.time) {
const hour = image.time.split(":")[0].padStart(2, "0");
const hourEntry = hourlyData.find(
(entry) => entry.hour === `${hour}:00`
);
if (hourEntry) {
hourEntry.uploads++;
}
}
});

// Convert to chart-friendly format
return Object.keys(uploadCounts)
.map((date) => ({
date,
uploads: uploadCounts[date],
}))
.sort((a, b) => new Date(a.date) - new Date(b.date));
return hourlyData;
};

const processHourlyData = () => {
const hourlyUploads = {};
// Determine the day with most uploads (if applicable)
const findMostActiveDay = (images) => {
if (images.length === 0) return null;

images.forEach((image) => {
if (image.time) {
const hour = image.time.split(":")[0];
hourlyUploads[hour] = (hourlyUploads[hour] || 0) + 1;
// Group images by date and count
const dateCounts = images.reduce((acc, image) => {
if (image.date) {
acc[image.date] = (acc[image.date] || 0) + 1;
}
});
return acc;
}, {});

// Convert to chart-friendly format
return Object.keys(hourlyUploads)
.map((hour) => ({
hour: `${hour}:00`,
uploads: hourlyUploads[hour],
}))
.sort((a, b) => parseInt(a.hour) - parseInt(b.hour));
// Find the date with most uploads
return Object.entries(dateCounts).reduce((a, b) =>
b[1] > a[1] ? b : a
)[0];
};

const dailyData = processImageData();
const hourlyData = processHourlyData();
// Process data
const hourlyData = processImageData(images);

// Find most active day
const mostActiveDay = findMostActiveDay(images);

// Calculate total uploads and max uploads
const totalUploads = hourlyData.reduce(
(sum, entry) => sum + entry.uploads,
0
);
const maxUploads = Math.max(...hourlyData.map((entry) => entry.uploads));

return (
<div className="w-full py-8 px-2 sm:px-4 md:px-6 lg:px-8">
{/* Charts Container - Responsive Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-8">
{/* Daily Uploads Chart */}
<div className="w-full">
<h2 className="text-lg md:text-xl font-semibold mb-2 md:mb-4 text-center">
Daily Uploads
</h2>
<ResponsiveContainer width="100%" height={250} className="max-w-full">
{dailyData.length > 0 ? (
<LineChart data={dailyData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis
dataKey="date"
tick={{ fontSize: 10 }}
interval="preserveStartEnd"
/>
<YAxis allowDecimals={false} tick={{ fontSize: 10 }} />
<Tooltip
contentStyle={{ fontSize: "12px" }}
labelStyle={{ fontSize: "10px" }}
/>
<Legend wrapperStyle={{ fontSize: "12px" }} />
<Line
type="monotone"
dataKey="uploads"
stroke="#365486"
activeDot={{ r: 6 }}
/>
</LineChart>
) : (
<div className="text-center text-gray-500">No daily data</div>
)}
</ResponsiveContainer>
</div>

{/* Hourly Uploads Chart */}
<div className="w-full ">
<h2 className="text-lg md:text-xl font-semibold mb-2 md:mb-4 text-center">
Hourly Uploads
</h2>
<ResponsiveContainer width="100%" height={250} className="max-w-full">
{hourlyData.length > 0 ? (
<LineChart data={hourlyData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis
dataKey="hour"
tick={{ fontSize: 10 }}
interval="preserveStartEnd"
/>
<YAxis allowDecimals={false} tick={{ fontSize: 10 }} />
<Tooltip
contentStyle={{ fontSize: "12px" }}
labelStyle={{ fontSize: "10px" }}
/>
<Legend wrapperStyle={{ fontSize: "12px" }} />
<Line
type="monotone"
dataKey="uploads"
stroke="#2a4675"
activeDot={{ r: 6 }}
/>
</LineChart>
) : (
<div className="text-center text-gray-500">No hourly data</div>
)}
</ResponsiveContainer>
</div>
<div className="w-full p-2">
<h2 className="text-lg md:text-xl font-semibold mb-2 md:mb-4 text-center">
Hourly Uploads {mostActiveDay ? `on ${mostActiveDay}` : ""}
</h2>
<ResponsiveContainer width="100%" height={300} className="max-w-full ">
{images.length > 0 ? (
<LineChart data={hourlyData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis
dataKey="hour"
tick={{ fontSize: 10 }}
interval="preserveStartEnd"
/>
<YAxis
allowDecimals={false}
tick={{ fontSize: 10 }}
label={{
value: "Uploads",
angle: -90,
position: "outsideLeft",
}}
/>
<Tooltip
contentStyle={{ fontSize: "12px" }}
labelStyle={{ fontSize: "10px" }}
/>
<Line
type="monotone"
dataKey="uploads"
stroke="#365486"
strokeWidth={2}
activeDot={{ r: 6 }}
/>
</LineChart>
) : (
<div className="text-center text-gray-500">
No upload data available
</div>
)}
</ResponsiveContainer>
</div>

{/* Additional Statistics - Responsive Grid */}
<div className="mt-4 md:mt-6 grid grid-cols-1 sm:grid-cols-3 gap-2 sm:gap-4 text-center">
<div className="grid grid-cols-1 sm:grid-cols-3 gap-2 sm:gap-4 text-center mb-6">
<div className="bg-[#e0f5ff] p-2 sm:p-4 rounded-lg">
<h3 className="font-semibold text-base sm:text-lg">Total Images</h3>
<p className="text-xl sm:text-2xl text-[#365486]">{images.length}</p>
Expand All @@ -134,24 +124,14 @@ const ImageUploadStats = ({ images }) => {
Most Active Day
</h3>
<p className="text-xl sm:text-2xl text-[#365486]">
{dailyData.length > 0
? dailyData.reduce((prev, current) =>
prev.uploads > current.uploads ? prev : current
).date
: "N/A"}
{mostActiveDay || "N/A"}
</p>
</div>
<div className="bg-[#e0f5ff] p-2 sm:p-4 rounded-lg">
<h3 className="font-semibold text-base sm:text-lg">
Most Active Hour
Peak Hour Uploads
</h3>
<p className="text-xl sm:text-2xl text-[#365486]">
{hourlyData.length > 0
? hourlyData.reduce((prev, current) =>
prev.uploads > current.uploads ? prev : current
).hour
: "N/A"}
</p>
<p className="text-xl sm:text-2xl text-[#365486]">{maxUploads}</p>
</div>
</div>
</div>
Expand Down
36 changes: 18 additions & 18 deletions src/pages/PlaybacksPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,26 @@ const PlaybacksPage = () => {
return (
<div className="font-poppins">
<Header />
<main className="mt-[120px]">
<div className="bg-[#f8fbff] font-poppins min-h-screen flex flex-col items-center py-4 sm:py-8 px-4 sm:px-6">
<main className="bg-[#f8fbff] font-poppins min-h-screen flex flex-col items-center py-4 sm:py-8 px-4 sm:px-6">
<div className="mt-[50px] md:mt-[100px]">
<ImageFilterForm onSubmit={handleFilterSubmit} />

<ImageViewModeToggle
viewMode={viewMode}
onViewModeChange={setViewMode}
/>

<ImageDisplay
images={images}
error={error}
viewMode={viewMode}
onImageClick={openModal}
/>

{isModalOpen && activeImage && (
<ImageModal image={activeImage} closeModal={closeModal} />
)}
</div>

<ImageViewModeToggle
viewMode={viewMode}
onViewModeChange={setViewMode}
/>

<ImageDisplay
images={images}
error={error}
viewMode={viewMode}
onImageClick={openModal}
/>

{isModalOpen && activeImage && (
<ImageModal image={activeImage} closeModal={closeModal} />
)}
</main>
<Footer />
</div>
Expand Down

0 comments on commit 8f938de

Please sign in to comment.