feat: Add 'mine' filter to ProjectListPage and update translations
This commit is contained in:
@@ -12,16 +12,19 @@ import SearchBar from "@/components/ui/SearchBar";
|
|||||||
import { LoadingState } from "@/components/ui/States";
|
import { LoadingState } from "@/components/ui/States";
|
||||||
import { formatDate } from "@/lib/utils";
|
import { formatDate } from "@/lib/utils";
|
||||||
import { useTranslation } from "@/lib/i18n";
|
import { useTranslation } from "@/lib/i18n";
|
||||||
|
import { useSession } from "next-auth/react";
|
||||||
|
|
||||||
export default function ProjectListPage() {
|
export default function ProjectListPage() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { data: session } = useSession();
|
||||||
const [projects, setProjects] = useState([]);
|
const [projects, setProjects] = useState([]);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const [filteredProjects, setFilteredProjects] = useState([]);
|
const [filteredProjects, setFilteredProjects] = useState([]);
|
||||||
const [filters, setFilters] = useState({
|
const [filters, setFilters] = useState({
|
||||||
status: 'all',
|
status: 'all',
|
||||||
type: 'all',
|
type: 'all',
|
||||||
customer: 'all'
|
customer: 'all',
|
||||||
|
mine: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const [customers, setCustomers] = useState([]);
|
const [customers, setCustomers] = useState([]);
|
||||||
@@ -63,6 +66,11 @@ export default function ProjectListPage() {
|
|||||||
filtered = filtered.filter(project => project.customer === filters.customer);
|
filtered = filtered.filter(project => project.customer === filters.customer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply mine filter
|
||||||
|
if (filters.mine && session?.user?.id) {
|
||||||
|
filtered = filtered.filter(project => project.assigned_to === session.user.id);
|
||||||
|
}
|
||||||
|
|
||||||
// Apply search term
|
// Apply search term
|
||||||
if (searchTerm.trim()) {
|
if (searchTerm.trim()) {
|
||||||
const searchLower = searchTerm.toLowerCase();
|
const searchLower = searchTerm.toLowerCase();
|
||||||
@@ -80,7 +88,7 @@ export default function ProjectListPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setFilteredProjects(filtered);
|
setFilteredProjects(filtered);
|
||||||
}, [searchTerm, projects, filters]);
|
}, [searchTerm, projects, filters, session]);
|
||||||
|
|
||||||
async function handleDelete(id) {
|
async function handleDelete(id) {
|
||||||
const confirmed = confirm(t('projects.deleteConfirm'));
|
const confirmed = confirm(t('projects.deleteConfirm'));
|
||||||
@@ -109,7 +117,8 @@ export default function ProjectListPage() {
|
|||||||
setFilters({
|
setFilters({
|
||||||
status: 'all',
|
status: 'all',
|
||||||
type: 'all',
|
type: 'all',
|
||||||
customer: 'all'
|
customer: 'all',
|
||||||
|
mine: false
|
||||||
});
|
});
|
||||||
setSearchTerm('');
|
setSearchTerm('');
|
||||||
};
|
};
|
||||||
@@ -118,13 +127,14 @@ export default function ProjectListPage() {
|
|||||||
setFiltersExpanded(!filtersExpanded);
|
setFiltersExpanded(!filtersExpanded);
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasActiveFilters = filters.status !== 'all' || filters.type !== 'all' || filters.customer !== 'all' || searchTerm.trim() !== '';
|
const hasActiveFilters = filters.status !== 'all' || filters.type !== 'all' || filters.customer !== 'all' || filters.mine || searchTerm.trim() !== '';
|
||||||
|
|
||||||
const getActiveFilterCount = () => {
|
const getActiveFilterCount = () => {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
if (filters.status !== 'all') count++;
|
if (filters.status !== 'all') count++;
|
||||||
if (filters.type !== 'all') count++;
|
if (filters.type !== 'all') count++;
|
||||||
if (filters.customer !== 'all') count++;
|
if (filters.customer !== 'all') count++;
|
||||||
|
if (filters.mine) count++;
|
||||||
if (searchTerm.trim()) count++;
|
if (searchTerm.trim()) count++;
|
||||||
return count;
|
return count;
|
||||||
};
|
};
|
||||||
@@ -170,6 +180,29 @@ export default function ProjectListPage() {
|
|||||||
{t('projects.mapView') || 'Widok mapy'}
|
{t('projects.mapView') || 'Widok mapy'}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
|
{session?.user && (
|
||||||
|
<Button
|
||||||
|
variant={filters.mine ? "primary" : "outline"}
|
||||||
|
size="lg"
|
||||||
|
className="w-full sm:w-auto"
|
||||||
|
onClick={() => handleFilterChange('mine', !filters.mine)}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="w-5 h-5 mr-2"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
{t('projects.mine') || 'Moje'}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Link href="/projects/new" className="w-full sm:w-auto">
|
<Link href="/projects/new" className="w-full sm:w-auto">
|
||||||
<Button variant="primary" size="lg" className="w-full">
|
<Button variant="primary" size="lg" className="w-full">
|
||||||
<svg
|
<svg
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ const translations = {
|
|||||||
view: "Wyświetl",
|
view: "Wyświetl",
|
||||||
clearSearch: "Wyczyść wyszukiwanie",
|
clearSearch: "Wyczyść wyszukiwanie",
|
||||||
filters:"Filtry",
|
filters:"Filtry",
|
||||||
|
clearAll: "Wyczyść",
|
||||||
clearAllFilters: "Wyczyść wszystkie filtry",
|
clearAllFilters: "Wyczyść wszystkie filtry",
|
||||||
sortBy: "Sortuj według",
|
sortBy: "Sortuj według",
|
||||||
days: "dni"
|
days: "dni"
|
||||||
@@ -162,6 +163,7 @@ const translations = {
|
|||||||
notFinished: "Nie zakończone",
|
notFinished: "Nie zakończone",
|
||||||
projects: "projektów",
|
projects: "projektów",
|
||||||
mapView: "Widok mapy",
|
mapView: "Widok mapy",
|
||||||
|
mine: "Moje",
|
||||||
createFirstProject: "Utwórz pierwszy projekt",
|
createFirstProject: "Utwórz pierwszy projekt",
|
||||||
noMatchingResults: "Brak projektów pasujących do kryteriów wyszukiwania. Spróbuj zmienić wyszukiwane frazy.",
|
noMatchingResults: "Brak projektów pasujących do kryteriów wyszukiwania. Spróbuj zmienić wyszukiwane frazy.",
|
||||||
showingResults: "Wyświetlono {shown} z {total} projektów",
|
showingResults: "Wyświetlono {shown} z {total} projektów",
|
||||||
@@ -631,6 +633,7 @@ const translations = {
|
|||||||
view: "View",
|
view: "View",
|
||||||
clearSearch: "Clear search",
|
clearSearch: "Clear search",
|
||||||
filters: "Filters",
|
filters: "Filters",
|
||||||
|
clearAll: "Clear",
|
||||||
clearAllFilters: "Clear all filters",
|
clearAllFilters: "Clear all filters",
|
||||||
sortBy: "Sort by",
|
sortBy: "Sort by",
|
||||||
days: "days"
|
days: "days"
|
||||||
@@ -717,6 +720,7 @@ const translations = {
|
|||||||
notFinished: "Not finished",
|
notFinished: "Not finished",
|
||||||
projects: "projects",
|
projects: "projects",
|
||||||
mapView: "Map View",
|
mapView: "Map View",
|
||||||
|
mine: "Mine",
|
||||||
createFirstProject: "Create first project",
|
createFirstProject: "Create first project",
|
||||||
noMatchingResults: "No projects match the search criteria. Try changing your search terms.",
|
noMatchingResults: "No projects match the search criteria. Try changing your search terms.",
|
||||||
showingResults: "Showing {shown} of {total} projects",
|
showingResults: "Showing {shown} of {total} projects",
|
||||||
|
|||||||
Reference in New Issue
Block a user