Location Ledger Copy this Tailwind Component 0to Your Project
Import { Card, MainLayout, Table, TableHeader } from "@/shared"; import { useEffect, useState } from "react"; import { StockLocation } from "./types"; import { motion } from "framer motion"; const headers: TableHeader[] = [ { label: "Name", key: "name", }, { label: "Description", key: "description", }, { label: "Capacity", key: "capacity", }, ]; export const TestUiPAge: React.FC = () => { const [data, setData] = useState<StockLocation[]>([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { // Simulate loading data setTimeout(() => { setData([ { name: "Workshop", description: "The stock area of the factory", capacity: 100, }, { name: "Warehouse London", description: "The warehouse found in London", capacity: 150, }, ]); setIsLoading(false); }, 800); }, []); return ( <MainLayout> <div className="p 6 max w 7xl mx auto"> {/* Content area (no additional header) */} <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.5 }} className="mb 8" > <h1 className="text 2xl font bold text gray 800"> Storage Locations </h1> <p className="text gray 500"> Manage your inventory storage locations </p> </motion.div> {/* Stats cards */} <div className="grid grid cols 1 md:grid cols 3 gap 5 mb 8"> <motion.div className="transition all shadow md duration 300 transform hover: translate y 1 hover:shadow lg " initial={{ opacity: 0, scale: 0.9 }} animate={{ opacity: 1, scale: 1 }} transition={{ delay: 0.2, duration: 0.4 }} > <Card header={"Total Locations"}> <span className="block text 2xl font semibold text gray 800"> {data.length} </span> </Card> </motion.div> <motion.div className="bg white rounded lg p 5 shadow md border l 4 border green 500 hover:shadow lg transition all duration 300 transform hover: translate y 1" initial={{ opacity: 0, scale: 0.9 }} animate={{ opacity: 1, scale: 1 }} transition={{ delay: 0.3, duration: 0.4 }} > <span className="block text 2xl font semibold text gray 800"> {data.reduce( (sum, location) => sum + location.capacity, 0 )} </span> <span className="text sm text gray 500"> Total Capacity </span> </motion.div> <motion.div className="bg white rounded lg p 5 shadow md border l 4 border yellow 500 hover:shadow lg transition all duration 300 transform hover: translate y 1" initial={{ opacity: 0, scale: 0.9 }} animate={{ opacity: 1, scale: 1 }} transition={{ delay: 0.4, duration: 0.4 }} > <span className="block text 2xl font semibold text gray 800"> {data.length > 0 ? Math.round( data.reduce( (sum, location) => sum + location.capacity, 0 ) / data.length ) : 0} </span> <span className="text sm text gray 500"> Avg. Capacity </span> </motion.div> </div> {/* Table section */} <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.5, duration: 0.5 }} className="bg white rounded lg shadow md p 6" > <div className="flex justify between items center mb 4"> <h2 className="text lg font medium text gray 800"> Location Details </h2> <button className="bg blue 500 hover:bg blue 600 text white px 4 py 2 rounded md text sm font medium transition colors duration 200"> + Add Location </button> </div> {isLoading ? ( <div className="flex flex col items center justify center py 10"> <div className="w 10 h 10 border 4 border gray 200 border l blue 500 rounded full animate spin mb 4"></div> <p className="text gray 500"> Loading locations... </p> </div> ) : ( <Table headers={headers} data={data}></Table> )} </motion.div> </div> </MainLayout> ); };