diff --git a/src/core/api/handlers/users.js b/src/core/api/handlers/users.js index d78ebbd..1045613 100644 --- a/src/core/api/handlers/users.js +++ b/src/core/api/handlers/users.js @@ -6,7 +6,7 @@ import { validateSession } from '../../../features/auth/lib/session.js'; import { cookies } from 'next/headers'; import { query, updateById } from '@hykocx/zen/database'; -import { getSessionCookieName, getModulesConfig } from '../../../shared/lib/appConfig.js'; +import { getSessionCookieName } from '../../../shared/lib/appConfig.js'; import { updateUser } from '../../../features/auth/lib/auth.js'; import { uploadImage, deleteFile, generateUniqueFilename, generateUserFilePath, FILE_TYPE_PRESETS, FILE_SIZE_LIMITS, validateUpload } from '@hykocx/zen/storage'; @@ -100,17 +100,6 @@ export async function handleGetUserById(request, userId) { const response = { user: result.rows[0] }; - // When clients module is active, include the client linked to this user (if any) - const modules = getModulesConfig(); - if (modules.clients) { - const clientResult = await query( - `SELECT id, client_number, company_name, first_name, last_name, email - FROM zen_clients WHERE user_id = $1 LIMIT 1`, - [userId] - ); - response.linkedClient = clientResult.rows[0] || null; - } - return response; } @@ -158,24 +147,6 @@ export async function handleUpdateUserById(request, userId) { return { success: false, error: 'Not Found', message: 'User not found' }; } - // When clients module is active, update client association (one user = one client) - const modules = getModulesConfig(); - if (modules.clients && body.client_id !== undefined) { - const clientId = body.client_id === null || body.client_id === '' ? null : parseInt(body.client_id, 10); - // Unlink all clients currently linked to this user - await query( - 'UPDATE zen_clients SET user_id = NULL, updated_at = CURRENT_TIMESTAMP WHERE user_id = $1', - [userId] - ); - // Link the selected client to this user if provided - if (clientId != null && !Number.isNaN(clientId)) { - await query( - 'UPDATE zen_clients SET user_id = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2', - [userId, clientId] - ); - } - } - const result = await query( 'SELECT id, email, name, role, image, email_verified, created_at FROM zen_auth_users WHERE id = $1', [userId] diff --git a/src/modules/clients/.env.example b/src/modules/clients/.env.example deleted file mode 100644 index a42bafa..0000000 --- a/src/modules/clients/.env.example +++ /dev/null @@ -1,4 +0,0 @@ -################################# -# MODULE CLIENTS -ZEN_MODULE_CLIENTS=false -################################# \ No newline at end of file diff --git a/src/modules/clients/INSTALL.md b/src/modules/clients/INSTALL.md deleted file mode 100644 index d73b609..0000000 --- a/src/modules/clients/INSTALL.md +++ /dev/null @@ -1,37 +0,0 @@ -# Clients Module Installation - -## 1. Configure Environment Variables - -Copy all variables from [`.env.example`](.env.example) and add them to your `.env` file. - -## 2. Activate the Module - -In your `.env` file, set: - -```env -ZEN_MODULE_CLIENTS=true -``` - -## 3. Database Setup - -Run the database initialization to create the required tables: - -```bash -npx zen-db init -``` - -This will create the following table: -- `zen_clients` - Stores client information - -## 4. Features - -### Client Management -- Create, edit, and delete clients -- Store contact information (name, email, phone, address) -- Link clients to user accounts (optional) -- Unique client numbers (auto-generated) - -### Used By Other Modules -The clients module is a dependency for: -- **Quote Module**: Assign quotes to clients -- **Invoice Module**: Assign invoices to clients diff --git a/src/modules/clients/admin/ClientCreatePage.js b/src/modules/clients/admin/ClientCreatePage.js deleted file mode 100644 index 92b97c1..0000000 --- a/src/modules/clients/admin/ClientCreatePage.js +++ /dev/null @@ -1,76 +0,0 @@ -'use client'; - -import React, { useState } from 'react'; -import { useRouter } from 'next/navigation'; -import { Button } from '../../../shared/components'; -import ClientForm from './ClientForm.js'; -import { useToast } from '@hykocx/zen/toast'; - -/** - * Client Create Page Component - * Page for creating a new client - */ -const ClientCreatePage = ({ user }) => { - const router = useRouter(); - const toast = useToast(); - const [saving, setSaving] = useState(false); - - const handleSubmit = async (formData) => { - try { - setSaving(true); - - const response = await fetch('/zen/api/admin/clients', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - credentials: 'include', - body: JSON.stringify({ client: formData }) - }); - - const data = await response.json(); - - if (data.success) { - toast.success('Client créé avec succès'); - router.push('/admin/clients/list'); - } else { - toast.error(data.message || 'Échec de la création du client'); - } - } catch (error) { - console.error('Error creating client:', error); - toast.error('Échec de la création du client'); - } finally { - setSaving(false); - } - }; - - return ( -
- {/* Header */} -
-
-

Créer un client

-

Remplissez les détails pour créer un nouveau client

-
- -
- - {/* Form */} - router.push('/admin/clients/list')} - isEdit={false} - saving={saving} - users={[]} - /> -
- ); -}; - -export default ClientCreatePage; diff --git a/src/modules/clients/admin/ClientEditPage.js b/src/modules/clients/admin/ClientEditPage.js deleted file mode 100644 index 694b948..0000000 --- a/src/modules/clients/admin/ClientEditPage.js +++ /dev/null @@ -1,139 +0,0 @@ -'use client'; - -import React, { useState, useEffect } from 'react'; -import { useRouter } from 'next/navigation'; -import { Button, Card, Loading } from '../../../shared/components'; -import ClientForm from './ClientForm.js'; -import { useToast } from '@hykocx/zen/toast'; - -/** - * Client Edit Page Component - * Page for editing an existing client - */ -const ClientEditPage = ({ clientId, user }) => { - const router = useRouter(); - const toast = useToast(); - const [client, setClient] = useState(null); - const [loading, setLoading] = useState(true); - const [saving, setSaving] = useState(false); - - useEffect(() => { - loadClient(); - }, [clientId]); - - const loadClient = async () => { - try { - setLoading(true); - - const response = await fetch(`/zen/api/admin/clients?id=${clientId}`, { - credentials: 'include' - }); - const data = await response.json(); - - if (data.success) { - setClient(data.client); - } else { - toast.error(data.error || 'Échec du chargement du client'); - } - } catch (error) { - console.error('Error loading client:', error); - toast.error('Échec du chargement du client'); - } finally { - setLoading(false); - } - }; - - const handleSubmit = async (formData) => { - try { - setSaving(true); - - const response = await fetch(`/zen/api/admin/clients`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - }, - credentials: 'include', - body: JSON.stringify({ id: clientId, client: formData }) - }); - - const data = await response.json(); - - if (data.success) { - toast.success('Client mis à jour avec succès'); - router.push('/admin/clients/list'); - } else { - toast.error(data.message || 'Échec de la mise à jour du client'); - } - } catch (error) { - console.error('Error updating client:', error); - toast.error('Échec de la mise à jour du client'); - } finally { - setSaving(false); - } - }; - - if (loading) { - return ( -
- -
- ); - } - - if (!client) { - return ( -
-
-
-

Modifier le client

-

Client non trouvé

-
- -
- -
-

Client non trouvé

-

Le client que vous recherchez n'existe pas ou a été supprimé.

-
-
-
- ); - } - - return ( -
- {/* Header */} -
-
-

Modifier le client

-

Client : {client.first_name} {client.last_name}

-
- -
- - {/* Form */} - router.push('/admin/clients/list')} - isEdit={true} - saving={saving} - users={[]} - /> -
- ); -}; - -export default ClientEditPage; diff --git a/src/modules/clients/admin/ClientForm.js b/src/modules/clients/admin/ClientForm.js deleted file mode 100644 index 1871f7e..0000000 --- a/src/modules/clients/admin/ClientForm.js +++ /dev/null @@ -1,245 +0,0 @@ -'use client'; - -import React, { useState } from 'react'; -import { Button, Card, Input, Select, Textarea } from '../../../shared/components'; - -/** - * Client Form Component - * Form for creating and editing clients - */ -const ClientForm = ({ - initialData = null, - users = [], - onSubmit, - onCancel, - isEdit = false, - saving = false -}) => { - const [formData, setFormData] = useState({ - user_id: initialData?.user_id || '', - company_name: initialData?.company_name || '', - first_name: initialData?.first_name || '', - last_name: initialData?.last_name || '', - email: initialData?.email || '', - phone: initialData?.phone || '', - address: initialData?.address || '', - city: initialData?.city || '', - province: initialData?.province || '', - postal_code: initialData?.postal_code || '', - country: initialData?.country || 'Canada', - notes: initialData?.notes || '', - }); - - const [errors, setErrors] = useState({}); - - const handleInputChange = (field, value) => { - setFormData(prev => ({ - ...prev, - [field]: value - })); - - if (errors[field]) { - setErrors(prev => ({ - ...prev, - [field]: null - })); - } - }; - - const validateForm = () => { - const newErrors = {}; - - if (!formData.first_name.trim()) { - newErrors.first_name = "Le prénom est requis"; - } - - if (!formData.last_name.trim()) { - newErrors.last_name = "Le nom de famille est requis"; - } - - if (!formData.email.trim()) { - newErrors.email = "L'email est requis"; - } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) { - newErrors.email = "Format d'email invalide"; - } - - setErrors(newErrors); - return Object.keys(newErrors).length === 0; - }; - - const handleSubmit = (e) => { - e.preventDefault(); - - if (!validateForm()) { - return; - } - - if (onSubmit) { - onSubmit(formData); - } - }; - - return ( -
- {/* Basic Information */} - -
-

Informations de base

- -
-
- handleInputChange('company_name', value)} - placeholder="Entrez le nom de la société..." - /> -
- - handleInputChange('first_name', value)} - placeholder="Entrez le prénom..." - error={errors.first_name} - /> - - handleInputChange('last_name', value)} - placeholder="Entrez le nom de famille..." - error={errors.last_name} - /> - - handleInputChange('email', value)} - placeholder="Entrez le courriel..." - error={errors.email} - /> - - handleInputChange('phone', value)} - placeholder="Entrez le numéro de téléphone..." - /> -
-
-
- - {/* Address */} - -
-

Adresse

- -
-
- handleInputChange('address', value)} - placeholder="Entrez l'adresse..." - /> -
- - handleInputChange('city', value)} - placeholder="Entrez la ville..." - /> - - handleInputChange('province', value)} - placeholder="Entrez la province ou l'état..." - /> - - handleInputChange('postal_code', value)} - placeholder="Entrez le code postal..." - /> - - handleInputChange('country', value)} - placeholder="Entrez le pays..." - /> -
-
-
- - {/* User Link */} - {users.length > 0 && ( - -
-

Lien compte utilisateur

-

- Vous pouvez associer ce client à un compte utilisateur sur la plateforme -

- -