Skip to content
This repository was archived by the owner on Apr 20, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions app/front/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/front/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"@radix-ui/react-slot": "^1.1.1",
"@tailwindcss/postcss": "^4.0.3",
"@tailwindcss/vite": "^4.0.3",
"@tanstack/react-router": "^1.99.6",
"@tanstack/react-router": "^1.103.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.474.0",
Expand Down
23 changes: 11 additions & 12 deletions app/front/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createRouter, RouterProvider } from "@tanstack/react-router";
import useAuth, { AuthProvider } from "./hooks/useAuth";
import { routeTree } from "./routeTree.gen";
import { StrictMode } from "react";
import { createRouter, RouterProvider } from '@tanstack/react-router';
import useAuth, { AuthProvider } from './hooks/useAuth';
import { routeTree } from './routeTree.gen';
import { StrictMode } from 'react';

// Create a new router instance
const router = createRouter({
Expand All @@ -15,22 +15,21 @@ const router = createRouter({
},
});


// Register the router instance for type safety
declare module "@tanstack/react-router" {
declare module '@tanstack/react-router' {
interface Register {
router: typeof router;
}
}

export function App(){
const auth = useAuth();
return (
export function App() {
const auth = useAuth();

return (
<StrictMode>
<AuthProvider>
<RouterProvider router={router} context={{ auth }} />
</AuthProvider>
</StrictMode>
)
}
);
}
127 changes: 127 additions & 0 deletions app/front/src/components/Folder.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { X } from 'lucide-react';
import axios from 'axios';
import { useState } from 'react';

interface CreateFolderModalProps {
isOpen: boolean;
onClose: () => void;
onCreateFolder: (folderName: string) => void;
}

const CreateFolderModal = ({ isOpen, onClose, onCreateFolder }: CreateFolderModalProps) => {
const [folderName, setFolderName] = useState('');
const [error, setError] = useState<string | null>(null);

const api = axios.create({
baseURL: 'http://localhost:8082/api',
headers: {
Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InRlc3Q0QGdtYWlsLmNvbSIsImV4cCI6MTczOTYyODAwNCwidXNlcl9pZCI6IjY3YWY0NzVmZjI0ZWVlZjFmYWI2ZmU5NSJ9.LrLYhffochKEgF8PJhK-S7uH6_WhFkmrkPtWEja1pl0',
'Content-Type': 'application/json',
},
});

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();

if (!folderName.trim()) {
setError('Le nom du dossier est requis');
return;
}

try {
const response = await api.post('/folders', {
name: folderName
});

console.log('Dossier créé:', response.data);

onCreateFolder(folderName);
setFolderName('');
setError(null);
onClose();
} catch (err) {
if (axios.isAxiosError(err)) {
setError(err.response?.data?.message || 'Erreur lors de la création du dossier');
} else {
setError('Une erreur inattendue est survenue');
}
}
};

if (!isOpen) return null;

return (
<div className="fixed inset-0 z-50 overflow-y-auto">
<div className="flex min-h-screen items-center justify-center p-4">
<div
className="fixed inset-0 bg-black/30 backdrop-blur-sm"
onClick={onClose}
/>

<div className="relative bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full mx-4">
<div className="flex items-center justify-between p-4 border-b dark:border-gray-700">
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">
Nouveau dossier
</h3>
<button
onClick={onClose}
className="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
>
<X className="h-5 w-5" />
</button>
</div>

<form onSubmit={handleSubmit} className="p-6">
<div className="space-y-4">
<div>
<label
htmlFor="folder-name"
className="block text-sm font-medium text-gray-700 dark:text-gray-300"
>
Nom du dossier
</label>
<input
type="text"
id="folder-name"
value={folderName}
onChange={(e) => setFolderName(e.target.value)}
className="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600
shadow-sm py-2 px-3 bg-white dark:bg-gray-700
text-gray-900 dark:text-white
focus:border-blue-500 focus:ring-1 focus:ring-blue-500"
placeholder="Mon nouveau dossier"
/>
</div>

{error && (
<p className="text-sm text-red-600 dark:text-red-400">
{error}
</p>
)}
</div>

<div className="mt-6 flex justify-end gap-3">
<button
type="button"
onClick={onClose}
className="px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-200
hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg"
>
Annuler
</button>
<button
type="submit"
className="px-4 py-2 text-sm font-medium text-white bg-blue-600
hover:bg-blue-700 rounded-lg"
>
Créer
</button>
</div>
</form>
</div>
</div>
</div>
);
};

export default CreateFolderModal;
79 changes: 79 additions & 0 deletions app/front/src/components/Table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Folder } from '@/types';

const formatDate = (dateString: string) => {
const date = new Date(dateString);
const day = date.getDate().toString().padStart(2, '0');
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const year = date.getFullYear();
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');

return `${day}/${month}/${year} ${hours}:${minutes}`;
};

const Table = ({
folders,
onFolderClick,
}: {
folders: Folder[];
onFolderClick: (folder: Folder) => void;
}) => {
if (!folders || folders.length === 0) {
return (
<div className='text-center py-4 text-gray-500'>Aucun dossier trouvé</div>
);
}

return (
<div className='overflow-x-auto'>
<table className='min-w-full bg-white border border-gray-200'>
<thead className='bg-gray-50'>
<tr>
<th className='px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider'>
Nom
</th>
<th className='px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider'>
Chemin
</th>
<th className='px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider'>
Profondeur
</th>
<th className='px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider'>
Créé le
</th>
<th className='px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider'>
Modifié le
</th>
</tr>
</thead>
<tbody className='bg-white divide-y divide-gray-200'>
{folders.map((folder: Folder) => (
<tr
key={folder.id}
className='hover:bg-gray-50 cursor-pointer'
onClick={() => onFolderClick(folder)}
>
<td className='px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900'>
{folder.name}
</td>
<td className='px-6 py-4 whitespace-nowrap text-sm text-gray-500'>
{folder.path}
</td>
<td className='px-6 py-4 whitespace-nowrap text-sm text-gray-500'>
{folder.depth}
</td>
<td className='px-6 py-4 whitespace-nowrap text-sm text-gray-500'>
{formatDate(folder.created_at)}
</td>
<td className='px-6 py-4 whitespace-nowrap text-sm text-gray-500'>
{formatDate(folder.updated_at)}
</td>
</tr>
))}
</tbody>
</table>
</div>
);
};

export default Table;
Loading
Loading