mirror of
https://github.com/BreizhHardware/Site-comptage-heure.git
synced 2026-01-18 16:17:28 +01:00
feat: enhance user seeding with UUIDs and improve code formatting in various files
This commit is contained in:
27
.github/workflows/ci.yml
vendored
27
.github/workflows/ci.yml
vendored
@@ -2,22 +2,23 @@ name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 8
|
||||
- run: pnpm install
|
||||
- run: npx prisma generate
|
||||
- run: npx prisma db push
|
||||
- run: node scripts/seed-test.js
|
||||
- run: pnpm ci
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 8
|
||||
- run: pnpm install
|
||||
- run: npx prisma generate
|
||||
- run: npx prisma db push
|
||||
- run: node scripts/seed-test.js
|
||||
- run: pnpm ci
|
||||
- run: pnpm run build
|
||||
|
||||
@@ -246,7 +246,8 @@ export default function AdminPage() {
|
||||
|
||||
const userMap = users.reduce(
|
||||
(acc, user) => {
|
||||
const name = `${user.firstName || ''} ${user.lastName || ''}`.trim() || user.email;
|
||||
const name =
|
||||
`${user.firstName || ''} ${user.lastName || ''}`.trim() || user.email;
|
||||
acc[user.id] = { name, email: user.email, role: user.role };
|
||||
return acc;
|
||||
},
|
||||
@@ -256,7 +257,7 @@ export default function AdminPage() {
|
||||
const userTotals = users.reduce(
|
||||
(acc, user) => {
|
||||
acc[user.id] = hours
|
||||
.filter(h => h.userId === user.id && h.status === 'VALIDATED')
|
||||
.filter((h) => h.userId === user.id && h.status === 'VALIDATED')
|
||||
.reduce((sum, h) => sum + h.duration, 0);
|
||||
return acc;
|
||||
},
|
||||
@@ -444,13 +445,14 @@ export default function AdminPage() {
|
||||
<TableCell>{hour.reason}</TableCell>
|
||||
<TableCell>
|
||||
{hour.status === 'VALIDATED' && hour.validatedBy
|
||||
? `Validé par ${hour.validatedBy.firstName || ''} ${hour.validatedBy.lastName || ''}`.trim() || hour.validatedBy.email
|
||||
? `Validé par ${hour.validatedBy.firstName || ''} ${hour.validatedBy.lastName || ''}`.trim() ||
|
||||
hour.validatedBy.email
|
||||
: hour.status === 'REJECTED' && hour.validatedBy
|
||||
? `Rejeté par ${hour.validatedBy.firstName || ''} ${hour.validatedBy.lastName || ''}`.trim() || hour.validatedBy.email
|
||||
: hour.status === 'PENDING'
|
||||
? 'En attente'
|
||||
: hour.status
|
||||
}
|
||||
? `Rejeté par ${hour.validatedBy.firstName || ''} ${hour.validatedBy.lastName || ''}`.trim() ||
|
||||
hour.validatedBy.email
|
||||
: hour.status === 'PENDING'
|
||||
? 'En attente'
|
||||
: hour.status}
|
||||
</TableCell>
|
||||
<TableCell>{userMap[hour.userId]?.name}</TableCell>
|
||||
<TableCell>
|
||||
@@ -729,7 +731,10 @@ export default function AdminPage() {
|
||||
</Dialog>
|
||||
)}
|
||||
{selectedUserForReset && (
|
||||
<Dialog open={resetPasswordDialog} onOpenChange={setResetPasswordDialog}>
|
||||
<Dialog
|
||||
open={resetPasswordDialog}
|
||||
onOpenChange={setResetPasswordDialog}
|
||||
>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Réinitialiser le mot de passe</DialogTitle>
|
||||
@@ -750,23 +755,31 @@ export default function AdminPage() {
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button onClick={() => setResetPasswordDialog(false)}>Annuler</Button>
|
||||
<Button onClick={() => setResetPasswordDialog(false)}>
|
||||
Annuler
|
||||
</Button>
|
||||
<Button onClick={handleResetPassword}>Réinitialiser</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)}
|
||||
{selectedUserForReset && confirmResetPassword && (
|
||||
<Dialog open={confirmResetPassword} onOpenChange={setConfirmResetPassword}>
|
||||
<Dialog
|
||||
open={confirmResetPassword}
|
||||
onOpenChange={setConfirmResetPassword}
|
||||
>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Confirmation de réinitialisation</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DialogDescription>
|
||||
Êtes-vous sûr de vouloir réinitialiser le mot de passe de {selectedUserForReset.name} ?
|
||||
Êtes-vous sûr de vouloir réinitialiser le mot de passe de{' '}
|
||||
{selectedUserForReset.name} ?
|
||||
</DialogDescription>
|
||||
<DialogFooter>
|
||||
<Button onClick={() => setConfirmResetPassword(false)}>Annuler</Button>
|
||||
<Button onClick={() => setConfirmResetPassword(false)}>
|
||||
Annuler
|
||||
</Button>
|
||||
<Button onClick={handleConfirmResetPassword}>Confirmer</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
|
||||
@@ -243,14 +243,17 @@ export default function DashboardPage() {
|
||||
</TableCell>
|
||||
<TableCell>{hour.duration} min</TableCell>
|
||||
<TableCell>{hour.reason}</TableCell>
|
||||
<TableCell>{hour.status === 'VALIDATED' && hour.validatedBy
|
||||
? `Validé par ${hour.validatedBy.firstName || ''} ${hour.validatedBy.lastName || ''}`.trim() || hour.validatedBy.email
|
||||
<TableCell>
|
||||
{hour.status === 'VALIDATED' && hour.validatedBy
|
||||
? `Validé par ${hour.validatedBy.firstName || ''} ${hour.validatedBy.lastName || ''}`.trim() ||
|
||||
hour.validatedBy.email
|
||||
: hour.status === 'REJECTED' && hour.validatedBy
|
||||
? `Rejeté par ${hour.validatedBy.firstName || ''} ${hour.validatedBy.lastName || ''}`.trim() || hour.validatedBy.email
|
||||
: hour.status === 'PENDING'
|
||||
? 'En attente'
|
||||
: hour.status
|
||||
}</TableCell>
|
||||
? `Rejeté par ${hour.validatedBy.firstName || ''} ${hour.validatedBy.lastName || ''}`.trim() ||
|
||||
hour.validatedBy.email
|
||||
: hour.status === 'PENDING'
|
||||
? 'En attente'
|
||||
: hour.status}
|
||||
</TableCell>
|
||||
{isAdmin && <TableCell>{hour.user.email}</TableCell>}
|
||||
{isAdmin && (
|
||||
<TableCell>
|
||||
|
||||
@@ -22,12 +22,15 @@ export default function Header() {
|
||||
{session && (
|
||||
<div className="flex items-center space-x-4">
|
||||
<span className="text-gray-900 dark:text-white">
|
||||
{session.user.email} ({
|
||||
session.user.role === 'MEMBER' ? 'Membre' :
|
||||
session.user.role === 'ADMIN' ? 'Bureau' :
|
||||
session.user.role === 'SUPER_ADMIN' ? 'Gestionnaire' :
|
||||
session.user.role
|
||||
})
|
||||
{session.user.email} (
|
||||
{session.user.role === 'MEMBER'
|
||||
? 'Membre'
|
||||
: session.user.role === 'ADMIN'
|
||||
? 'Bureau'
|
||||
: session.user.role === 'SUPER_ADMIN'
|
||||
? 'Gestionnaire'
|
||||
: session.user.role}
|
||||
)
|
||||
</span>
|
||||
<Button onClick={() => signOut()} variant="destructive">
|
||||
Déconnexion
|
||||
|
||||
@@ -8,9 +8,7 @@ export function Providers({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<SessionProvider>
|
||||
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
||||
<SettingsProvider>
|
||||
{children}
|
||||
</SettingsProvider>
|
||||
<SettingsProvider>{children}</SettingsProvider>
|
||||
</ThemeProvider>
|
||||
</SessionProvider>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
'use client';
|
||||
|
||||
import { createContext, useContext, useState, useEffect, ReactNode } from 'react';
|
||||
import {
|
||||
createContext,
|
||||
useContext,
|
||||
useState,
|
||||
useEffect,
|
||||
ReactNode,
|
||||
} from 'react';
|
||||
|
||||
interface Settings {
|
||||
name: string;
|
||||
@@ -12,7 +18,9 @@ interface SettingsContextType {
|
||||
refetchSettings: () => void;
|
||||
}
|
||||
|
||||
const SettingsContext = createContext<SettingsContextType | undefined>(undefined);
|
||||
const SettingsContext = createContext<SettingsContextType | undefined>(
|
||||
undefined,
|
||||
);
|
||||
|
||||
export function useSettings() {
|
||||
const context = useContext(SettingsContext);
|
||||
@@ -38,7 +46,9 @@ export function SettingsProvider({ children }: { children: ReactNode }) {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<SettingsContext.Provider value={{ settings, refetchSettings: fetchSettings }}>
|
||||
<SettingsContext.Provider
|
||||
value={{ settings, refetchSettings: fetchSettings }}
|
||||
>
|
||||
{children}
|
||||
</SettingsContext.Provider>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defineConfig } from 'cypress'
|
||||
import { defineConfig } from 'cypress';
|
||||
|
||||
export default defineConfig({
|
||||
e2e: {
|
||||
@@ -7,4 +7,4 @@ export default defineConfig({
|
||||
// implement node event listeners here
|
||||
},
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
describe('Login', () => {
|
||||
it('should login successfully', () => {
|
||||
cy.visit('/login')
|
||||
cy.get('input[name="email"]').type('test@example.com')
|
||||
cy.get('input[name="password"]').type('password')
|
||||
cy.get('button[type="submit"]').click()
|
||||
cy.url().should('include', '/dashboard')
|
||||
})
|
||||
})
|
||||
|
||||
cy.visit('/login');
|
||||
cy.get('input[name="email"]').type('test@example.com');
|
||||
cy.get('input[name="password"]').type('password');
|
||||
cy.get('button[type="submit"]').click();
|
||||
cy.url().should('include', '/dashboard');
|
||||
});
|
||||
});
|
||||
|
||||
2838
pnpm-lock.yaml
generated
2838
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const bcrypt = require('bcryptjs');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
@@ -15,6 +16,7 @@ async function main() {
|
||||
role: 'MEMBER',
|
||||
firstName: 'Test',
|
||||
lastName: 'User',
|
||||
id: uuidv4(),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user