Files
003-fleet-management/biljeske/SKELETON_LIST_VIEW.md
2026-05-26 06:29:06 +00:00

114 lines
3.5 KiB
Markdown

## Skeleton za List View
```jsx
// src/components/common/UniversalList.jsx
import { h } from 'preact';
import { useEffect, useState } from 'preact/hooks';
import { useStore } from '@nanostores/preact';
import { getBaseUrl } from '../lib/nav';
import LoadingSpinner from './LoadingSpinner.jsx';
export default function UniversalList({ store, setter, fetchMethod, limit, baseName, children }) {
const [loading, setLoading] = useState(true);
const list = useStore(store);
// Ako je baseName poslan, dohvati URL, inače ostavi undefined
const baseUrl = baseName ? getBaseUrl(baseName) : undefined;
useEffect(() => {
async function fetchData() {
if (list.length > 0) {
setLoading(false);
return;
}
try {
setLoading(true);
const data = await fetchMethod();
setter(data || []);
} catch (error) {
console.error("Greška pri dohvatu:", error);
setter([]);
} finally {
setTimeout(() => setLoading(false), 1000);
}
}
fetchData();
}, []);
if (loading) return <LoadingSpinner text="Učitavanje..." />;
const displayList = limit ? list.slice(0, limit) : list;
return (
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{/* children funkcija sada prima item i opcionalni baseUrl */}
{displayList.map(item => children(item, baseUrl))}
</div>
);
}
```
## Loading komponenta
```jsx
// src/components/common/LoadingSpinner.jsx
import { h } from 'preact';
export default function LoadingSpinner({ text = "Učitavanje podataka..." }) {
return (
<div class="flex items-center justify-center p-12 text-gray-500">
<div class="animate-spin mr-3 h-5 w-5 border-2 border-gray-400 border-t-transparent rounded-full"></div>
{text}
</div>
);
}
```
## Komponenta FleetStrojeviLista.jsx koristi Skeleton
```jsx
/// src/components/fleet/FleetStrojeviLista.jsx
import { h } from 'preact';
import UniversalList from '../common/UniversalList.jsx';
import { strojevi, setStrojevi } from '../stores/fleetStore';
import { getStrojevi } from '../lib/api';
export default function FleetStrojeviLista({ limit = 10 }) {
return (
<UniversalList
store={strojevi}
setter={setStrojevi}
fetchMethod={getStrojevi}
baseName="Registrirani strojevi"
limit={limit}
>
{(s, baseUrl) => (
<div key={s.id} class="p-6 border border-gray-200 rounded-2xl bg-white shadow-sm hover:shadow-md transition-shadow">
<div class="flex justify-between items-start mb-4">
<h3 class="text-xl font-black text-gray-900">{s.naziv}</h3>
<span class="px-2 py-1 bg-blue-100 text-blue-800 text-xs font-bold rounded-full uppercase">
{s.tip_human_readable}
</span>
</div>
<ul class="text-sm text-gray-600 space-y-1 mb-4">
<li><strong>Marka/Model:</strong> {s.marka} {s.model_stroja}</li>
<li><strong>Serijski br:</strong> {s.serijski_broj}</li>
<li><strong>Vlasnik:</strong> {s.vlasnik_naziv}</li>
<li><strong>Radni sati:</strong> {s.radni_sati} h</li>
{s.registracija && <li><strong>Reg:</strong> {s.registracija}</li>}
</ul>
<a
href={`${baseUrl}/${s.id}`}
class="block text-center w-full py-2 bg-gray-900 text-white rounded-lg hover:bg-gray-700 transition"
>
Pregled detalja
</a>
</div>
)}
</UniversalList>
);
}
```