feat: actualizar carpeta dist probada en XAMPP y modulos de edicion de tiempo y persistencia UI
This commit is contained in:
+127
-14
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
ChevronDown,
|
||||
ChevronLeft,
|
||||
@@ -69,6 +69,73 @@ const EMPTY_ADVANCED_FILTERS: AdvancedFilters = {
|
||||
cm: "",
|
||||
};
|
||||
|
||||
const DEFAULT_PAGE_BY_FILTER: Record<BoardView, number> = {
|
||||
nuevos: 1,
|
||||
todos: 1,
|
||||
abiertos: 1,
|
||||
cerrados: 1,
|
||||
no_aprobados: 1,
|
||||
};
|
||||
|
||||
const BOARD_UI_STATE_KEY = "tablero-cdc:ui-state:v1";
|
||||
|
||||
type PersistedBoardUiState = {
|
||||
query: string;
|
||||
filter: BoardView;
|
||||
advancedFilters: AdvancedFilters;
|
||||
pageByFilter: Record<BoardView, number>;
|
||||
tariffManagerOpen: boolean;
|
||||
listManagerOpen: boolean;
|
||||
scrollY: number;
|
||||
};
|
||||
|
||||
function loadBoardUiState(): PersistedBoardUiState {
|
||||
const fallback: PersistedBoardUiState = {
|
||||
query: "",
|
||||
filter: "todos",
|
||||
advancedFilters: EMPTY_ADVANCED_FILTERS,
|
||||
pageByFilter: DEFAULT_PAGE_BY_FILTER,
|
||||
tariffManagerOpen: false,
|
||||
listManagerOpen: false,
|
||||
scrollY: 0,
|
||||
};
|
||||
|
||||
if (typeof window === "undefined") return fallback;
|
||||
|
||||
try {
|
||||
const raw = window.localStorage.getItem(BOARD_UI_STATE_KEY);
|
||||
if (!raw) return fallback;
|
||||
const parsed = JSON.parse(raw) as Partial<PersistedBoardUiState>;
|
||||
const validFilters: BoardView[] = ["nuevos", "todos", "abiertos", "cerrados", "no_aprobados"];
|
||||
const nextFilter = validFilters.includes(parsed.filter as BoardView)
|
||||
? (parsed.filter as BoardView)
|
||||
: fallback.filter;
|
||||
|
||||
return {
|
||||
query: typeof parsed.query === "string" ? parsed.query : fallback.query,
|
||||
filter: nextFilter,
|
||||
advancedFilters: {
|
||||
country: typeof parsed.advancedFilters?.country === "string" ? parsed.advancedFilters.country : "",
|
||||
brand: typeof parsed.advancedFilters?.brand === "string" ? parsed.advancedFilters.brand : "",
|
||||
client: typeof parsed.advancedFilters?.client === "string" ? parsed.advancedFilters.client : "",
|
||||
cm: typeof parsed.advancedFilters?.cm === "string" ? parsed.advancedFilters.cm : "",
|
||||
},
|
||||
pageByFilter: Object.fromEntries(
|
||||
Object.entries({ ...DEFAULT_PAGE_BY_FILTER, ...(parsed.pageByFilter || {}) }).map(([key, value]) => [
|
||||
key,
|
||||
Math.max(1, Math.floor(Number(value) || 1)),
|
||||
]),
|
||||
) as Record<BoardView, number>,
|
||||
tariffManagerOpen: parsed.tariffManagerOpen === true,
|
||||
listManagerOpen: parsed.listManagerOpen === true,
|
||||
scrollY: Number.isFinite(Number(parsed.scrollY)) ? Math.max(0, Number(parsed.scrollY)) : 0,
|
||||
};
|
||||
} catch (error) {
|
||||
console.warn("No se pudo restaurar la vista anterior del Tablero CDC:", error);
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
function initials(name: string | null | undefined, email: string | null | undefined): string {
|
||||
if (name) {
|
||||
const parts = name.trim().split(/\s+/);
|
||||
@@ -80,21 +147,18 @@ function initials(name: string | null | undefined, email: string | null | undefi
|
||||
}
|
||||
|
||||
export default function BoardPage() {
|
||||
const [initialUiState] = useState(loadBoardUiState);
|
||||
const hasMountedFilterReset = useRef(false);
|
||||
const hasRestoredScroll = useRef(initialUiState.scrollY <= 0);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [editing, setEditing] = useState<Project | null>(null);
|
||||
const [query, setQuery] = useState("");
|
||||
const [filter, setFilter] = useState<BoardView>("todos");
|
||||
const [advancedFilters, setAdvancedFilters] = useState<AdvancedFilters>(EMPTY_ADVANCED_FILTERS);
|
||||
const [pageByFilter, setPageByFilter] = useState<Record<BoardView, number>>({
|
||||
nuevos: 1,
|
||||
todos: 1,
|
||||
abiertos: 1,
|
||||
cerrados: 1,
|
||||
no_aprobados: 1,
|
||||
});
|
||||
const [query, setQuery] = useState(initialUiState.query);
|
||||
const [filter, setFilter] = useState<BoardView>(initialUiState.filter);
|
||||
const [advancedFilters, setAdvancedFilters] = useState<AdvancedFilters>(initialUiState.advancedFilters);
|
||||
const [pageByFilter, setPageByFilter] = useState<Record<BoardView, number>>(initialUiState.pageByFilter);
|
||||
const [deletingProjectId, setDeletingProjectId] = useState<string | null>(null);
|
||||
const [tariffManagerOpen, setTariffManagerOpen] = useState(false);
|
||||
const [listManagerOpen, setListManagerOpen] = useState(false);
|
||||
const [tariffManagerOpen, setTariffManagerOpen] = useState(initialUiState.tariffManagerOpen);
|
||||
const [listManagerOpen, setListManagerOpen] = useState(initialUiState.listManagerOpen);
|
||||
const [timeProject, setTimeProject] = useState<Project | null>(null);
|
||||
const [reviewingBriefId, setReviewingBriefId] = useState<string | null>(null);
|
||||
|
||||
@@ -185,16 +249,65 @@ export default function BoardPage() {
|
||||
const visibleEnd = Math.min(pageStart + PROJECTS_PER_PAGE, currentTotalItems);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasMountedFilterReset.current) {
|
||||
hasMountedFilterReset.current = true;
|
||||
return;
|
||||
}
|
||||
setPageByFilter((prev) => ({ ...prev, [filter]: 1 }));
|
||||
}, [
|
||||
query,
|
||||
filter,
|
||||
advancedFilters.country,
|
||||
advancedFilters.brand,
|
||||
advancedFilters.client,
|
||||
advancedFilters.cm,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const saveUiState = () => {
|
||||
try {
|
||||
const nextState: PersistedBoardUiState = {
|
||||
query,
|
||||
filter,
|
||||
advancedFilters,
|
||||
pageByFilter,
|
||||
tariffManagerOpen,
|
||||
listManagerOpen,
|
||||
scrollY: hasRestoredScroll.current ? window.scrollY : initialUiState.scrollY,
|
||||
};
|
||||
window.localStorage.setItem(BOARD_UI_STATE_KEY, JSON.stringify(nextState));
|
||||
} catch (error) {
|
||||
console.warn("No se pudo guardar la vista del Tablero CDC:", error);
|
||||
}
|
||||
};
|
||||
|
||||
saveUiState();
|
||||
const handlePageHide = () => saveUiState();
|
||||
const handleVisibilityChange = () => {
|
||||
if (document.visibilityState === "hidden") saveUiState();
|
||||
};
|
||||
|
||||
window.addEventListener("pagehide", handlePageHide);
|
||||
document.addEventListener("visibilitychange", handleVisibilityChange);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("pagehide", handlePageHide);
|
||||
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
||||
};
|
||||
}, [query, filter, advancedFilters, pageByFilter, tariffManagerOpen, listManagerOpen, initialUiState.scrollY]);
|
||||
|
||||
useEffect(() => {
|
||||
const savedScrollY = initialUiState.scrollY;
|
||||
const currentViewLoading = isBriefReviewView ? briefInbox.loading : loading;
|
||||
if (savedScrollY <= 0 || currentViewLoading || hasRestoredScroll.current) return;
|
||||
|
||||
const timer = window.setTimeout(() => {
|
||||
window.scrollTo({ top: savedScrollY, behavior: "auto" });
|
||||
hasRestoredScroll.current = true;
|
||||
}, 120);
|
||||
|
||||
return () => window.clearTimeout(timer);
|
||||
}, [initialUiState.scrollY, isBriefReviewView, briefInbox.loading, loading]);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentPage > totalPages) {
|
||||
setPageByFilter((prev) => ({ ...prev, [filter]: totalPages }));
|
||||
|
||||
Reference in New Issue
Block a user