This commit is contained in:
NotII
2025-03-24 16:53:19 +00:00
parent 11d32a2c46
commit 8534ed040c
3 changed files with 15 additions and 13 deletions

View File

@@ -4,7 +4,7 @@ import { useState, useEffect } from "react";
import Layout from "@/components/layout/layout"; import Layout from "@/components/layout/layout";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Plus, Pencil, Trash2, ChevronRight, ChevronDown, Loader2 } from "lucide-react"; import { Plus, Pencil, Trash2, ChevronRight, ChevronDown } from "lucide-react";
import { toast } from "sonner"; import { toast } from "sonner";
import { import {
Select, Select,
@@ -29,7 +29,6 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
export default function CategoriesPage() { export default function CategoriesPage() {
const [categories, setCategories] = useState<Category[]>([]); const [categories, setCategories] = useState<Category[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [newCategoryName, setNewCategoryName] = useState(""); const [newCategoryName, setNewCategoryName] = useState("");
const [selectedParentId, setSelectedParentId] = useState<string>(""); const [selectedParentId, setSelectedParentId] = useState<string>("");
const [editingCategory, setEditingCategory] = useState<Category | null>(null); const [editingCategory, setEditingCategory] = useState<Category | null>(null);
@@ -46,13 +45,10 @@ export default function CategoriesPage() {
const fetchCategories = async () => { const fetchCategories = async () => {
try { try {
setIsLoading(true);
const fetchedCategories = await apiRequest("/categories", "GET"); const fetchedCategories = await apiRequest("/categories", "GET");
setCategories(fetchedCategories); setCategories(fetchedCategories);
} catch (error) { } catch (error) {
toast.error("Failed to fetch categories"); toast.error("Failed to fetch categories");
} finally {
setIsLoading(false);
} }
}; };
@@ -247,11 +243,7 @@ export default function CategoriesPage() {
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="space-y-1"> <div className="space-y-1">
{isLoading ? ( {rootCategories.length === 0 ? (
<div className="flex items-center justify-center py-8">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
</div>
) : rootCategories.length === 0 ? (
<p className="text-sm text-muted-foreground text-center py-4"> <p className="text-sm text-muted-foreground text-center py-4">
No categories yet. Add your first category above. No categories yet. Add your first category above.
</p> </p>

View File

@@ -6,10 +6,17 @@
* Get the authentication token from cookies or localStorage * Get the authentication token from cookies or localStorage
*/ */
export function getAuthToken(): string | null { export function getAuthToken(): string | null {
return document.cookie const token = document.cookie
.split('; ') .split('; ')
.find(row => row.startsWith('Authorization=')) .find(row => row.startsWith('Authorization='))
?.split('=')[1] || localStorage.getItem('Authorization'); ?.split('=')[1] || localStorage.getItem('Authorization');
// If token exists but doesn't have Bearer prefix, add it
if (token && !token.startsWith('Bearer ')) {
return `Bearer ${token}`;
}
return token;
} }
/** /**
@@ -30,7 +37,7 @@ export async function logoutUser(): Promise<void> {
await fetch(`/api/auth/logout`, { await fetch(`/api/auth/logout`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Authorization': `Bearer ${token}`, 'Authorization': token,
'Content-Type': 'application/json' 'Content-Type': 'application/json'
} }
}).catch(err => { }).catch(err => {

View File

@@ -32,12 +32,13 @@ function getAuthToken(): string | null {
function createApiHeaders(token?: string | null, customHeaders: Record<string, string> = {}): Headers { function createApiHeaders(token?: string | null, customHeaders: Record<string, string> = {}): Headers {
const headers = new Headers({ const headers = new Headers({
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'accept': '*/*',
...customHeaders ...customHeaders
}); });
const authToken = token || getAuthToken(); const authToken = token || getAuthToken();
if (authToken) { if (authToken) {
headers.set('Authorization', `Bearer ${authToken}`); headers.set('authorization', `Bearer ${authToken}`);
} }
return headers; return headers;
@@ -59,6 +60,8 @@ export async function clientFetch<T = any>(url: string, options: RequestInit = {
...options, ...options,
headers, headers,
credentials: 'include', credentials: 'include',
mode: 'cors',
referrerPolicy: 'strict-origin-when-cross-origin'
}); });
if (!res.ok) { if (!res.ok) {