diff --git a/frontend/components/user/UserDrawer.vue b/frontend/components/user/UserDrawer.vue index 0f7fcf1..964f818 100644 --- a/frontend/components/user/UserDrawer.vue +++ b/frontend/components/user/UserDrawer.vue @@ -11,6 +11,16 @@ :error="touched.username && !form.username.trim() ? 'Le nom est requis' : ''" @blur="touched.username = true" /> + + props.modelValue, (open) => { if (open) { if (props.item) { form.username = props.item.username ?? '' + form.firstName = props.item.firstName ?? '' + form.lastName = props.item.lastName ?? '' form.password = '' form.roles = [...props.item.roles] form.isEmployee = props.item.isEmployee ?? false } else { form.username = '' + form.firstName = '' + form.lastName = '' form.password = '' form.roles = ['ROLE_USER'] form.isEmployee = false @@ -124,6 +140,8 @@ async function handleSubmit() { try { const payload: UserWrite = { username: form.username.trim(), + firstName: form.firstName.trim() || null, + lastName: form.lastName.trim() || null, roles: form.roles, isEmployee: form.isEmployee, } diff --git a/frontend/services/dto/user-data.ts b/frontend/services/dto/user-data.ts index 84e4608..3f5f5df 100644 --- a/frontend/services/dto/user-data.ts +++ b/frontend/services/dto/user-data.ts @@ -4,6 +4,8 @@ export type UserData = { id: number '@id'?: string username: string + firstName?: string | null + lastName?: string | null roles: string[] avatarUrl?: string | null apiToken?: string | null @@ -20,6 +22,8 @@ export type UserData = { export type UserWrite = { username: string + firstName?: string | null + lastName?: string | null plainPassword?: string roles: string[] // HR / absence management diff --git a/migrations/Version20260526120000.php b/migrations/Version20260526120000.php new file mode 100644 index 0000000..5d02af7 --- /dev/null +++ b/migrations/Version20260526120000.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE "user" ADD first_name VARCHAR(100) DEFAULT NULL'); + $this->addSql('ALTER TABLE "user" ADD last_name VARCHAR(100) DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE "user" DROP COLUMN IF EXISTS first_name'); + $this->addSql('ALTER TABLE "user" DROP COLUMN IF EXISTS last_name'); + } +} diff --git a/src/DataFixtures/AppFixtures.php b/src/DataFixtures/AppFixtures.php index ef9f2cb..0b5de94 100644 --- a/src/DataFixtures/AppFixtures.php +++ b/src/DataFixtures/AppFixtures.php @@ -43,6 +43,8 @@ class AppFixtures extends Fixture // Users $admin = new User(); $admin->setUsername('admin'); + $admin->setFirstName('Alex'); + $admin->setLastName('Martin'); $admin->setRoles(['ROLE_ADMIN']); $admin->setPassword($this->passwordHasher->hashPassword($admin, 'admin')); $admin->setApiToken('dev-mcp-token-for-testing-only-do-not-use-in-production'); @@ -50,18 +52,24 @@ class AppFixtures extends Fixture $userAlice = new User(); $userAlice->setUsername('alice'); + $userAlice->setFirstName('Alice'); + $userAlice->setLastName('Dupont'); $userAlice->setRoles(['ROLE_USER']); $userAlice->setPassword($this->passwordHasher->hashPassword($userAlice, 'alice')); $manager->persist($userAlice); $userBob = new User(); $userBob->setUsername('bob'); + $userBob->setFirstName('Bob'); + $userBob->setLastName('Leroy'); $userBob->setRoles(['ROLE_USER']); $userBob->setPassword($this->passwordHasher->hashPassword($userBob, 'bob')); $manager->persist($userBob); $userCharlie = new User(); $userCharlie->setUsername('charlie'); + $userCharlie->setFirstName('Charlie'); + $userCharlie->setLastName('Moreau'); $userCharlie->setRoles(['ROLE_USER']); $userCharlie->setPassword($this->passwordHasher->hashPassword($userCharlie, 'charlie')); $manager->persist($userCharlie); diff --git a/src/Entity/User.php b/src/Entity/User.php index 22b8a8d..fd75f39 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -55,6 +55,14 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface #[Groups(['me:read', 'task:read', 'user:list', 'user:write', 'time_entry:read', 'absence_request:read', 'absence_balance:read'])] private ?string $username = null; + #[ORM\Column(length: 100, nullable: true)] + #[Groups(['me:read', 'user:list', 'user:write'])] + private ?string $firstName = null; + + #[ORM\Column(length: 100, nullable: true)] + #[Groups(['me:read', 'user:list', 'user:write'])] + private ?string $lastName = null; + /** @var list */ #[ORM\Column] #[ApiProperty(security: "is_granted('ROLE_ADMIN') or object == user")] @@ -147,6 +155,30 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface return $this; } + public function getFirstName(): ?string + { + return $this->firstName; + } + + public function setFirstName(?string $firstName): static + { + $this->firstName = $firstName; + + return $this; + } + + public function getLastName(): ?string + { + return $this->lastName; + } + + public function setLastName(?string $lastName): static + { + $this->lastName = $lastName; + + return $this; + } + public function getUserIdentifier(): string { return (string) $this->username;