<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="CopilotDiffPersistence">
    <option name="pendingDiffs">
      <map>
        <entry key="$PROJECT_DIR$/frontend/src/App.jsx">
          <value>
            <PendingDiffInfo>
              <option name="filePath" value="$PROJECT_DIR$/frontend/src/App.jsx" />
              <option name="originalContent" value="import { Navigate, Route, Routes } from &quot;react-router-dom&quot;;&#10;&#10;import LandingPage from &quot;./pages/LandingPage/LandingPage.jsx&quot;;&#10;import Login from &quot;./pages/Login/Login.jsx&quot;;&#10;import Register from &quot;./pages/Register/Register.jsx&quot;;&#10;import DashboardLayout from &quot;./pages/Dashboard/DashboardLayout.jsx&quot;;&#10;import ControlCenter from &quot;./pages/Dashboard/pages/ControlCenter/ControlCenter.jsx&quot;;&#10;import Training from &quot;./pages/Dashboard/pages/Training/Training.jsx&quot;;&#10;import TrainingTracking from &quot;./pages/Dashboard/pages/Training/TrainingTracking.jsx&quot;;&#10;import NewTrainingSession from &quot;./pages/Dashboard/pages/Training/NewTrainingSession.jsx&quot;;&#10;import Weight from &quot;./pages/Dashboard/pages/Weight/Weight.jsx&quot;;&#10;import WeightTracking from &quot;./pages/Dashboard/pages/Weight/WeightTracking.jsx&quot;;&#10;import NewWeightIntake from &quot;./pages/Dashboard/pages/Weight/NewWeightIntake.jsx&quot;;&#10;import Finance from &quot;./pages/Dashboard/pages/Finance/Finance.jsx&quot;;&#10;import FinanceTracking from &quot;./pages/Dashboard/pages/Finance/FinanceTracking.jsx&quot;;&#10;import NewIncome from &quot;./pages/Dashboard/pages/Finance/NewIncome.jsx&quot;;&#10;import Investing from &quot;./pages/Dashboard/pages/Investing/Investing.jsx&quot;;&#10;import InvestingTracking from &quot;./pages/Dashboard/pages/Investing/InvestingTracking.jsx&quot;;&#10;import NewInvestment from &quot;./pages/Dashboard/pages/Investing/NewInvestment.jsx&quot;;&#10;import Discipline from &quot;./pages/Dashboard/pages/Discipline/Discipline.jsx&quot;;&#10;import DisciplineTracking from &quot;./pages/Dashboard/pages/Discipline/DisciplineTracking.jsx&quot;;&#10;import CustomCategoryKanban from &quot;./pages/Dashboard/pages/CustomCategory/CustomCategoryKanban.jsx&quot;;&#10;&#10;function RequireAuth({ children }) {&#10;  const token = localStorage.getItem(&quot;authToken&quot;);&#10;  if (!token) return &lt;Navigate to=&quot;/login&quot; replace /&gt;;&#10;  return children;&#10;}&#10;&#10;function App() {&#10;  return (&#10;    &lt;div data-theme=&quot;forest&quot; className=&quot;min-h-screen w-full&quot;&gt;&#10;      &lt;Routes&gt;&#10;        &lt;Route path=&quot;/&quot; element={&lt;LandingPage /&gt;} /&gt;&#10;        &lt;Route path=&quot;/login&quot; element={&lt;Login /&gt;} /&gt;&#10;        &lt;Route path=&quot;/register&quot; element={&lt;Register /&gt;} /&gt;&#10;        &lt;Route&#10;          path=&quot;/dashboard&quot;&#10;          element={&#10;            &lt;RequireAuth&gt;&#10;              &lt;DashboardLayout /&gt;&#10;            &lt;/RequireAuth&gt;&#10;          }&#10;        &gt;&#10;          &lt;Route index element={&lt;Navigate to=&quot;control-center&quot; replace /&gt;} /&gt;&#10;          &lt;Route path=&quot;control-center&quot; element={&lt;ControlCenter /&gt;} /&gt;&#10;          &lt;Route path=&quot;training&quot; element={&lt;Training /&gt;} /&gt;&#10;          &lt;Route path=&quot;training/tracking&quot; element={&lt;TrainingTracking /&gt;} /&gt;&#10;          &lt;Route&#10;            path=&quot;training/sessions/new&quot;&#10;            element={&lt;NewTrainingSession /&gt;}&#10;          /&gt;&#10;          &lt;Route path=&quot;weight&quot; element={&lt;Weight /&gt;} /&gt;&#10;          &lt;Route path=&quot;weight/tracking&quot; element={&lt;WeightTracking /&gt;} /&gt;&#10;          &lt;Route path=&quot;weight/intakes/new&quot; element={&lt;NewWeightIntake /&gt;} /&gt;&#10;          &lt;Route path=&quot;finance&quot; element={&lt;Finance /&gt;} /&gt;&#10;           &lt;Route path=&quot;finance/tracking&quot; element={&lt;FinanceTracking /&gt;} /&gt;&#10;           &lt;Route path=&quot;finance/incomes/new&quot; element={&lt;NewIncome /&gt;} /&gt;&#10;          &lt;Route path=&quot;investing&quot; element={&lt;Investing /&gt;} /&gt;&#10;          &lt;Route path=&quot;investing/tracking&quot; element={&lt;InvestingTracking /&gt;} /&gt;&#10;          &lt;Route path=&quot;investing/assets/new&quot; element={&lt;NewInvestment /&gt;} /&gt;&#10;          &lt;Route path=&quot;discipline&quot; element={&lt;Discipline /&gt;} /&gt;&#10;           &lt;Route path=&quot;discipline/tracking&quot; element={&lt;DisciplineTracking /&gt;} /&gt;&#10;           &lt;Route path=&quot;custom/:customTrackingId&quot; element={&lt;CustomCategoryKanban /&gt;} /&gt;&#10;        &lt;/Route&gt;&#10;        &lt;Route path=&quot;*&quot; element={&lt;Navigate to=&quot;/&quot; replace /&gt;} /&gt;&#10;      &lt;/Routes&gt;&#10;    &lt;/div&gt;&#10;  );&#10;}&#10;&#10;export default App;&#10;" />
              <option name="updatedContent" value="import { Navigate, Route, Routes } from &quot;react-router-dom&quot;;&#10;import { clearAuthSession, getAuthToken, isTokenExpired } from &quot;./utils/authSession&quot;;&#10;&#10;import LandingPage from &quot;./pages/LandingPage/LandingPage.jsx&quot;;&#10;import Login from &quot;./pages/Login/Login.jsx&quot;;&#10;import Register from &quot;./pages/Register/Register.jsx&quot;;&#10;import DashboardLayout from &quot;./pages/Dashboard/DashboardLayout.jsx&quot;;&#10;import ControlCenter from &quot;./pages/Dashboard/pages/ControlCenter/ControlCenter.jsx&quot;;&#10;import Training from &quot;./pages/Dashboard/pages/Training/Training.jsx&quot;;&#10;import TrainingTracking from &quot;./pages/Dashboard/pages/Training/TrainingTracking.jsx&quot;;&#10;import NewTrainingSession from &quot;./pages/Dashboard/pages/Training/NewTrainingSession.jsx&quot;;&#10;import Weight from &quot;./pages/Dashboard/pages/Weight/Weight.jsx&quot;;&#10;import WeightTracking from &quot;./pages/Dashboard/pages/Weight/WeightTracking.jsx&quot;;&#10;import NewWeightIntake from &quot;./pages/Dashboard/pages/Weight/NewWeightIntake.jsx&quot;;&#10;import Finance from &quot;./pages/Dashboard/pages/Finance/Finance.jsx&quot;;&#10;import FinanceTracking from &quot;./pages/Dashboard/pages/Finance/FinanceTracking.jsx&quot;;&#10;import NewIncome from &quot;./pages/Dashboard/pages/Finance/NewIncome.jsx&quot;;&#10;import Investing from &quot;./pages/Dashboard/pages/Investing/Investing.jsx&quot;;&#10;import InvestingTracking from &quot;./pages/Dashboard/pages/Investing/InvestingTracking.jsx&quot;;&#10;import NewInvestment from &quot;./pages/Dashboard/pages/Investing/NewInvestment.jsx&quot;;&#10;import Discipline from &quot;./pages/Dashboard/pages/Discipline/Discipline.jsx&quot;;&#10;import DisciplineTracking from &quot;./pages/Dashboard/pages/Discipline/DisciplineTracking.jsx&quot;;&#10;import CustomCategoryKanban from &quot;./pages/Dashboard/pages/CustomCategory/CustomCategoryKanban.jsx&quot;;&#10;&#10;function RequireAuth({ children }) {&#10;  const token = getAuthToken();&#10;  if (token &amp;&amp; isTokenExpired(token)) {&#10;    clearAuthSession();&#10;    return &lt;Navigate to=&quot;/login&quot; replace /&gt;;&#10;  }&#10;  if (!token) return &lt;Navigate to=&quot;/login&quot; replace /&gt;;&#10;  return children;&#10;}&#10;&#10;function App() {&#10;  return (&#10;    &lt;div data-theme=&quot;forest&quot; className=&quot;min-h-screen w-full&quot;&gt;&#10;      &lt;Routes&gt;&#10;        &lt;Route path=&quot;/&quot; element={&lt;LandingPage /&gt;} /&gt;&#10;        &lt;Route path=&quot;/login&quot; element={&lt;Login /&gt;} /&gt;&#10;        &lt;Route path=&quot;/register&quot; element={&lt;Register /&gt;} /&gt;&#10;        &lt;Route&#10;          path=&quot;/dashboard&quot;&#10;          element={&#10;            &lt;RequireAuth&gt;&#10;              &lt;DashboardLayout /&gt;&#10;            &lt;/RequireAuth&gt;&#10;          }&#10;        &gt;&#10;          &lt;Route index element={&lt;Navigate to=&quot;control-center&quot; replace /&gt;} /&gt;&#10;          &lt;Route path=&quot;control-center&quot; element={&lt;ControlCenter /&gt;} /&gt;&#10;          &lt;Route path=&quot;training&quot; element={&lt;Training /&gt;} /&gt;&#10;          &lt;Route path=&quot;training/tracking&quot; element={&lt;TrainingTracking /&gt;} /&gt;&#10;          &lt;Route&#10;            path=&quot;training/sessions/new&quot;&#10;            element={&lt;NewTrainingSession /&gt;}&#10;          /&gt;&#10;          &lt;Route path=&quot;weight&quot; element={&lt;Weight /&gt;} /&gt;&#10;          &lt;Route path=&quot;weight/tracking&quot; element={&lt;WeightTracking /&gt;} /&gt;&#10;          &lt;Route path=&quot;weight/intakes/new&quot; element={&lt;NewWeightIntake /&gt;} /&gt;&#10;          &lt;Route path=&quot;finance&quot; element={&lt;Finance /&gt;} /&gt;&#10;           &lt;Route path=&quot;finance/tracking&quot; element={&lt;FinanceTracking /&gt;} /&gt;&#10;           &lt;Route path=&quot;finance/incomes/new&quot; element={&lt;NewIncome /&gt;} /&gt;&#10;          &lt;Route path=&quot;investing&quot; element={&lt;Investing /&gt;} /&gt;&#10;          &lt;Route path=&quot;investing/tracking&quot; element={&lt;InvestingTracking /&gt;} /&gt;&#10;          &lt;Route path=&quot;investing/assets/new&quot; element={&lt;NewInvestment /&gt;} /&gt;&#10;          &lt;Route path=&quot;discipline&quot; element={&lt;Discipline /&gt;} /&gt;&#10;           &lt;Route path=&quot;discipline/tracking&quot; element={&lt;DisciplineTracking /&gt;} /&gt;&#10;           &lt;Route path=&quot;custom/:customTrackingId&quot; element={&lt;CustomCategoryKanban /&gt;} /&gt;&#10;        &lt;/Route&gt;&#10;        &lt;Route path=&quot;*&quot; element={&lt;Navigate to=&quot;/&quot; replace /&gt;} /&gt;&#10;      &lt;/Routes&gt;&#10;    &lt;/div&gt;&#10;  );&#10;}&#10;&#10;export default App;&#10;" />
            </PendingDiffInfo>
          </value>
        </entry>
        <entry key="$PROJECT_DIR$/frontend/src/api/axios.js">
          <value>
            <PendingDiffInfo>
              <option name="filePath" value="$PROJECT_DIR$/frontend/src/api/axios.js" />
              <option name="originalContent" value="import axios from &quot;axios&quot;;&#10;&#10;const api = axios.create({&#10;  baseURL: import.meta.env.VITE_API_BASE_URL ?? &quot;http://localhost:8080/api&quot;,&#10;});&#10;&#10;api.interceptors.request.use((config) =&gt; {&#10;  const token = localStorage.getItem(&quot;authToken&quot;);&#10;  if (token) {&#10;    config.headers = config.headers ?? {};&#10;    config.headers.Authorization = `Bearer ${token}`;&#10;  }&#10;  return config;&#10;});&#10;&#10;export default api;" />
              <option name="updatedContent" value="import axios from &quot;axios&quot;;&#10;import { getAuthToken, isTokenExpired, logoutAndRedirect } from &quot;../utils/authSession&quot;;&#10;&#10;const api = axios.create({&#10;  baseURL: import.meta.env.VITE_API_BASE_URL ?? &quot;http://localhost:8080/api&quot;,&#10;});&#10;&#10;api.interceptors.request.use((config) =&gt; {&#10;  const token = getAuthToken();&#10;  if (token) {&#10;    if (isTokenExpired(token)) {&#10;      logoutAndRedirect(&quot;/dashboard&quot;);&#10;      return Promise.reject(new Error(&quot;Authentication session expired&quot;));&#10;    }&#10;    config.headers = config.headers ?? {};&#10;    config.headers.Authorization = `Bearer ${token}`;&#10;  }&#10;  return config;&#10;});&#10;&#10;api.interceptors.response.use(&#10;  (response) =&gt; response,&#10;  (error) =&gt; {&#10;    const status = error?.response?.status;&#10;    if (status === 401 || status === 403) {&#10;      logoutAndRedirect(&quot;/dashboard&quot;);&#10;    }&#10;    return Promise.reject(error);&#10;  },&#10;);&#10;&#10;export default api;" />
            </PendingDiffInfo>
          </value>
        </entry>
        <entry key="$PROJECT_DIR$/frontend/src/pages/Dashboard/DashboardLayout.jsx">
          <value>
            <PendingDiffInfo>
              <option name="filePath" value="$PROJECT_DIR$/frontend/src/pages/Dashboard/DashboardLayout.jsx" />
              <option name="originalContent" value="import React, { useMemo } from &quot;react&quot;;&#10;import { Outlet, useNavigate } from &quot;react-router-dom&quot;;&#10;&#10;import { SidebarInset, SidebarProvider } from &quot;@relume_io/relume-ui&quot;;&#10;&#10;import DashboardSidebar from &quot;./components/DashboardSidebar.jsx&quot;;&#10;import DashboardTopbar from &quot;./components/DashboardTopbar.jsx&quot;;&#10;&#10;const DashboardLayout = () =&gt; {&#10;  const navigate = useNavigate();&#10;&#10;  const user = useMemo(() =&gt; {&#10;    try {&#10;      const raw = localStorage.getItem(&quot;authUser&quot;);&#10;      return raw ? JSON.parse(raw) : null;&#10;    } catch {&#10;      return null;&#10;    }&#10;  }, []);&#10;&#10;  const username = user?.username ?? &quot;&quot;;&#10;&#10;  const onLogout = () =&gt; {&#10;    localStorage.removeItem(&quot;authToken&quot;);&#10;    localStorage.removeItem(&quot;authUser&quot;);&#10;    navigate(&quot;/&quot;, { replace: true });&#10;  };&#10;&#10;  return (&#10;    &lt;SidebarProvider&gt;&#10;      {/* App shell background */}&#10;      &lt;div className=&quot;pointer-events-none fixed inset-0 -z-10&quot;&gt;&#10;        &lt;div className=&quot;absolute inset-0 bg-base-300/10&quot; /&gt;&#10;        &lt;div className=&quot;absolute inset-0 bg-radial-[circle_at_20%_20%] from-green-400/10 via-transparent to-transparent&quot; /&gt;&#10;        &lt;div className=&quot;absolute inset-0 bg-radial-[circle_at_80%_30%] from-blue-400/10 via-transparent to-transparent&quot; /&gt;&#10;        &lt;div className=&quot;absolute inset-0 bg-linear-to-b from-black/10 via-transparent to-black/25&quot; /&gt;&#10;      &lt;/div&gt;&#10;&#10;      &lt;DashboardSidebar /&gt;&#10;&#10;      &lt;SidebarInset className=&quot;pt-16 lg:pt-0&quot;&gt;&#10;        &lt;DashboardTopbar username={username} onLogout={onLogout} /&gt;&#10;&#10;        &lt;div className=&quot;h-[calc(100vh-4rem)] overflow-auto&quot;&gt;&#10;          &lt;div className=&quot;mx-auto w-full max-w-7xl px-4 py-6 sm:px-6 sm:py-8 lg:px-8 lg:py-10&quot;&gt;&#10;            &lt;div className=&quot;rounded-3xl border border-white/10 bg-base-100/60 shadow-[0_0_0_1px_rgba(255,255,255,0.04),0_24px_90px_rgba(0,0,0,0.35)] backdrop-blur-xl&quot;&gt;&#10;              &lt;div className=&quot;p-4 sm:p-6 lg:p-8&quot;&gt;&#10;                &lt;Outlet /&gt;&#10;              &lt;/div&gt;&#10;            &lt;/div&gt;&#10;          &lt;/div&gt;&#10;        &lt;/div&gt;&#10;      &lt;/SidebarInset&gt;&#10;    &lt;/SidebarProvider&gt;&#10;  );&#10;};&#10;&#10;export default DashboardLayout;&#10;" />
              <option name="updatedContent" value="import React, { useMemo } from &quot;react&quot;;&#10;import { Outlet, useNavigate } from &quot;react-router-dom&quot;;&#10;&#10;import { SidebarInset, SidebarProvider } from &quot;@relume_io/relume-ui&quot;;&#10;&#10;import DashboardSidebar from &quot;./components/DashboardSidebar.jsx&quot;;&#10;import DashboardTopbar from &quot;./components/DashboardTopbar.jsx&quot;;&#10;import { clearAuthSession } from &quot;../../utils/authSession&quot;;&#10;&#10;const DashboardLayout = () =&gt; {&#10;  const navigate = useNavigate();&#10;&#10;  const user = useMemo(() =&gt; {&#10;    try {&#10;      const raw = localStorage.getItem(&quot;authUser&quot;);&#10;      return raw ? JSON.parse(raw) : null;&#10;    } catch {&#10;      return null;&#10;    }&#10;  }, []);&#10;&#10;  const username = user?.username ?? &quot;&quot;;&#10;&#10;  const onLogout = () =&gt; {&#10;    clearAuthSession();&#10;    navigate(&quot;/&quot;, { replace: true });&#10;  };&#10;&#10;  return (&#10;    &lt;SidebarProvider&gt;&#10;      {/* App shell background */}&#10;      &lt;div className=&quot;pointer-events-none fixed inset-0 -z-10&quot;&gt;&#10;        &lt;div className=&quot;absolute inset-0 bg-base-300/10&quot; /&gt;&#10;        &lt;div className=&quot;absolute inset-0 bg-radial-[circle_at_20%_20%] from-green-400/10 via-transparent to-transparent&quot; /&gt;&#10;        &lt;div className=&quot;absolute inset-0 bg-radial-[circle_at_80%_30%] from-blue-400/10 via-transparent to-transparent&quot; /&gt;&#10;        &lt;div className=&quot;absolute inset-0 bg-linear-to-b from-black/10 via-transparent to-black/25&quot; /&gt;&#10;      &lt;/div&gt;&#10;&#10;      &lt;DashboardSidebar /&gt;&#10;&#10;      &lt;SidebarInset className=&quot;pt-16 lg:pt-0&quot;&gt;&#10;        &lt;DashboardTopbar username={username} onLogout={onLogout} /&gt;&#10;&#10;        &lt;div className=&quot;h-[calc(100vh-4rem)] overflow-auto&quot;&gt;&#10;          &lt;div className=&quot;mx-auto w-full max-w-7xl px-4 py-6 sm:px-6 sm:py-8 lg:px-8 lg:py-10&quot;&gt;&#10;            &lt;div className=&quot;rounded-3xl border border-white/10 bg-base-100/60 shadow-[0_0_0_1px_rgba(255,255,255,0.04),0_24px_90px_rgba(0,0,0,0.35)] backdrop-blur-xl&quot;&gt;&#10;              &lt;div className=&quot;p-4 sm:p-6 lg:p-8&quot;&gt;&#10;                &lt;Outlet /&gt;&#10;              &lt;/div&gt;&#10;            &lt;/div&gt;&#10;          &lt;/div&gt;&#10;        &lt;/div&gt;&#10;      &lt;/SidebarInset&gt;&#10;    &lt;/SidebarProvider&gt;&#10;  );&#10;};&#10;&#10;export default DashboardLayout;&#10;" />
            </PendingDiffInfo>
          </value>
        </entry>
        <entry key="$PROJECT_DIR$/frontend/src/utils/authSession.js">
          <value>
            <PendingDiffInfo>
              <option name="filePath" value="$PROJECT_DIR$/frontend/src/utils/authSession.js" />
              <option name="updatedContent" value="export const AUTH_TOKEN_KEY = &quot;authToken&quot;;&#10;export const AUTH_USER_KEY = &quot;authUser&quot;;&#10;&#10;function decodeJwtPayload(token) {&#10;  try {&#10;    const parts = token.split(&quot;.&quot;);&#10;    if (parts.length &lt; 2) return null;&#10;    const base64 = parts[1].replace(/-/g, &quot;+&quot;).replace(/_/g, &quot;/&quot;);&#10;    const normalized = base64.padEnd(Math.ceil(base64.length / 4) * 4, &quot;=&quot;);&#10;    const json = atob(normalized);&#10;    return JSON.parse(json);&#10;  } catch {&#10;    return null;&#10;  }&#10;}&#10;&#10;export function isTokenExpired(token) {&#10;  if (!token) return true;&#10;  const payload = decodeJwtPayload(token);&#10;  if (!payload || typeof payload.exp !== &quot;number&quot;) return true;&#10;  return payload.exp * 1000 &lt;= Date.now();&#10;}&#10;&#10;export function getAuthToken() {&#10;  return localStorage.getItem(AUTH_TOKEN_KEY);&#10;}&#10;&#10;export function clearAuthSession() {&#10;  localStorage.removeItem(AUTH_TOKEN_KEY);&#10;  localStorage.removeItem(AUTH_USER_KEY);&#10;}&#10;&#10;export function logoutAndRedirect(path = &quot;/dashboard&quot;) {&#10;  clearAuthSession();&#10;  window.location.assign(path);&#10;}&#10;" />
            </PendingDiffInfo>
          </value>
        </entry>
      </map>
    </option>
  </component>
</project>