Refactor Project Tasks and Task Templates pages with new UI components
- Introduced PageContainer and PageHeader components for consistent layout. - Added SearchBar and FilterBar components for improved task filtering and searching. - Implemented LoadingState component for better loading indication. - Updated ProjectTasksPage to utilize new components and enhance user experience. - Refactored TaskTemplatesPage to use PageContainer and PageHeader for better structure. - Created FilterBar component to manage filter options dynamically. - Added SearchBar component for searching tasks with clear functionality. - Introduced States component for loading and error states.
This commit is contained in:
@@ -5,6 +5,11 @@ import Link from "next/link";
|
||||
import { Card, CardHeader, CardContent } from "@/components/ui/Card";
|
||||
import Button from "@/components/ui/Button";
|
||||
import Badge from "@/components/ui/Badge";
|
||||
import PageContainer from "@/components/ui/PageContainer";
|
||||
import PageHeader from "@/components/ui/PageHeader";
|
||||
import SearchBar from "@/components/ui/SearchBar";
|
||||
import FilterBar from "@/components/ui/FilterBar";
|
||||
import { LoadingState } from "@/components/ui/States";
|
||||
|
||||
export default function ContractsMainPage() {
|
||||
const [contracts, setContracts] = useState([]);
|
||||
@@ -162,37 +167,75 @@ export default function ContractsMainPage() {
|
||||
};
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="p-6 max-w-7xl mx-auto">
|
||||
<div className="text-center">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto"></div>
|
||||
<p className="mt-2 text-gray-600">Ładowanie umów...</p>
|
||||
</div>
|
||||
</div>
|
||||
<PageContainer>
|
||||
<PageHeader
|
||||
title="Umowy"
|
||||
description="Zarządzaj swoimi umowami i kontraktami"
|
||||
>
|
||||
<Link href="/contracts/new">
|
||||
<Button variant="primary" size="lg">
|
||||
<span className="mr-2">➕</span>
|
||||
Nowa umowa
|
||||
</Button>
|
||||
</Link>
|
||||
</PageHeader>
|
||||
<LoadingState message="Ładowanie umów..." />
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
const stats = getContractStats();
|
||||
|
||||
const filterOptions = [
|
||||
{
|
||||
label: "Status",
|
||||
value: statusFilter,
|
||||
onChange: (e) => setStatusFilter(e.target.value),
|
||||
options: [
|
||||
{ value: "all", label: "Wszystkie" },
|
||||
{ value: "active", label: "Aktywne" },
|
||||
{ value: "completed", label: "Zakończone" },
|
||||
{ value: "no_end_date", label: "Bez daty końca" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Sortuj według",
|
||||
value: sortBy,
|
||||
onChange: (e) => setSortBy(e.target.value),
|
||||
options: [
|
||||
{ value: "contract_number", label: "Numer umowy" },
|
||||
{ value: "contract_name", label: "Nazwa umowy" },
|
||||
{ value: "customer", label: "Klient" },
|
||||
{ value: "start_date", label: "Data rozpoczęcia" },
|
||||
{ value: "finish_date", label: "Data zakończenia" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Kolejność",
|
||||
value: sortOrder,
|
||||
onChange: (e) => setSortOrder(e.target.value),
|
||||
options: [
|
||||
{ value: "asc", label: "Rosnąco" },
|
||||
{ value: "desc", label: "Malejąco" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="p-6 max-w-7xl mx-auto space-y-6">
|
||||
{/* Header */}
|
||||
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900">Umowy</h1>
|
||||
<p className="text-gray-600 mt-1">
|
||||
Zarządzaj swoimi umowami i kontraktami
|
||||
</p>
|
||||
</div>{" "}
|
||||
<Link
|
||||
href="/contracts/new"
|
||||
className="inline-flex items-center justify-center px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
|
||||
>
|
||||
<span className="mr-2">➕</span>
|
||||
Nowa umowa
|
||||
</Link>
|
||||
</div>
|
||||
<PageContainer>
|
||||
<PageHeader
|
||||
title="Umowy"
|
||||
description="Zarządzaj swoimi umowami i kontraktami"
|
||||
>
|
||||
<Link href="/contracts/new">
|
||||
<Button variant="primary" size="lg">
|
||||
<span className="mr-2">➕</span>
|
||||
Nowa umowa
|
||||
</Button>
|
||||
</Link>{" "}
|
||||
</PageHeader>
|
||||
{/* Statistics Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
|
||||
<Card>
|
||||
<CardContent className="p-4">
|
||||
<div className="flex items-center">
|
||||
@@ -302,93 +345,17 @@ export default function ContractsMainPage() {
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</CardContent>{" "}
|
||||
</Card>
|
||||
</div>
|
||||
{/* Filters and Search */}
|
||||
<Card>
|
||||
<CardContent className="p-4">
|
||||
<div className="flex flex-col lg:flex-row gap-4">
|
||||
{/* Search */}
|
||||
<div className="flex-1">
|
||||
<label
|
||||
htmlFor="search"
|
||||
className="block text-sm font-medium text-gray-700 mb-1"
|
||||
>
|
||||
Wyszukaj
|
||||
</label>
|
||||
<input
|
||||
id="search"
|
||||
type="text"
|
||||
placeholder="Szukaj po numerze, nazwie, kliencie lub inwestorze..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Status Filter */}
|
||||
<div className="w-full lg:w-48">
|
||||
<label
|
||||
htmlFor="status"
|
||||
className="block text-sm font-medium text-gray-700 mb-1"
|
||||
>
|
||||
Status
|
||||
</label>
|
||||
<select
|
||||
id="status"
|
||||
value={statusFilter}
|
||||
onChange={(e) => setStatusFilter(e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||
>
|
||||
<option value="all">Wszystkie</option>
|
||||
<option value="active">Aktywne</option>
|
||||
<option value="completed">Zakończone</option>
|
||||
<option value="no_end_date">W trakcie</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Sort */}
|
||||
<div className="w-full lg:w-48">
|
||||
<label
|
||||
htmlFor="sort"
|
||||
className="block text-sm font-medium text-gray-700 mb-1"
|
||||
>
|
||||
Sortuj według
|
||||
</label>
|
||||
<select
|
||||
id="sort"
|
||||
value={`${sortBy}-${sortOrder}`}
|
||||
onChange={(e) => {
|
||||
const [field, order] = e.target.value.split("-");
|
||||
setSortBy(field);
|
||||
setSortOrder(order);
|
||||
}}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||
>
|
||||
<option value="contract_number-asc">Numer umowy (A-Z)</option>
|
||||
<option value="contract_number-desc">Numer umowy (Z-A)</option>
|
||||
<option value="contract_name-asc">Nazwa (A-Z)</option>
|
||||
<option value="contract_name-desc">Nazwa (Z-A)</option>
|
||||
<option value="customer-asc">Klient (A-Z)</option>
|
||||
<option value="customer-desc">Klient (Z-A)</option>
|
||||
<option value="date_signed-desc">
|
||||
Data zawarcia (najnowsze)
|
||||
</option>
|
||||
<option value="date_signed-asc">
|
||||
Data zawarcia (najstarsze)
|
||||
</option>
|
||||
<option value="finish_date-desc">
|
||||
Data zakończenia (najnowsze)
|
||||
</option>
|
||||
<option value="finish_date-asc">
|
||||
Data zakończenia (najstarsze)
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>{" "}
|
||||
<SearchBar
|
||||
searchTerm={searchTerm}
|
||||
onSearchChange={handleSearchChange}
|
||||
placeholder="Szukaj umów po numerze, nazwie, kliencie lub inwestorze..."
|
||||
resultsCount={filteredContracts.length}
|
||||
resultsText="umów"
|
||||
/>
|
||||
<FilterBar filters={filterOptions} className="mb-6" />{" "}
|
||||
{/* Contracts List */}
|
||||
{filteredContracts.length === 0 ? (
|
||||
<Card>
|
||||
@@ -624,9 +591,9 @@ export default function ContractsMainPage() {
|
||||
Wyczyść filtry
|
||||
</button>
|
||||
)}
|
||||
</p>
|
||||
</p>{" "}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user