Compare commits
57 Commits
7ba2db3d92
...
09b84379bf
Author | SHA1 | Date | |
---|---|---|---|
09b84379bf | |||
8c78abc668 | |||
![]() |
643d5d451a | ||
![]() |
806044e990 | ||
![]() |
57a8eba238 | ||
1722e0e6b5 | |||
0246adcc03 | |||
89e0dd4d58 | |||
![]() |
9074447216 | ||
![]() |
c1a79f7621 | ||
![]() |
d6d0a9bbad | ||
![]() |
549d0c5bfc | ||
![]() |
ebb799bcb8 | ||
a52c5adb83 | |||
c5cec0fa04 | |||
cb867ba8bb | |||
1567570d12 | |||
0e2a2f25f6 | |||
65f5c8cce4 | |||
f244e51aa7 | |||
![]() |
12ac37c97e | ||
80f18f7fc8 | |||
9a75d46972 | |||
f3a44047c4 | |||
c1ea94eb95 | |||
e96b410627 | |||
1bc9610b75 | |||
f5c0954435 | |||
e9f74aa3bf | |||
e297480fae | |||
![]() |
579a56c53f | ||
![]() |
a0e50bf187 | ||
![]() |
f7c08a5c98 | ||
![]() |
3cf9ab3bed | ||
![]() |
ae335524db | ||
![]() |
9e49da7775 | ||
![]() |
432d7ba4de | ||
f8569d8db3 | |||
3eca8a4421 | |||
b702ca50ed | |||
9369682362 | |||
9efc4931f9 | |||
a6d83640bd | |||
ddf458e44c | |||
2be0e352ef | |||
9ec6a67a92 | |||
e083dc1cec | |||
ac42fb9f85 | |||
c84c7c4c49 | |||
c93e5af9e3 | |||
18dd03a84b | |||
d4c858474c | |||
e153266b65 | |||
bfbccea96f | |||
007935cea6 | |||
![]() |
ea5be39a2e | ||
![]() |
562b343063 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -23,5 +23,3 @@
|
|||||||
.idea
|
.idea
|
||||||
|
|
||||||
composer.lock
|
composer.lock
|
||||||
|
|
||||||
/migrations/
|
|
@ -3,10 +3,10 @@ services:
|
|||||||
database:
|
database:
|
||||||
image: postgres:${POSTGRES_VERSION:-16}-alpine
|
image: postgres:${POSTGRES_VERSION:-16}-alpine
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: ${POSTGRES_DB:-app}
|
POSTGRES_DB: ${POSTGRES_DB:-hegresphere}
|
||||||
# You should definitely change the password in production
|
# You should definitely change the password in production
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!}
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-Btssio2024}
|
||||||
POSTGRES_USER: ${POSTGRES_USER:-app}
|
POSTGRES_USER: ${POSTGRES_USER:-bourgoino}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "pg_isready", "-d", "${POSTGRES_DB:-app}", "-U", "${POSTGRES_USER:-app}"]
|
test: ["CMD", "pg_isready", "-d", "${POSTGRES_DB:-app}", "-U", "${POSTGRES_USER:-app}"]
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
|
@ -42,8 +42,10 @@
|
|||||||
"symfony/validator": "7.1.*",
|
"symfony/validator": "7.1.*",
|
||||||
"symfony/web-link": "7.1.*",
|
"symfony/web-link": "7.1.*",
|
||||||
"symfony/yaml": "7.1.*",
|
"symfony/yaml": "7.1.*",
|
||||||
|
"symfonycasts/sass-bundle": "^0.7.0",
|
||||||
"twig/extra-bundle": "^2.12|^3.0",
|
"twig/extra-bundle": "^2.12|^3.0",
|
||||||
"twig/twig": "^2.12|^3.0"
|
"twig/twig": "^2.12|^3.0",
|
||||||
|
"ext-http": "*"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"allow-plugins": {
|
"allow-plugins": {
|
||||||
|
102
composer.lock
generated
102
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "1bc99d81c026aaf4e662ffffde457d04",
|
"content-hash": "39f4377209acc13ab9e977a5301faef0",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "composer/semver",
|
"name": "composer/semver",
|
||||||
@ -379,26 +379,29 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/deprecations",
|
"name": "doctrine/deprecations",
|
||||||
"version": "1.1.4",
|
"version": "1.1.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/deprecations.git",
|
"url": "https://github.com/doctrine/deprecations.git",
|
||||||
"reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9"
|
"reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/31610dbb31faa98e6b5447b62340826f54fbc4e9",
|
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38",
|
||||||
"reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9",
|
"reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1 || ^8.0"
|
"php": "^7.1 || ^8.0"
|
||||||
},
|
},
|
||||||
|
"conflict": {
|
||||||
|
"phpunit/phpunit": "<=7.5 || >=13"
|
||||||
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"doctrine/coding-standard": "^9 || ^12",
|
"doctrine/coding-standard": "^9 || ^12 || ^13",
|
||||||
"phpstan/phpstan": "1.4.10 || 2.0.3",
|
"phpstan/phpstan": "1.4.10 || 2.1.11",
|
||||||
"phpstan/phpstan-phpunit": "^1.0 || ^2",
|
"phpstan/phpstan-phpunit": "^1.0 || ^2",
|
||||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12",
|
||||||
"psr/log": "^1 || ^2 || ^3"
|
"psr/log": "^1 || ^2 || ^3"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
@ -418,9 +421,9 @@
|
|||||||
"homepage": "https://www.doctrine-project.org/",
|
"homepage": "https://www.doctrine-project.org/",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/doctrine/deprecations/issues",
|
"issues": "https://github.com/doctrine/deprecations/issues",
|
||||||
"source": "https://github.com/doctrine/deprecations/tree/1.1.4"
|
"source": "https://github.com/doctrine/deprecations/tree/1.1.5"
|
||||||
},
|
},
|
||||||
"time": "2024-12-07T21:18:45+00:00"
|
"time": "2025-04-07T20:06:18+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/doctrine-bundle",
|
"name": "doctrine/doctrine-bundle",
|
||||||
@ -6249,16 +6252,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/stimulus-bundle",
|
"name": "symfony/stimulus-bundle",
|
||||||
"version": "v2.23.0",
|
"version": "v2.24.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/stimulus-bundle.git",
|
"url": "https://github.com/symfony/stimulus-bundle.git",
|
||||||
"reference": "254f4e05cbaa349d4ae68b9b2e6a22995e0887f9"
|
"reference": "e09840304467cda3324cc116c7f4ee23c8ff227c"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/stimulus-bundle/zipball/254f4e05cbaa349d4ae68b9b2e6a22995e0887f9",
|
"url": "https://api.github.com/repos/symfony/stimulus-bundle/zipball/e09840304467cda3324cc116c7f4ee23c8ff227c",
|
||||||
"reference": "254f4e05cbaa349d4ae68b9b2e6a22995e0887f9",
|
"reference": "e09840304467cda3324cc116c7f4ee23c8ff227c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -6298,7 +6301,7 @@
|
|||||||
"symfony-ux"
|
"symfony-ux"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/stimulus-bundle/tree/v2.23.0"
|
"source": "https://github.com/symfony/stimulus-bundle/tree/v2.24.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -6314,7 +6317,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-01-16T21:55:09+00:00"
|
"time": "2025-03-09T21:10:04+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/stopwatch",
|
"name": "symfony/stopwatch",
|
||||||
@ -6914,16 +6917,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/ux-turbo",
|
"name": "symfony/ux-turbo",
|
||||||
"version": "v2.23.0",
|
"version": "v2.24.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/ux-turbo.git",
|
"url": "https://github.com/symfony/ux-turbo.git",
|
||||||
"reference": "db96cf04d70a8c820671ce55530e8bf641ada33f"
|
"reference": "22954300bd0b01ca46f17c7890ea15138d9cf67f"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/ux-turbo/zipball/db96cf04d70a8c820671ce55530e8bf641ada33f",
|
"url": "https://api.github.com/repos/symfony/ux-turbo/zipball/22954300bd0b01ca46f17c7890ea15138d9cf67f",
|
||||||
"reference": "db96cf04d70a8c820671ce55530e8bf641ada33f",
|
"reference": "22954300bd0b01ca46f17c7890ea15138d9cf67f",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -6992,7 +6995,7 @@
|
|||||||
"turbo-stream"
|
"turbo-stream"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/ux-turbo/tree/v2.23.0"
|
"source": "https://github.com/symfony/ux-turbo/tree/v2.24.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -7008,7 +7011,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-02-06T08:47:30+00:00"
|
"time": "2025-04-04T17:29:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/validator",
|
"name": "symfony/validator",
|
||||||
@ -7420,6 +7423,61 @@
|
|||||||
],
|
],
|
||||||
"time": "2025-01-07T12:50:05+00:00"
|
"time": "2025-01-07T12:50:05+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfonycasts/sass-bundle",
|
||||||
|
"version": "v0.7.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/SymfonyCasts/sass-bundle.git",
|
||||||
|
"reference": "d88601c50eff716d9273dffbd736adefdc19e2fc"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/SymfonyCasts/sass-bundle/zipball/d88601c50eff716d9273dffbd736adefdc19e2fc",
|
||||||
|
"reference": "d88601c50eff716d9273dffbd736adefdc19e2fc",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.1",
|
||||||
|
"symfony/asset-mapper": "^6.3|^7.0",
|
||||||
|
"symfony/console": "^5.4|^6.3|^7.0",
|
||||||
|
"symfony/filesystem": "^5.4|^6.3|^7.0",
|
||||||
|
"symfony/http-client": "^5.4|^6.3|^7.0",
|
||||||
|
"symfony/process": "^5.4|^6.3|^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"matthiasnoback/symfony-config-test": "^5.0",
|
||||||
|
"phpstan/phpstan-symfony": "^1.4",
|
||||||
|
"symfony/framework-bundle": "^6.3|^7.0",
|
||||||
|
"symfony/phpunit-bridge": "^6.3|^7.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfonycasts\\SassBundle\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Mathéo Daninos",
|
||||||
|
"homepage": "https://github.com/WebMamba"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Delightful Sass Support for Symfony + AssetMapper",
|
||||||
|
"keywords": [
|
||||||
|
"asset-mapper",
|
||||||
|
"sass"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/SymfonyCasts/sass-bundle/issues",
|
||||||
|
"source": "https://github.com/SymfonyCasts/sass-bundle/tree/v0.7.0"
|
||||||
|
},
|
||||||
|
"time": "2024-05-22T14:59:07+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/extra-bundle",
|
"name": "twig/extra-bundle",
|
||||||
"version": "v3.20.0",
|
"version": "v3.20.0",
|
||||||
|
@ -13,4 +13,5 @@ return [
|
|||||||
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||||
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||||
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||||
|
Symfonycasts\SassBundle\SymfonycastsSassBundle::class => ['all' => true],
|
||||||
];
|
];
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||||
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
||||||
parameters:
|
parameters:
|
||||||
|
app.jwtsecret : '%env(JWT_SECRET)%'
|
||||||
services:
|
services:
|
||||||
# default configuration for services in *this* file
|
# default configuration for services in *this* file
|
||||||
_defaults:
|
_defaults:
|
||||||
|
38
migrations/Version20241121141451.php
Normal file
38
migrations/Version20241121141451.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20241121141451 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('DROP SEQUENCE status_id_seq CASCADE');
|
||||||
|
$this->addSql('DROP TABLE status');
|
||||||
|
$this->addSql('ALTER TABLE userapp ADD is_verified BOOLEAN NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE userapp ALTER roles SET NOT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE SCHEMA public');
|
||||||
|
$this->addSql('CREATE SEQUENCE status_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||||
|
$this->addSql('CREATE TABLE status (id INT NOT NULL, label VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('ALTER TABLE userApp DROP is_verified');
|
||||||
|
$this->addSql('ALTER TABLE userApp ALTER roles DROP NOT NULL');
|
||||||
|
}
|
||||||
|
}
|
40
migrations/Version20241121141722.php
Normal file
40
migrations/Version20241121141722.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20241121141722 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE userapp ALTER first_name DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE userapp ALTER last_name DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE userapp ALTER tel DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE userapp ALTER address DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE userapp ALTER mail DROP NOT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE SCHEMA public');
|
||||||
|
$this->addSql('ALTER TABLE userApp ALTER first_name SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE userApp ALTER last_name SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE userApp ALTER tel SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE userApp ALTER address SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE userApp ALTER mail SET NOT NULL');
|
||||||
|
}
|
||||||
|
}
|
31
migrations/Version20241121141818.php
Normal file
31
migrations/Version20241121141818.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20241121141818 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE SCHEMA public');
|
||||||
|
}
|
||||||
|
}
|
32
migrations/Version20241121141912.php
Normal file
32
migrations/Version20241121141912.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20241121141912 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE userapp ALTER is_verified DROP NOT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE SCHEMA public');
|
||||||
|
$this->addSql('ALTER TABLE userApp ALTER is_verified SET NOT NULL');
|
||||||
|
}
|
||||||
|
}
|
34
migrations/Version20241121142119.php
Normal file
34
migrations/Version20241121142119.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20241121142119 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE intern ALTER cover_letter DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE intern ALTER resume DROP NOT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE SCHEMA public');
|
||||||
|
$this->addSql('ALTER TABLE intern ALTER cover_letter SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE intern ALTER resume SET NOT NULL');
|
||||||
|
}
|
||||||
|
}
|
31
migrations/Version20241121142432.php
Normal file
31
migrations/Version20241121142432.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20241121142432 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE SCHEMA public');
|
||||||
|
}
|
||||||
|
}
|
32
migrations/Version20241121145353.php
Normal file
32
migrations/Version20241121145353.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20241121145353 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE employee ALTER company_id DROP NOT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE SCHEMA public');
|
||||||
|
$this->addSql('ALTER TABLE employee ALTER company_id SET NOT NULL');
|
||||||
|
}
|
||||||
|
}
|
7
public/js/map.js
Normal file
7
public/js/map.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<script src="{{ asset('js/map.js') }}"></script>
|
||||||
|
|
||||||
|
// initialize the map on the "map" div with a given center and zoom
|
||||||
|
var map = L.map('map', {
|
||||||
|
center: [51.505, -0.09],
|
||||||
|
zoom: 13
|
||||||
|
});
|
@ -20,7 +20,6 @@ final class AnnouncementController extends AbstractController
|
|||||||
$user = $this->getUser();
|
$user = $this->getUser();
|
||||||
$announcements = [];
|
$announcements = [];
|
||||||
|
|
||||||
// Récupérer les paramètres de recherche
|
|
||||||
$companyName = $request->query->get('company_name');
|
$companyName = $request->query->get('company_name');
|
||||||
$location = $request->query->get('location');
|
$location = $request->query->get('location');
|
||||||
$category = $request->query->get('category');
|
$category = $request->query->get('category');
|
||||||
@ -47,18 +46,27 @@ final class AnnouncementController extends AbstractController
|
|||||||
$announcements = $announcementRepository->findBy(['status' => 'Verified']);
|
$announcements = $announcementRepository->findBy(['status' => 'Verified']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filtrer les annonces en fonction des critères de recherche
|
|
||||||
if ($companyName || $location || $category) {
|
if ($companyName || $location || $category) {
|
||||||
$announcements = $announcementRepository->searchAnnouncements($companyName, $location, $category);
|
$announcements = $announcementRepository->searchAnnouncements($companyName, $location, $category);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$favorites = [];
|
||||||
|
if (in_array('ROLE_INTERN', $user->getRoles())) {
|
||||||
|
$favorites = array_map(
|
||||||
|
fn($f) => $f->getAnnouncement()->getId(),
|
||||||
|
$user->getFavorites()->toArray()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->render('announcement/index.html.twig', [
|
return $this->render('announcement/index.html.twig', [
|
||||||
'announcements' => $announcements,
|
'announcements' => $announcements,
|
||||||
|
'favorites' => $favorites,
|
||||||
'showNonValidated' => $request->query->get('show_non_validated', false),
|
'showNonValidated' => $request->query->get('show_non_validated', false),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[Route('/new', name: 'app_announcement_new', methods: ['GET', 'POST'])]
|
#[Route('/new', name: 'app_announcement_new', methods: ['GET', 'POST'])]
|
||||||
public function new(Request $request, EntityManagerInterface $entityManager): Response
|
public function new(Request $request, EntityManagerInterface $entityManager): Response
|
||||||
{
|
{
|
||||||
|
@ -3,8 +3,11 @@
|
|||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Entity\Employee;
|
use App\Entity\Employee;
|
||||||
|
use App\Entity\InternApplication;
|
||||||
use App\Form\EmployeeType;
|
use App\Form\EmployeeType;
|
||||||
|
use App\Repository\AnnouncementRepository;
|
||||||
use App\Repository\EmployeeRepository;
|
use App\Repository\EmployeeRepository;
|
||||||
|
use App\Repository\InternApplicationRepository;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
@ -14,15 +17,23 @@ use Symfony\Component\Routing\Attribute\Route;
|
|||||||
#[Route('/employee')]
|
#[Route('/employee')]
|
||||||
final class EmployeeController extends AbstractController
|
final class EmployeeController extends AbstractController
|
||||||
{
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly EntityManagerInterface $entityManager,
|
||||||
|
private readonly EmployeeRepository $employeeRepository,
|
||||||
|
private readonly AnnouncementRepository $announcementRepository,
|
||||||
|
private readonly InternApplicationRepository $internApplicationRepository
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
#[Route(name: 'app_employee_index', methods: ['GET'])]
|
#[Route(name: 'app_employee_index', methods: ['GET'])]
|
||||||
public function index(EmployeeRepository $employeeRepository): Response
|
public function index(): Response
|
||||||
{
|
{
|
||||||
return $this->render('employee/index.html.twig', [
|
return $this->render('employee/index.html.twig', [
|
||||||
'employees' => $employeeRepository->findAll(),
|
'employees' => $this->employeeRepository->findAll(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/{id}', name: 'app_employee_show', methods: ['GET'])]
|
#[Route('/{id}', name: 'app_employee_show', requirements: ['id' => '\d+'], methods: ['GET'])]
|
||||||
public function show(Employee $employee): Response
|
public function show(Employee $employee): Response
|
||||||
{
|
{
|
||||||
return $this->render('employee/show.html.twig', [
|
return $this->render('employee/show.html.twig', [
|
||||||
@ -30,14 +41,14 @@ final class EmployeeController extends AbstractController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/{id}/edit', name: 'app_employee_edit', methods: ['GET', 'POST'])]
|
#[Route('/{id}/edit', name: 'app_employee_edit', requirements: ['id' => '\d+'], methods: ['GET', 'POST'])]
|
||||||
public function edit(Request $request, Employee $employee, EntityManagerInterface $entityManager): Response
|
public function edit(Request $request, Employee $employee): Response
|
||||||
{
|
{
|
||||||
$form = $this->createForm(EmployeeType::class, $employee);
|
$form = $this->createForm(EmployeeType::class, $employee);
|
||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
|
|
||||||
if ($form->isSubmitted() && $form->isValid()) {
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
$entityManager->flush();
|
$this->entityManager->flush();
|
||||||
|
|
||||||
return $this->redirectToRoute('app_employee_index', [], Response::HTTP_SEE_OTHER);
|
return $this->redirectToRoute('app_employee_index', [], Response::HTTP_SEE_OTHER);
|
||||||
}
|
}
|
||||||
@ -48,14 +59,38 @@ final class EmployeeController extends AbstractController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/{id}', name: 'app_employee_delete', methods: ['POST'])]
|
#[Route('/{id}', name: 'app_employee_delete', requirements: ['id' => '\d+'], methods: ['POST'])]
|
||||||
public function delete(Request $request, Employee $employee, EntityManagerInterface $entityManager): Response
|
public function delete(Request $request, Employee $employee): Response
|
||||||
{
|
{
|
||||||
if ($this->isCsrfTokenValid('delete'.$employee->getId(), $request->getPayload()->getString('_token'))) {
|
if ($this->isCsrfTokenValid('delete'.$employee->getId(), $request->getPayload()->getString('_token'))) {
|
||||||
$entityManager->remove($employee);
|
$this->entityManager->remove($employee);
|
||||||
$entityManager->flush();
|
$this->entityManager->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->redirectToRoute('app_employee_index', [], Response::HTTP_SEE_OTHER);
|
return $this->redirectToRoute('app_employee_index', [], Response::HTTP_SEE_OTHER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route('/seeApplications', name: 'app_employee_seeApplications')]
|
||||||
|
public function seeApplications(): Response
|
||||||
|
{
|
||||||
|
$employee = $this->getUser();
|
||||||
|
|
||||||
|
if (!$employee instanceof Employee){
|
||||||
|
throw $this->createAccessDeniedException('Seuls les employés peuvent accéder à cette page.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$company = $employee->getCompany();
|
||||||
|
|
||||||
|
$announcements = $this->announcementRepository
|
||||||
|
->findBy(['company' => $company]);
|
||||||
|
|
||||||
|
$applications = $this->internApplicationRepository
|
||||||
|
->findBy(['application' => $announcements]);
|
||||||
|
|
||||||
|
return $this->render('employee/applications.html.twig', [
|
||||||
|
'applications' => $applications,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,13 @@
|
|||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Entity\Announcement;
|
||||||
use App\Entity\Degree;
|
use App\Entity\Degree;
|
||||||
use App\Entity\Intern;
|
use App\Entity\Intern;
|
||||||
|
use App\Entity\InternApplication;
|
||||||
use App\Entity\InternDegree;
|
use App\Entity\InternDegree;
|
||||||
|
use App\Entity\InternSkill;
|
||||||
|
use App\Entity\Skill;
|
||||||
use App\Form\InternType;
|
use App\Form\InternType;
|
||||||
use App\Repository\InternRepository;
|
use App\Repository\InternRepository;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
@ -108,4 +112,86 @@ final class InternController extends AbstractController
|
|||||||
|
|
||||||
return $this->redirectToRoute('app_profile');
|
return $this->redirectToRoute('app_profile');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route('/application/send', name:'app_intern_send_application', methods:['POST'])]
|
||||||
|
public function sendApplication(Request $request, EntityManagerInterface $entityManager): Response
|
||||||
|
{
|
||||||
|
$intern = $this->getUser();
|
||||||
|
if (!$intern instanceof Intern) {
|
||||||
|
throw $this->createAccessDeniedException("Seuls les stagiaires peuvent envoyer des candidatures.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$announcementRepository = $entityManager->getRepository(Announcement::class);
|
||||||
|
$internApplicationRepository = $entityManager->getRepository(InternApplication::class);
|
||||||
|
|
||||||
|
$announcementId = $request->request->get('announcement_id');
|
||||||
|
$announcement = $announcementRepository->find($announcementId);
|
||||||
|
|
||||||
|
$existingInternApplication = $internApplicationRepository->findOneBy([
|
||||||
|
'intern' => $intern,
|
||||||
|
'application' => $announcement
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!$existingInternApplication) {
|
||||||
|
$internApplication = new InternApplication();
|
||||||
|
$internApplication->setIntern($intern);
|
||||||
|
$internApplication->setApplication($announcement);
|
||||||
|
$internApplication->setApplicationDate(new \DateTime());
|
||||||
|
$internApplication->setStatus("En Attente");
|
||||||
|
|
||||||
|
$entityManager->persist($internApplication);
|
||||||
|
}
|
||||||
|
$entityManager->flush();
|
||||||
|
|
||||||
|
$this->addFlash('success', 'La candidature à bien été envoyée.');
|
||||||
|
|
||||||
|
return $this->redirectToRoute('app_profile');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/skills/add', name:'app_intern_add_skills', methods:['POST'])]
|
||||||
|
public function addSkills(Request $request, EntityManagerInterface $entityManager): Response
|
||||||
|
{
|
||||||
|
$intern = $this->getUser();
|
||||||
|
|
||||||
|
if (!$intern instanceof Intern) {
|
||||||
|
throw $this->createAccessDeniedException("Seuls les stagiaires peuvent sélectionner des compétences.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$selectedSkillIds = $request->request->all('selected_skills');
|
||||||
|
|
||||||
|
if ($selectedSkillIds == []) {
|
||||||
|
$this->addFlash('error', "Aucune sélection valide n'a été effectuée.");
|
||||||
|
return $this->redirectToRoute('app_skill_index');
|
||||||
|
}
|
||||||
|
|
||||||
|
$skillRepository = $entityManager->getRepository(Skill::class);
|
||||||
|
$internSkillRepository = $entityManager->getRepository(InternSkill::class);
|
||||||
|
|
||||||
|
foreach ($selectedSkillIds as $skillId) {
|
||||||
|
$skill = $skillRepository->find($skillId);
|
||||||
|
|
||||||
|
if (!$skill) continue;
|
||||||
|
|
||||||
|
$existingInternSkill = $internSkillRepository->findOneBy([
|
||||||
|
'intern' => $intern,
|
||||||
|
'skill' => $skill
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!$existingInternSkill) {
|
||||||
|
$internSkill = new InternSkill();
|
||||||
|
$internSkill->setIntern($intern);
|
||||||
|
$internSkill->setSkill($skill);
|
||||||
|
|
||||||
|
$entityManager->persist($internSkill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$entityManager->flush();
|
||||||
|
|
||||||
|
$this->addFlash('success', 'Les compétences ont été ajoutées avec succès.');
|
||||||
|
|
||||||
|
return $this->redirectToRoute('app_profile');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
136
src/Controller/InternFavoriteController.php
Normal file
136
src/Controller/InternFavoriteController.php
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Entity\Announcement;
|
||||||
|
use App\Entity\Intern;
|
||||||
|
use App\Entity\InternFavorite;
|
||||||
|
use App\Repository\InternFavoriteRepository;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Bundle\SecurityBundle\Security;
|
||||||
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class InternFavoriteController extends AbstractController
|
||||||
|
{
|
||||||
|
#[Route('/favorite/toggle/{id}', name: 'toggle_favorite')]
|
||||||
|
public function toggleFavorite(
|
||||||
|
Announcement $announcement,
|
||||||
|
EntityManagerInterface $em,
|
||||||
|
InternFavoriteRepository $repo
|
||||||
|
): RedirectResponse {
|
||||||
|
$intern = $this->getUser()->getIntern();
|
||||||
|
|
||||||
|
$existing = $repo->findOneBy([
|
||||||
|
'intern' => $intern,
|
||||||
|
'announcement' => $announcement
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($existing) {
|
||||||
|
$em->remove($existing);
|
||||||
|
} else {
|
||||||
|
$favorite = new InternFavorite();
|
||||||
|
$favorite->setIntern($intern);
|
||||||
|
$favorite->setAnnouncement($announcement);
|
||||||
|
$em->persist($favorite);
|
||||||
|
}
|
||||||
|
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
return $this->redirectToRoute('app_announcement_index');
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/announcement/{id}/favorite/toggle', name: 'app_favorite_toggle', methods: ['POST'])]
|
||||||
|
public function toggle(Announcement $announcement, EntityManagerInterface $em, Security $security): RedirectResponse
|
||||||
|
{
|
||||||
|
$user = $security->getUser();
|
||||||
|
|
||||||
|
if (!$user instanceof Intern) {
|
||||||
|
throw new AccessDeniedHttpException('Seuls les stagiaires peuvent ajouter aux favoris.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$favorite = $em->getRepository(InternFavorite::class)->findOneBy([
|
||||||
|
'intern' => $user,
|
||||||
|
'announcement' => $announcement
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($favorite) {
|
||||||
|
$em->remove($favorite);
|
||||||
|
} else {
|
||||||
|
$favorite = new InternFavorite();
|
||||||
|
$favorite->setIntern($user);
|
||||||
|
$favorite->setAnnouncement($announcement);
|
||||||
|
$em->persist($favorite);
|
||||||
|
}
|
||||||
|
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
return new RedirectResponse($_SERVER['HTTP_REFERER'] ?? '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/announcement/{id}', name: 'app_announcement_show')]
|
||||||
|
public function show(Announcement $announcement, InternFavoriteRepository $internFavoriteRepository): Response
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
$isFavorite = false;
|
||||||
|
|
||||||
|
if (in_array('ROLE_INTERN', $user->getRoles())) {
|
||||||
|
$favorite = $internFavoriteRepository->findOneBy([
|
||||||
|
'announcement' => $announcement,
|
||||||
|
'intern' => $user,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$isFavorite = $favorite ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->render('announcement/show.html.twig', [
|
||||||
|
'announcement' => $announcement,
|
||||||
|
'isFavorite' => $isFavorite,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/favorite/add/{id}', name: 'app_favorite_add')]
|
||||||
|
public function addFavorite(Announcement $announcement, EntityManagerInterface $entityManager): Response
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
// Vérifier si l'intern a déjà ce favori
|
||||||
|
$existingFavorite = $entityManager->getRepository(InternFavorite::class)->findOneBy([
|
||||||
|
'announcement' => $announcement,
|
||||||
|
'intern' => $user,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!$existingFavorite) {
|
||||||
|
$favorite = new InternFavorite();
|
||||||
|
$favorite->setAnnouncement($announcement);
|
||||||
|
$favorite->setIntern($user);
|
||||||
|
|
||||||
|
$entityManager->persist($favorite);
|
||||||
|
$entityManager->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->redirectToRoute('app_announcement_show', ['id' => $announcement->getId()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/favorite/remove/{id}', name: 'app_favorite_remove')]
|
||||||
|
public function removeFavorite(Announcement $announcement, EntityManagerInterface $entityManager): Response
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
$favorite = $entityManager->getRepository(InternFavorite::class)->findOneBy([
|
||||||
|
'announcement' => $announcement,
|
||||||
|
'intern' => $user,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($favorite) {
|
||||||
|
$entityManager->remove($favorite);
|
||||||
|
$entityManager->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->redirectToRoute('app_announcement_show', ['id' => $announcement->getId()]);
|
||||||
|
}
|
||||||
|
}
|
@ -2,8 +2,12 @@
|
|||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Entity\Announcement;
|
||||||
|
use App\Entity\Intern;
|
||||||
|
use App\Entity\InternApplication;
|
||||||
use App\Entity\UserApp;
|
use App\Entity\UserApp;
|
||||||
use App\Form\UserAppType;
|
use App\Form\UserAppType;
|
||||||
|
use App\Repository\SkillRepository;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
@ -13,7 +17,7 @@ use Symfony\Component\Routing\Attribute\Route;
|
|||||||
class ProfileController extends AbstractController
|
class ProfileController extends AbstractController
|
||||||
{
|
{
|
||||||
#[Route('/profile', name: 'app_profile')]
|
#[Route('/profile', name: 'app_profile')]
|
||||||
public function profile(): Response
|
public function profile(EntityManagerInterface $entityManager): Response
|
||||||
{
|
{
|
||||||
$user = $this->getUser();
|
$user = $this->getUser();
|
||||||
|
|
||||||
@ -21,8 +25,23 @@ class ProfileController extends AbstractController
|
|||||||
throw $this->createAccessDeniedException('Vous devez être connecté pour accéder à cette page.');
|
throw $this->createAccessDeniedException('Vous devez être connecté pour accéder à cette page.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($user instanceof Intern)
|
||||||
|
{
|
||||||
|
$internApplicationRepository = $entityManager->getRepository(InternApplication::class);
|
||||||
|
|
||||||
|
$internApplications = $internApplicationRepository->findBy([
|
||||||
|
'intern' => $user,
|
||||||
|
]);
|
||||||
|
|
||||||
return $this->render('profile/index.html.twig', [
|
return $this->render('profile/index.html.twig', [
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
|
'applications' => $internApplications
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->render('profile/index.html.twig', [
|
||||||
|
'user' => $user,
|
||||||
|
'applications' => []
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +63,21 @@ class ProfileController extends AbstractController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route('/profile/{id}/visit', name: 'app_profile_visit')]
|
||||||
|
public function visitProfile(EntityManagerInterface $entityManager, int $id): Response
|
||||||
|
{
|
||||||
|
$user = $entityManager->getRepository(Intern::class)->find($id);
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
throw $this->createNotFoundException('Utilisateur non trouvé.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->render('profile/index.html.twig', [
|
||||||
|
'user' => $user,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[Route('profile/pickDegree', name: 'app_profile_pickDegree', methods: ['GET'])]
|
#[Route('profile/pickDegree', name: 'app_profile_pickDegree', methods: ['GET'])]
|
||||||
public function pickDegree(UserApp $userApp): Response
|
public function pickDegree(UserApp $userApp): Response
|
||||||
{
|
{
|
||||||
@ -51,4 +85,16 @@ class ProfileController extends AbstractController
|
|||||||
'user_app' => $userApp,
|
'user_app' => $userApp,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route('/profile/pickSkill', name: 'app_profile_pickSkill', methods: ['GET'])]
|
||||||
|
public function pickSkill(UserApp $userApp): Response
|
||||||
|
{
|
||||||
|
|
||||||
|
return $this->render('skill/index.html.twig', [
|
||||||
|
'user_app' => $userApp,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use App\Entity\UserApp;
|
||||||
|
use App\Entity\Announcement;
|
||||||
use App\Repository\FavorisRepository;
|
use App\Repository\FavorisRepository;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
@ -13,15 +15,38 @@ class Favoris
|
|||||||
#[ORM\Column]
|
#[ORM\Column]
|
||||||
private ?int $id = null;
|
private ?int $id = null;
|
||||||
|
|
||||||
|
#[ORM\ManyToOne(inversedBy: 'favoris')]
|
||||||
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
|
private ?UserApp $user = null;
|
||||||
|
|
||||||
|
#[ORM\ManyToOne(inversedBy: 'favoris')]
|
||||||
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
|
private ?Announcement $announcement = null;
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
{
|
{
|
||||||
return $this->id;
|
return $this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setId(int $id): static
|
public function getUser(): ?UserApp
|
||||||
{
|
{
|
||||||
$this->id = $id;
|
return $this->user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser(?UserApp $user): static
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAnnouncement(): ?Announcement
|
||||||
|
{
|
||||||
|
return $this->announcement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAnnouncement(?Announcement $announcement): static
|
||||||
|
{
|
||||||
|
$this->announcement = $announcement;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,9 @@ class InternApplication
|
|||||||
#[ORM\Column(type: Types::DATE_MUTABLE)]
|
#[ORM\Column(type: Types::DATE_MUTABLE)]
|
||||||
private ?\DateTimeInterface $applicationDate = null;
|
private ?\DateTimeInterface $applicationDate = null;
|
||||||
|
|
||||||
|
#[ORM\Column(length: 20)]
|
||||||
|
private ?string $status = null;
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
{
|
{
|
||||||
return $this->id;
|
return $this->id;
|
||||||
@ -63,4 +66,14 @@ class InternApplication
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getStatus(): ?string
|
||||||
|
{
|
||||||
|
return $this->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStatus(?string $status): void
|
||||||
|
{
|
||||||
|
$this->status = $status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
25
src/Form/ResetPasswordRequestFormType.php
Normal file
25
src/Form/ResetPasswordRequestFormType.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Form;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
class ResetPasswordRequestFormType extends AbstractType
|
||||||
|
{
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||||
|
{
|
||||||
|
$builder
|
||||||
|
->add('email', EmailType::class)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
// Configure your form options here
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
60
src/Security/UserAuthenticator.php
Normal file
60
src/Security/UserAuthenticator.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Security;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||||
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
|
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
|
||||||
|
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
|
||||||
|
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
|
||||||
|
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||||
|
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
|
||||||
|
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||||
|
use Symfony\Component\Security\Http\SecurityRequestAttributes;
|
||||||
|
use Symfony\Component\Security\Http\Util\TargetPathTrait;
|
||||||
|
|
||||||
|
class UserAuthenticator extends AbstractLoginFormAuthenticator
|
||||||
|
{
|
||||||
|
use TargetPathTrait;
|
||||||
|
|
||||||
|
public const LOGIN_ROUTE = 'app_login';
|
||||||
|
|
||||||
|
public function __construct(private UrlGeneratorInterface $urlGenerator)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authenticate(Request $request): Passport
|
||||||
|
{
|
||||||
|
$nickname = $request->getPayload()->getString('nickname');
|
||||||
|
|
||||||
|
$request->getSession()->set(SecurityRequestAttributes::LAST_USERNAME, $nickname);
|
||||||
|
|
||||||
|
return new Passport(
|
||||||
|
new UserBadge($nickname),
|
||||||
|
new PasswordCredentials($request->getPayload()->getString('password')),
|
||||||
|
[
|
||||||
|
new CsrfTokenBadge('authenticate', $request->getPayload()->getString('_csrf_token')),
|
||||||
|
new RememberMeBadge(),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||||
|
{
|
||||||
|
if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
|
||||||
|
return new RedirectResponse($targetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For example:
|
||||||
|
return new RedirectResponse($this->urlGenerator->generate('index'));
|
||||||
|
//throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getLoginUrl(Request $request): string
|
||||||
|
{
|
||||||
|
return $this->urlGenerator->generate(self::LOGIN_ROUTE);
|
||||||
|
}
|
||||||
|
}
|
@ -288,6 +288,9 @@
|
|||||||
"config/packages/messenger.yaml"
|
"config/packages/messenger.yaml"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"symfonycasts/sass-bundle": {
|
||||||
|
"version": "v0.7.0"
|
||||||
|
},
|
||||||
"twig/extra-bundle": {
|
"twig/extra-bundle": {
|
||||||
"version": "v3.13.0"
|
"version": "v3.13.0"
|
||||||
}
|
}
|
||||||
|
@ -7,26 +7,16 @@
|
|||||||
<h1 class="text-3xl font-bold mb-6 text-center">Liste des Annonces</h1>
|
<h1 class="text-3xl font-bold mb-6 text-center">Liste des Annonces</h1>
|
||||||
|
|
||||||
{% if 'ROLE_ADMIN' in app.user.roles %}
|
{% if 'ROLE_ADMIN' in app.user.roles %}
|
||||||
<!-- Formulaire pour afficher uniquement les annonces non validées -->
|
|
||||||
<form method="get" class="mb-6 text-center">
|
<form method="get" class="mb-6 text-center">
|
||||||
<label class="flex items-center justify-center space-x-2">
|
<label class="flex items-center justify-center space-x-2">
|
||||||
<input
|
<input type="checkbox" name="show_non_validated" value="1" {% if showNonValidated %}checked{% endif %} class="rounded text-teal-500">
|
||||||
type="checkbox"
|
|
||||||
name="show_non_validated"
|
|
||||||
value="1"
|
|
||||||
{% if showNonValidated %}checked{% endif %}
|
|
||||||
class="rounded text-teal-500"
|
|
||||||
>
|
|
||||||
<span class="text-gray-700">Afficher uniquement les annonces non validées</span>
|
<span class="text-gray-700">Afficher uniquement les annonces non validées</span>
|
||||||
</label>
|
</label>
|
||||||
<button type="submit" class="ml-4 bg-teal-500 text-white px-4 py-2 rounded mt-2">
|
<button type="submit" class="ml-4 bg-teal-500 text-white px-4 py-2 rounded mt-2">Appliquer</button>
|
||||||
Appliquer
|
|
||||||
</button>
|
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if 'ROLE_EMPLOYEE' in app.user.roles %}
|
{% if 'ROLE_EMPLOYEE' in app.user.roles %}
|
||||||
<!-- Bouton pour créer une annonce -->
|
|
||||||
<div class="text-center mb-6">
|
<div class="text-center mb-6">
|
||||||
<a href="{{ path('app_announcement_new') }}" class="bg-teal-500 text-white px-6 py-3 rounded-md hover:bg-teal-600">
|
<a href="{{ path('app_announcement_new') }}" class="bg-teal-500 text-white px-6 py-3 rounded-md hover:bg-teal-600">
|
||||||
Créer une annonce
|
Créer une annonce
|
||||||
@ -34,57 +24,49 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Liste des annonces -->
|
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="bg-white rounded-lg shadow-lg p-6 inline-block text-center my-10">
|
<div class="bg-white rounded-lg shadow-lg p-6 inline-block text-center my-10">
|
||||||
<form method="get" class="flex flex-col md:flex-row space-y-4 md:space-y-0 md:space-x-4 text-black">
|
<form method="get" class="flex flex-col md:flex-row space-y-4 md:space-y-0 md:space-x-4 text-black">
|
||||||
<label>
|
|
||||||
<input class="border border-gray-300 rounded py-2 px-4 w-full md:w-auto" placeholder="Rechercher par entreprise" type="text" name="company_name" value="{{ app.request.query.get('company_name') }}"/>
|
<input class="border border-gray-300 rounded py-2 px-4 w-full md:w-auto" placeholder="Rechercher par entreprise" type="text" name="company_name" value="{{ app.request.query.get('company_name') }}"/>
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
<input class="border border-gray-300 rounded py-2 px-4 w-full md:w-auto" placeholder="Rechercher par lieu" type="text" name="location" value="{{ app.request.query.get('location') }}"/>
|
<input class="border border-gray-300 rounded py-2 px-4 w-full md:w-auto" placeholder="Rechercher par lieu" type="text" name="location" value="{{ app.request.query.get('location') }}"/>
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
<input class="border border-gray-300 rounded py-2 px-4 w-full md:w-auto" placeholder="Autre recherche" type="text" name="category" value="{{ app.request.query.get('category') }}"/>
|
<input class="border border-gray-300 rounded py-2 px-4 w-full md:w-auto" placeholder="Autre recherche" type="text" name="category" value="{{ app.request.query.get('category') }}"/>
|
||||||
</label>
|
|
||||||
<button type="submit" class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-6 rounded">Rechercher</button>
|
<button type="submit" class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-6 rounded">Rechercher</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% for announcement in announcements %}
|
{% for announcement in announcements %}
|
||||||
<div class="bg-white p-6 rounded-lg shadow mb-4 relative">
|
<div class="bg-white p-6 rounded-lg shadow mb-4 relative">
|
||||||
<!-- Statut en haut à droite -->
|
<div class="absolute top-4 right-4 flex items-center space-x-2">
|
||||||
<div class="absolute top-4 right-4">
|
|
||||||
{% if announcement.status == 'notVerified' %}
|
{% if announcement.status == 'notVerified' %}
|
||||||
<span class="text-red-500 font-semibold">Non validée</span>
|
<span class="text-red-500 font-semibold">Non validée</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="text-green-500 font-semibold">Validée</span>
|
<span class="text-green-500 font-semibold">Validée</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<form method="post" action="{{ path('app_favorite_toggle', {id: announcement.id}) }}">
|
||||||
|
<button type="submit" class="text-xl">
|
||||||
|
{% if announcement.id in favorites %}
|
||||||
|
⭐
|
||||||
|
{% else %}
|
||||||
|
☆
|
||||||
|
{% endif %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Titre de l'annonce -->
|
|
||||||
<h2 class="text-3xl font-semibold mb-2">{{ announcement.title }}</h2>
|
<h2 class="text-3xl font-semibold mb-2">{{ announcement.title }}</h2>
|
||||||
|
|
||||||
<!-- Nom de l'entreprise -->
|
|
||||||
<p class="text-gray-600 mb-2">{{ announcement.company.name }}</p>
|
<p class="text-gray-600 mb-2">{{ announcement.company.name }}</p>
|
||||||
|
|
||||||
<div class="text-gray-500 text-sm mb-4">
|
<div class="text-gray-500 text-sm mb-4">
|
||||||
<!-- Date du stage -->
|
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<i class="fas fa-calendar-alt mr-1"></i>
|
<i class="fas fa-calendar-alt mr-1"></i> <span>Date du stage : {{ announcement.date }}</span>
|
||||||
<span>Date du stage : {{ announcement.date }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Adresse de l'entreprise -->
|
|
||||||
<div>
|
<div>
|
||||||
<i class="fas fa-map-marker-alt mr-1"></i>
|
<i class="fas fa-map-marker-alt mr-1"></i> <span>{{ announcement.company.address }}</span>
|
||||||
<span>{{ announcement.company.address }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Lien vers la page de détails -->
|
<a href="{{ path('app_announcement_show', { id: announcement.id }) }}" class="bg-teal-500 text-white px-4 py-2 rounded">
|
||||||
<a href="{{ path('app_announcement_show', { id: announcement.id }) }}"
|
|
||||||
class="bg-teal-500 text-white px-4 py-2 rounded">
|
|
||||||
Détails
|
Détails
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -94,4 +76,3 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
@ -52,6 +52,15 @@
|
|||||||
<span>{{ announcement.creationDate | date('d/m/Y') }}</span>
|
<span>{{ announcement.creationDate | date('d/m/Y') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if 'ROLE_INTERN' in app.user.roles %}
|
||||||
|
<form method="post" action="{{ path('app_intern_send_application') }}">
|
||||||
|
<input type="hidden" name="announcement_id" value="{{ announcement.id }}">
|
||||||
|
<button type="submit" class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded">
|
||||||
|
<i class="fas fa-paper-plane"></i> Candidater à cette offre
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if 'ROLE_ADMIN' in app.user.roles %}
|
{% if 'ROLE_ADMIN' in app.user.roles %}
|
||||||
|
|
||||||
<!-- Boutons Modifier et Valider -->
|
<!-- Boutons Modifier et Valider -->
|
||||||
@ -71,6 +80,16 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<!-- Vérifier si c'est un favori -->
|
||||||
|
<form method="post" action="{{ path(isFavorite ? 'app_favorite_remove' : 'app_favorite_add', {id: announcement.id}) }}">
|
||||||
|
<button type="submit" class="text-yellow-500">
|
||||||
|
{% if isFavorite %}
|
||||||
|
⭐ Retirer des favoris
|
||||||
|
{% else %}
|
||||||
|
☆ Ajouter aux favoris
|
||||||
|
{% endif %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Bouton de retour à la liste -->
|
<!-- Bouton de retour à la liste -->
|
||||||
|
@ -28,7 +28,8 @@
|
|||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
{% if 'ROLE_INTERN' in app.user.roles %}
|
{% if 'ROLE_INTERN' in app.user.roles %}
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" name="selected_degrees[]" value="{{ degree.id }}" class="mr-2">
|
<input type="checkbox" name="selected_degrees[]" value="{{ degree.id }}"
|
||||||
|
class="mr-2">
|
||||||
Sélectionner
|
Sélectionner
|
||||||
</label>
|
</label>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -67,7 +68,8 @@
|
|||||||
{% if 'ROLE_ADMIN' in app.user.roles %}
|
{% if 'ROLE_ADMIN' in app.user.roles %}
|
||||||
<!-- Lien pour ajouter un nouveau diplôme -->
|
<!-- Lien pour ajouter un nouveau diplôme -->
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<a href="{{ path('app_degree_new') }}" class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4 rounded-full">
|
<a href="{{ path('app_degree_new') }}" class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4
|
||||||
|
rounded-full">
|
||||||
<i class="fas fa-plus-circle"></i> Ajouter un nouveau diplôme
|
<i class="fas fa-plus-circle"></i> Ajouter un nouveau diplôme
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
24
templates/employee/applications.html.twig
Normal file
24
templates/employee/applications.html.twig
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}Liste des Candidatures{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<h2 class="text-2xl font-bold mb-6">Candidatures reçues</h2>
|
||||||
|
|
||||||
|
{% for app in applications %}
|
||||||
|
<div class="border border-gray-300 rounded-lg p-4 mb-4 shadow-sm bg-white">
|
||||||
|
<p><strong>Annonce :</strong> {{ app.application.title }}</p>
|
||||||
|
<p><strong>Candidat :</strong> {{ app.intern.firstName }} {{ app.intern.lastName }}</p>
|
||||||
|
<p><strong>Date :</strong> {{ app.applicationDate|date('d/m/Y') }}</p>
|
||||||
|
<p><strong>Statut :</strong> {{ app.status }}</p>
|
||||||
|
|
||||||
|
<a href="{{ path('app_profile_visit', { id: app.intern.id }) }}"
|
||||||
|
class="inline-block mt-2 bg-teal-500 hover:bg-teal-600 text-white px-4 py-2 rounded">
|
||||||
|
Voir le profil du candidat
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<p>Aucune candidature pour le moment.</p>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -48,4 +48,18 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<h3 class="text-lg font-semibold mt-6">Vos compétences :</h3>
|
||||||
|
<ul class="list-disc list-inside text-gray-800">
|
||||||
|
{% if app.user.skills|length > 0 %}
|
||||||
|
{% for internSkill in app.user.skills %}
|
||||||
|
<li>{{ internSkill.skill.label }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<li>Aucune compétence sélectionnée</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4 rounded-full"
|
||||||
|
href="{{ path('app_profile_pickSkill') }}">Sélectionner vos compétences</a>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -8,6 +8,12 @@
|
|||||||
<p class="text-gray-600">Téléphone : {{ app.user.tel }}</p>
|
<p class="text-gray-600">Téléphone : {{ app.user.tel }}</p>
|
||||||
<p class="text-gray-600">Email : {{ app.user.mail }}</p>
|
<p class="text-gray-600">Email : {{ app.user.mail }}</p>
|
||||||
|
|
||||||
|
<a href="{{ path('app_employee_seeApplications') }}"
|
||||||
|
class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded">
|
||||||
|
Voir les candidatures reçues
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<div class="flex justify-end mt-6">
|
<div class="flex justify-end mt-6">
|
||||||
<a class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4 rounded-full"
|
<a class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4 rounded-full"
|
||||||
href="{{ path('app_profile_edit',{id: app.user.id}) }}"> Modifier
|
href="{{ path('app_profile_edit',{id: app.user.id}) }}"> Modifier
|
||||||
|
@ -27,8 +27,8 @@
|
|||||||
<h3 class="text-lg font-semibold mt-6">Vos compétences :</h3>
|
<h3 class="text-lg font-semibold mt-6">Vos compétences :</h3>
|
||||||
<ul class="list-disc list-inside text-gray-800">
|
<ul class="list-disc list-inside text-gray-800">
|
||||||
{% if app.user.skills|length > 0 %}
|
{% if app.user.skills|length > 0 %}
|
||||||
{% for comp in app.user.skills %}
|
{% for internSkill in app.user.skills %}
|
||||||
<li>{{ comp.label }}</li>
|
<li>{{ internSkill.skill.label }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<br>
|
<br>
|
||||||
@ -37,14 +37,34 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
<a class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4 rounded-full"
|
<a class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4 rounded-full"
|
||||||
href="{{ path('app_user_edit',{id: app.user.id}) }}"> Selectionner vos compétences
|
href="{{ path('app_skill_index',{id: app.user.id}) }}"> Sélectionner vos compétences
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<div class="flex justify-center mt-6">
|
<div class="flex justify-center mt-6">
|
||||||
<a class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4 rounded-full"
|
<a class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4 rounded-full"
|
||||||
href="{{ path('app_user_edit',{id: app.user.id}) }}"> Accéder aux favoris
|
href="{{ path('app_user_edit',{id: app.user.id}) }}"> Accéder aux favoris
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h3 class="text-lg font-semibold mt-6">Vos candidatures :</h3>
|
||||||
|
|
||||||
|
{% if applications|length > 0 %}
|
||||||
|
<ul class="space-y-4 mt-2">
|
||||||
|
{% for appli in applications %}
|
||||||
|
<div class="border border-gray-300 bg-gray-50 p-4 rounded-lg shadow-sm">
|
||||||
|
<p><strong>Offre :</strong> {{ appli.application.title }}</p>
|
||||||
|
<p><strong>Entreprise :</strong> {{ appli.application.company.name }}</p>
|
||||||
|
<p><strong>Date de candidature :</strong> {{ appli.applicationDate|date('d/m/Y') }}</p>
|
||||||
|
<p><strong>Statut :</strong> {{ appli.status }}</p>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
<p class="text-gray-600">Vous n'avez pas encore postulé à une offre.</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
<div class="flex justify-end mt-6">
|
<div class="flex justify-end mt-6">
|
||||||
<a class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4 rounded-full"
|
<a class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4 rounded-full"
|
||||||
href="{{ path('app_profile_edit',{id: app.user.id}) }}"> Modifier
|
href="{{ path('app_profile_edit',{id: app.user.id}) }}"> Modifier
|
||||||
|
52
templates/profile/visit.html.twig
Normal file
52
templates/profile/visit.html.twig
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}Profil du candidat{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<div class="max-w-3xl mx-auto mt-8 bg-white p-6 rounded-lg shadow-lg border border-gray-300">
|
||||||
|
<h2 class="text-2xl font-bold mb-4">Profil du candidat</h2>
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<p><strong>Nom :</strong> {{ user.lastName }}</p>
|
||||||
|
<p><strong>Prénom :</strong> {{ user.firstName }}</p>
|
||||||
|
<p><strong>Email :</strong> {{ user.mail }}</p>
|
||||||
|
<p><strong>Téléphone :</strong> {{ user.tel }}</p>
|
||||||
|
<p><strong>Adresse :</strong> {{ user.address }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<h3 class="text-xl font-semibold">Diplômes</h3>
|
||||||
|
<ul class="list-disc list-inside text-gray-800 mt-2">
|
||||||
|
{% if user.degrees|length > 0 %}
|
||||||
|
{% for deg in user.degrees %}
|
||||||
|
<li>
|
||||||
|
{{ deg.degree.label }} — Obtenu le {{ deg.graduationDate|date('d/m/Y') }}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<p class="text-gray-500 mt-2">Aucun diplôme renseigné.</p>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<h3 class="text-xl font-semibold">Compétences</h3>
|
||||||
|
<ul class="list-disc list-inside text-gray-800 mt-2">
|
||||||
|
{% if user.skills|length > 0 %}
|
||||||
|
{% for skill in user.skills %}
|
||||||
|
<li>{{ skill.label }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<p class="text-gray-500 mt-2">Aucune compétence renseignée.</p>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-6">
|
||||||
|
<a href="{{ path('app_index') }}"
|
||||||
|
class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4 rounded-full">
|
||||||
|
Retour à l'accueil
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
14
templates/security/reset_password_request.html.twig
Normal file
14
templates/security/reset_password_request.html.twig
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}Demande de réinitialisation de mot de passe{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<section>
|
||||||
|
<h1>Demande de réinitialisation de mot de passe</h1>
|
||||||
|
{{ form_start(requestPassForm) }}
|
||||||
|
{{ form_row(requestPassForm.email) }}
|
||||||
|
<button type="submit">Envoyer</button>
|
||||||
|
|
||||||
|
{{ form_end(requestPassForm) }}
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
@ -6,6 +6,11 @@
|
|||||||
<div class="container mx-auto p-6">
|
<div class="container mx-auto p-6">
|
||||||
<h1 class="text-3xl font-bold mb-4">Liste des Compétences</h1>
|
<h1 class="text-3xl font-bold mb-4">Liste des Compétences</h1>
|
||||||
|
|
||||||
|
{% if 'ROLE_INTERN' in app.user.roles %}
|
||||||
|
<form method="post" action="{{ path('app_intern_add_skills') }}">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Tableau des compétences -->
|
||||||
<div class="overflow-x-auto bg-white shadow-lg rounded-lg">
|
<div class="overflow-x-auto bg-white shadow-lg rounded-lg">
|
||||||
<table class="min-w-full table-auto">
|
<table class="min-w-full table-auto">
|
||||||
<thead>
|
<thead>
|
||||||
@ -21,14 +26,20 @@
|
|||||||
<td class="px-4 py-2">{{ skill.id }}</td>
|
<td class="px-4 py-2">{{ skill.id }}</td>
|
||||||
<td class="px-4 py-2">{{ skill.label }}</td>
|
<td class="px-4 py-2">{{ skill.label }}</td>
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
<a href="{{ path('app_skill_show', {'id': skill.id}) }}" class="text-teal-500 hover:text-teal-700 mr-3">
|
{% if 'ROLE_INTERN' in app.user.roles %}
|
||||||
<i class="fas fa-eye"></i> Voir
|
<label>
|
||||||
</a>
|
<input type="checkbox" name="selected_skills[]" value="{{ skill.id }}" class="mr-2">
|
||||||
|
Sélectionner
|
||||||
|
</label>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if 'ROLE_ADMIN' in app.user.roles %}
|
||||||
|
<!-- Modifier la compétence -->
|
||||||
<a href="{{ path('app_skill_edit', {'id': skill.id}) }}" class="text-yellow-500 hover:text-yellow-700 mr-3">
|
<a href="{{ path('app_skill_edit', {'id': skill.id}) }}" class="text-yellow-500 hover:text-yellow-700 mr-3">
|
||||||
<i class="fas fa-edit"></i> Modifier
|
<i class="fas fa-edit"></i> Modifier
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<!-- Supprimer la compétence -->
|
||||||
<form method="post" action="{{ path('app_skill_delete', {'id': skill.id}) }}" style="display:inline;">
|
<form method="post" action="{{ path('app_skill_delete', {'id': skill.id}) }}" style="display:inline;">
|
||||||
<input type="hidden" name="_method" value="DELETE">
|
<input type="hidden" name="_method" value="DELETE">
|
||||||
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ skill.id) }}">
|
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ skill.id) }}">
|
||||||
@ -36,6 +47,7 @@
|
|||||||
<i class="fas fa-trash-alt"></i> Supprimer
|
<i class="fas fa-trash-alt"></i> Supprimer
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -43,10 +55,21 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if 'ROLE_INTERN' in app.user.roles %}
|
||||||
|
<div class="mt-4">
|
||||||
|
<button type="submit" class="bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded-full">
|
||||||
|
<i class="fas fa-check-circle"></i> Valider la sélection
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if 'ROLE_ADMIN' in app.user.roles %}
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<a href="{{ path('app_skill_new') }}" class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4 rounded-full">
|
<a href="{{ path('app_skill_new') }}" class="bg-teal-500 hover:bg-teal-600 text-white py-2 px-4 rounded-full">
|
||||||
<i class="fas fa-plus-circle"></i> Ajouter une nouvelle compétence
|
<i class="fas fa-plus-circle"></i> Ajouter une compétence
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user