I want to create a storage management system for dentists. I don't seem to understand the concept of SSR and CSR and how to properly use it in my project. I have a route app/stock/page.tsx and this file has the "use client" tag. Though I am almost certain this is not the right way, it works. With which I struggle the most is the data fetching and the Next.js API routes. The API Routes just wont work for me when I add /app/stock/api/route.ts and write a GET handler. When i check with Postman I get Error 404.
I just need someone to tell me which functions or logic I should seperate into it's own file and why.
On StackOverflow I just get downvotes and nobody wants to tell me what I'm doing wrong. Thank you in advance.
The code is as follows:
"use client";
import React, { useEffect, useState } from "react";
import "tailwindcss/tailwind.css";
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@/components/ui/resizable"
import { Button } from "@/components/ui/button"
const StockPage: React.FC = () => {
const [items, setItems] = useState<any[]>([]);
const [sortedItems, setSortedItems] = useState<any[]>([]);
const [subcategories, setSubcategories] = useState<any[]>([]);
const [selectedSubcategory, setSelectedSubcategory] = useState<any | null>(
null
);
const [selectedItem, setSelectedItem] = useState<any | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
const res = await fetch("http://localhost:5000/get_items", {
method: "GET",
cache: "no-store",
});
const data = await res.json();
setItems(data);
setSortedItems(data);
} catch (error) {
console.error("Error fetching data:", error);
}
};
fetchData();
}, []);
useEffect(() => {
const fetchSubcategories = async () => {
try {
const res = await fetch("http://localhost:5000/get_subcategories", {
method: "GET",
cache: "no-store",
});
const data = await res.json();
setSubcategories(data);
} catch (error) {
console.error("Error fetching subcategories:", error);
}
};
fetchSubcategories();
}, []);
const handleSortBySubcategory = (selectedSubcategory: any) => {
const sorted = items.filter((item) => item.subcategory === selectedSubcategory.id);
setSortedItems(sorted);
setSelectedSubcategory(selectedSubcategory);
};
const handleViewAll = () => {
// Reset the sorting and display all items
setSortedItems(items);
setSelectedSubcategory(null);
};
const getSubcategoryName = (subcategoryId: string) => {
const subcategory = subcategories.find(sub => sub.id === subcategoryId);
return subcategory ? subcategory.name : "Unknown";
};
const handleRowClick = (item: any) => {
// Toggle selection on row click
setSelectedItem(selectedItem === item ? null : item);
};
const handleIncrementAmount = async () => {
if (selectedItem) {
// Make an API call to update the amount in the database
try {
const res = await fetch(`http://localhost:5000/updateAmount?id=${selectedItem.id}`, {
method: 'PUT',
cache: 'no-store',
});
if (res.ok) {
// Update the amount in the local state only if the API call is successful
const updatedItems = items.map((item) =>
item.id === selectedItem.id
? { ...item, amount: item.amount + 1 }
: item
);
// Update state to trigger a re-render
setItems(updatedItems);
setSortedItems(updatedItems);
} else {
console.error('Failed to update amount in the database');
}
} catch (error) {
console.error('Error updating amount:', error);
}
}
};
const handleDecrementAmount = () => {
if (selectedItem && selectedItem.amount > 0) {
// Update the amount of the selected item by subtracting 1
const updatedItems = items.map((item) =>
item.id === selectedItem.id
? { ...item, amount: item.amount - 1 }
: item
);
// Update state to trigger a re-render
setItems(updatedItems);
setSortedItems(updatedItems);
}
};
return (
<ResizablePanelGroup
direction="horizontal"
className="fit-w-md rounded-lg border"
>
<ResizablePanel defaultSize={50}>
<div className="flex h-full items-center justify-center p-full">
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Subcategory</th>
<th>Amount</th>
<th>Limit</th>
<th>Description</th>
<th>TimestampE</th>
<th>TimestampR</th>
</tr>
</thead>
<tbody>
{sortedItems.map((item) => (
<tr
key={item.id}
onClick={() => handleRowClick(item)} // Handle row click
className={selectedItem === item ? "selected-row" : ""}
>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{getSubcategoryName(item.subcategory)}</td>
<td>{item.amount}</td>
<td>{item.limit}</td>
<td>{item.description}</td>
<td>{item.timestampE}</td>
<td>{item.timestampR}</td>
</tr>
))}
</tbody>
</table>
{selectedItem && (
<p>Selected Row: {selectedItem.name}</p>
)}
{selectedSubcategory && (
<p>Sorted by Subcategory: {selectedSubcategory.name}</p>
)}
</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={50}>
<ResizablePanelGroup direction="vertical">
<ResizablePanel defaultSize={25}>
<div className="flex-wrap h-full items-center justify-center p-full">
{subcategories.map((subcategory) => (
<Button variant="custom"
key={subcategory.id}
onClick={() => handleSortBySubcategory(subcategory)}
>
{subcategory.name}
</Button>
))}
<Button variant="custom" onClick={handleViewAll}>View All</Button>
</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={75}>
<div className="flex h-full justify-center p-full">
{selectedItem ? (
<>
<div>
<p>Selected Row: {selectedItem.name}</p>
<p>Amount: {selectedItem.amount}</p>
{/* Add a button to increment amount */}
<Button onClick={handleIncrementAmount}>+</Button>
<Button onClick={handleDecrementAmount}>-</Button>
</div>
</>
) : null}
</div>
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
</ResizablePanelGroup>
);
};
export default StockPage;
Top comments (0)