Compare commits

..

24 Commits

Author SHA1 Message Date
e376dadb4b add: composer
* add phpstan library and require extensions
2025-01-21 14:46:35 -05:00
b990ea55cb fix: twig
* couple display fixes
2025-01-21 14:46:03 -05:00
67d83a1f98 add: twig nav
* add company directory link
2025-01-21 14:44:39 -05:00
79db6b2ec9 fix: twig add-member
* add checkboxes for each company document
2025-01-21 14:43:55 -05:00
0c5fa617ad fix: twig list-users
* fix display of user profile
* add text muting if user is inactive
2025-01-21 14:43:20 -05:00
6effcba396 fix: twig edit-user
* fix background image display
* fix display for work and personal phone numbers
* add active checkbox
* fix displays for role checkboxes
2025-01-21 14:41:49 -05:00
43e6811928 fix: twig users
Fix user background image that displays left of the form
2025-01-21 14:40:01 -05:00
705d7330b0 add: twig company-info
Add new display
2025-01-21 14:38:49 -05:00
7bc73345b0 fix: twig couple files
* fix referralType display after converting to enum
2025-01-21 14:38:12 -05:00
610cccc191 fix: twig assign-case
* add number of cases to user list
2025-01-21 14:36:46 -05:00
a47a5e8adb fix: twig add-case
* fix display with admit and close dates
* convert referralType to use enum
* fix display for case level, referral source & 2, county
* remove case documents checkboxes
2025-01-21 14:35:53 -05:00
81838608b3 add: NavList
Add company_directory field
2025-01-21 14:32:32 -05:00
d39942eced fix: MemberCase
Migration for CaseDocuments to MemberDocuments
Convert referralType field to use ReferralType Enum
2025-01-21 14:32:04 -05:00
cdacfd918a fix: MessageFactory
Add link parameter to createNewCase method
2025-01-21 14:30:17 -05:00
922852f211 fix: User
various updates
* remove unnecessary caseWorker, caseManager, therapist, su properties
* Removed retrieveUnreadNotifications method that was just a stub
* convert "is..." methods to check for present roles
* update getJobs method with above logic
* add generateVCard method to support company directory
2025-01-21 14:29:31 -05:00
224a5cd243 add: MemberDocument
Add MemberDocument class and assoc repo
2025-01-21 14:25:00 -05:00
6d8fbd5bb8 fix: MemberCase
ReferralType
* Convert ReferralType in class to an Enum
2025-01-21 14:24:11 -05:00
82ee30a724 add: CompanyDocument
Add class
* Add CompanyDocument class, associated repo and twig files
2025-01-21 14:23:14 -05:00
e13dc0bf66 fix: MemberController
MemberDocument migration
* Migrate CaseDocument to MemberDocument
* Setup assigning a document to a case member when creating member
* Still need to fix member edit
2025-01-21 14:20:57 -05:00
844209d3e3 commit gitmessage template 2025-01-21 14:18:06 -05:00
001a674f6f fix: DocumentController
move case documents to member documents
first draft of signing
2025-01-21 14:13:19 -05:00
caeb15f05b add: CompanyController
Add company directory method
2025-01-21 14:11:40 -05:00
2af4b8e04e fix: CaseController
migrate documents to MemberController
add link to new case message
2025-01-21 14:09:21 -05:00
c04e255476 fix: AdminController
ensure new users are active
fix role assignments and remove unnecessary fields
fix supervision assignment to update the record instead of deleting
2025-01-21 14:08:12 -05:00
43 changed files with 1358 additions and 255 deletions

5
.gitmessage Normal file
View File

@ -0,0 +1,5 @@
{commit-type}: {module}
{description}
### Changes
* {change1}

View File

@ -102,8 +102,12 @@
}
},
"require-dev": {
"ext-dom": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"doctrine/doctrine-fixtures-bundle": "^4.0",
"fakerphp/faker": "^1.24",
"phpstan/phpstan": "^2.1",
"phpunit/phpunit": "^9.5",
"symfony/browser-kit": "7.2.*",
"symfony/css-selector": "7.2.*",

View File

@ -136,6 +136,7 @@ class AdminController extends AbstractController
->setRate($form->get('rate')->getData())
->setLevel($form->get('level')->getData())
->setCompany($admin->getCompany())
->setActive(true)
->setPasswordChanged(new DateTime('now', new DateTimeZone($_ENV['COMPANY_TIMEZONE'])))
;
@ -197,15 +198,31 @@ class AdminController extends AbstractController
$this->navLinks['user_list'] = NavList::PRESENT_LINK;
if ($form->isSubmitted() && $form->isValid()) {
$roles = ['ROLE_USER'];
if ($form->get('caseWorker')->getData()) {
$roles[] = 'ROLE_CASE_WORKER';
}
if ($form->get('caseManager')->getData()) {
$roles[] = 'ROLE_CASE_MANAGER';
}
if ($form->get('therapist')->getData()) {
$roles[] = 'ROLE_THERAPIST';
}
if ($form->get('su')->getData()) {
$roles[] = 'ROLE_ADMIN';
}
$user->setName($form->get('name')->getData())
->setEmail($form->get('email')->getData())
->setCaseWorker($form->get('caseWorker')->getData())
->setCaseManager($form->get('caseManager')->getData())
->setTherapist($form->get('therapist')->getData())
->setSu($form->get('su')->getData())
->setRoles($roles)
->setActive((bool) $form->get('active')->getData())
->setRateType($form->get('rateType')->getData())
->setRate($form->get('rate')->getData())
->setLevel($form->get('level')->getData());
->setLevel($form->get('level')->getData())
;
$this->entityManager->flush();
@ -237,27 +254,32 @@ class AdminController extends AbstractController
/** @var User $user */
$user = $userRepo->find($id);
$prevSup = $this->entityManager->getRepository(Supervision::class)->findBy(['worker' => $user]);
$prevSup = $this->entityManager->getRepository(Supervision::class)->findOneBy(['worker' => $user]);
$form = $this->createForm(SupervisorFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/** @var User $supervisor */
$supervisor = $form->get('supervisor')->getData();
if (count($prevSup) > 0) {
$this->entityManager->remove($prevSup[0]);
if ($prevSup) {
$prevSup->setSupervisor($supervisor);
$this->entityManager->persist($prevSup);
$this->entityManager->flush();
}
$this->addFlash('success', "Supervisor updated for {$user->getName()}");
} else {
$sup = new Supervision();
$sup->setSupervisor($supervisor);
$sup->setWorker($user);
$sup->setSupervisor($supervisor);
$this->entityManager->persist($sup);
$this->entityManager->flush();
$this->addFlash('success', "Supervisor assigned to {$user->getName()}");
}
$supMsg = MessageFactory::createUser($admin, $supervisor, 'New Case Worker', "You've been assigned a new case worker, {$user->getName()}");
$userMsg = MessageFactory::createUser($admin, $user, 'New Staff Supervisor', "You've been assigned a new staff supervisor {$supervisor->getName()}");
$this->entityManager->persist($sup);
$this->entityManager->persist($userMsg);
$this->entityManager->persist($supMsg);
$this->entityManager->flush();

View File

@ -101,8 +101,10 @@ class CaseController extends AbstractController
}
$case = $this->entityManager->getRepository(MemberCase::class)->find($caseId);
$caseDocs = $this->entityManager->getRepository(CaseDocument::class)->getDocumentsByCase($case);
$compDocs = $this->entityManager->getRepository(CompanyDocument::class)->findBy(['company' => $user->getCompany()]);
/** @todo validate user has access to case, check for admin, case manager of case worker */
//$uc = $this->entityManager->getRepository(UserCase::class)
$sources = $this->entityManager->getRepository(ReferralSource::class)->findAll();
return $this->render(
@ -111,8 +113,6 @@ class CaseController extends AbstractController
$this->navLinks,
[
'case' => $case,
'caseDocs' => $caseDocs,
'compDocs' => $compDocs,
'sources' => $sources,
'breadcrumbs' => [
new Breadcrumb($this->generateUrl('app_list_cases'), 'List Cases'),
@ -129,9 +129,8 @@ class CaseController extends AbstractController
{
$this->denyAccessUnlessGranted('ROLE_ADMIN');
$companyDocs = $this->entityManager->getRepository(CompanyDocument::class)->findBy(['company' => $admin->getCompany()]);
$case = new MemberCase();
$form = $this->createForm(MemberCaseFormType::class, $case, ['docs' => $companyDocs]);
$form = $this->createForm(MemberCaseFormType::class);
$form->handleRequest($request);
@ -159,7 +158,6 @@ class CaseController extends AbstractController
'notifications' => Libs::getMessages($admin, $this->entityManager),
'form' => $form,
'sources' => $this->entityManager->getRepository(ReferralSource::class)->retrieveOrderedList(),
'docs' => $companyDocs,
]
)
);
@ -227,7 +225,11 @@ class CaseController extends AbstractController
$this->entityManager->flush();
}
$msg = MessageFactory::createNewCase($admin, $user);
$msg = MessageFactory::createNewCase(
$admin,
$user,
$this->generateUrl('app_view_case', ['caseId' => $case->getId()->toString()])
);
$this->entityManager->persist($uc);
$this->entityManager->persist($msg);

View File

@ -14,8 +14,10 @@ use DateTime;
use DateTimeZone;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\ExpressionLanguage\Expression;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\CurrentUser;
use Symfony\Component\Security\Http\Attribute\IsGranted;
@ -32,6 +34,7 @@ class CompanyController extends AbstractController
}
#[Route('/company', name: 'app_company')]
#[IsGranted(new Expression('is_granted("ROLE_ADMIN")'))]
public function editCompanyInfo(
#[CurrentUser()] User $user,
Request $request,
@ -81,7 +84,54 @@ class CompanyController extends AbstractController
);
}
#[Route('/company/directory', name: 'app_company_directory')]
public function companyDirectory(#[CurrentUser()] User $user): Response
{
$this->navLinks['company_nav'] = NavList::PRESENT_LINK;
$users = $this->entityManager->getRepository(User::class)->findBy(['company' => $user->getCompany()], ['name' => 'ASC']);
return $this->render(
'internal/admin/company/directory.html.twig',
array_merge(
$this->navLinks,
[
'breadcrumbs' => [
new Breadcrumb(
($this->isGranted('ROLE_ADMIN') ? $this->generateUrl('app_admin_dashboard') : $this->generateUrl('app_dashboard')),
($this->isGranted('ROLE_ADMIN') ? "Admin Dashboard" : "Dashboard")
),
],
'users' => $users,
'notifications' => Libs::getMessages($user, $this->entityManager),
]
)
);
}
#[Route('/user/download-vcard/{id}', name: 'app_download_user_vcard')]
public function downloadUserVcard(#[CurrentUser()] User $user, string $id): Response
{
$coworker = $this->entityManager->getRepository(User::class)->find($id);
if (!$coworker) {
throw new NotFoundHttpException('Coworker not found');
}
if ($coworker->getCompany() !== $user->getCompany()) {
throw new NotFoundHttpException('Coworker not found');
}
return new Response($coworker->generateVCard(), 200, [
'Content-Type' => 'text/vcf',
'Content-Disposition' => 'attachment; filename="' . str_replace(' ', '', $coworker->getName()) . '.vcf"',
'Content-Length' => strlen($coworker->generateVCard()),
'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
'Expires' => '0',
'Pragma' => 'public',
'Content-Transfer-Encoding' => 'binary'
]);
}
#[Route('/docs/list', name: 'app_list_documents')]
#[IsGranted(new Expression('is_granted("ROLE_ADMIN")'))]
public function listDocs(#[CurrentUser()] User $user): Response
{
$this->navLinks['company_nav'] = NavList::PRESENT_LINK;
@ -102,6 +152,7 @@ class CompanyController extends AbstractController
}
#[Route('/docs/add', name: 'app_add_doc')]
#[IsGranted(new Expression('is_granted("ROLE_ADMIN")'))]
public function addCompanyDocument(Request $request, #[CurrentUser()] User $user): Response
{
$this->navLinks['company_nav'] = NavList::PRESENT_LINK;
@ -137,6 +188,7 @@ class CompanyController extends AbstractController
}
#[Route('/docs/edit/{docId}', name: 'app_edit_doc')]
#[IsGranted(new Expression('is_granted("ROLE_ADMIN")'))]
public function editCompanyDocument(string $docId, Request $request, #[CurrentUser()] User $user): Response
{
$companyDoc = $this->entityManager->getRepository(CompanyDocument::class)->find($docId);

View File

@ -2,15 +2,17 @@
namespace App\Controller;
use App\Entity\CaseDocument;
use App\Entity\CompanyDocument;
use App\Entity\MemberCase;
use App\Entity\Member;
use App\Entity\MemberDocument;
use App\Entity\User;
use App\Libs\Breadcrumb;
use App\Libs\NavList;
use App\Libs\Libs;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\CurrentUser;
@ -23,22 +25,51 @@ class DocumentController extends AbstractController
$this->navLinks = NavList::LIST;
}
#[Route('/case/{caseId}/doc/{docId}', name: 'app_display_case_doc')]
public function displayCaseDocument(string $caseId, string $docId, #[CurrentUser()] User $user): Response
#[Route('/member/{memberId}', name: 'app_display_case_doc')]
public function displayCaseDocument(string $memberId, #[CurrentUser()] User $user): Response
{
$case = $this->entityManager->getRepository(MemberCase::class)->find($caseId);
$doc = $this->entityManager->getRepository(CompanyDocument::class)->find($docId);
$caseDoc = $this->entityManager->getRepository(CaseDocument::class)->getCaseDocument($case, $doc);
/** @var Member $member */
$member = $this->entityManager->getRepository(Member::class)->find($memberId);
$memberDocs = $this->entityManager->getRepository(MemberDocument::class)->findBy(['client' => $member]);
return $this->render(
'internal/cases/documents/display-case-doc.html.twig',
'internal/cases/members/documents/list-member-docs.html.twig',
array_merge(
$this->navLinks,
[
'msgs' => Libs::getMessages($user, $this->entityManager),
'breadcrumbs' => []
'notifications' => Libs::getMessages($user, $this->entityManager),
'breadcrumbs' => [
new Breadcrumb($this->generateUrl('app_my_cases'), 'Cases'),
new Breadcrumb($this->generateUrl('app_case_members', ['id' => $member->getCaseId()->getId()->toString()]), 'Members'),
],
'docs' => $memberDocs,
]
)
);
}
#[Route('/member/{memberId}/document/{docId}/sign', name: 'app_member_sign_case_doc')]
public function signCaseDocument(string $memberId, string $docId, #[CurrentUser()] User $user): Response
{
/** @var Member $member */
$member = $this->entityManager->getRepository(Member::class)->find($memberId);
$doc = $this->entityManager->getRepository(CompanyDocument::class)->find($docId);
$memDoc = $this->entityManager->getRepository(MemberDocument::class)->findOneBy([
'document' => $doc,
'client' => $member,
'caseWorker' => $user
]);
if (!$memDoc) {
throw new NotFoundHttpException('Document not found');
}
return $this->render(
'internal/cases/members/documents/sign-member-doc.html.twig', [
'doc' => $memDoc,
'caseWorkerSignature' => $user->getSignature(),
]
);
}
}

View File

@ -2,10 +2,13 @@
namespace App\Controller;
use App\Entity\CompanyDocument;
use App\Entity\Member;
use App\Entity\User;
use App\Entity\MemberCase;
use App\Entity\MemberDocument;
use App\Entity\Messages;
use App\Entity\User;
use App\Entity\UserCase;
use App\Form\MemberFormType;
use App\Libs\Breadcrumb;
use App\Libs\Libs;
@ -55,45 +58,48 @@ class MemberController extends AbstractController
{
/** @var MemberCase $case */
$case = $this->entityManager->getRepository(MemberCase::class)->find($id);
/** @var UserCase $userCase */
$userCase = $this->entityManager->getRepository(UserCase::class)->findOneBy(['memberCase' => $case]);
/** @var User $caseWorker */
$caseWorker = $userCase->getUser();
/** @var array $docs<int, CompanyDocuments> */
$docs = $this->entityManager->getRepository(CompanyDocument::class)->findBy(['company' => $user->getCompany()], ['title' => 'ASC']);
$member = new Member();
$form = $this->createForm(MemberFormType::class, $member);
$form = $this->createForm(MemberFormType::class, $member, ['docs' => $docs]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$member = $form->getData();
$member->setCaseId($case)
->setFirstName($form->get('firstName')->getData())
->setLastName($form->get('lastName')->getData())
->setDob($form->get('dob')->getData())
->setGender($form->get('gender')->getData())
->setRace($form->get('race')->getData())
->setLanguage($form->get('language')->getData())
->setPersonalId($form->get('personalId')->getData())
->setEmergencyContact($form->get('emergencyContact')->getData())
->setEmail($form->get('email')->getData())
->setAddress($form->get('address')->getData())
->setCity($form->get('city')->getData())
->setState($form->get('state')->getData())
->setZip($form->get('zip')->getData())
->setPhone($form->get('phone')->getData())
->setRelationship($form->get('relationship')->getData())
->setDayPhone($form->get('dayPhone')->getData())
->setEveningPhone($form->get('eveningPhone')->getData())
->setCellPhone($form->get('cellPhone')->getData())
->setSchool($form->get('school')->getData())
->setMaritalStatus($form->get('maritalStatus')->getData())
->setChild($form->get('isChild')->getData())
->setParent($form->get('isParent')->getData())
->setAdultChild($form->get('isAdultChild')->getData())
->setLegalGuardian($form->get('isLegalGuardian')->getData())
->setParentsLiveTogether($form->get('parentsLiveTogether')->getData())
->setDcsApproved($form->get('dcsApproved')->getData())
->setChild(($form->get('isChild') ? true : false))
->setParent(($form->get('isParent') ? true : false))
->setAdultChild(($form->get('isAdultChild') ? true : false))
->setLegalGuardian(($form->get('isLegalGuardian') ? true : false))
->setParentsLiveTogether(($form->get('parentsLiveTogether') ? true : false))
->setDcsApproved(($form->get('dcsApproved') ? true : false))
;
$this->entityManager->persist($member);
$this->entityManager->flush();
$selectedDocs = $form->get('docs');
foreach ($selectedDocs->getData() as $doc) {
$dbDoc = $this->entityManager->getRepository(CompanyDocument::class)->find($doc);
if (!$dbDoc) {
continue;
}
$md = new MemberDocument();
$md->setClient($member)
->setDocument($dbDoc)
->setCaseWorker($caseWorker)
;
$this->entityManager->persist($md);
$this->entityManager->flush();
}
$this->addFlash(
'success',
'Member added successfully'
@ -115,6 +121,7 @@ class MemberController extends AbstractController
'notifications' => Libs::getMessages($user, $this->entityManager),
'case' => $case,
'form' => $form->createView(),
'docs' => $docs,
]
)
);

View File

@ -0,0 +1,125 @@
<?php
namespace App\Entity;
use App\Enums\DocumentExtras;
use App\Repository\CompanyDocumentRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid;
#[ORM\Entity(repositoryClass: CompanyDocumentRepository::class)]
class CompanyDocument
{
#[ORM\Id]
#[ORM\Column(type: UuidType::NAME, unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')]
private ?Uuid $id = null;
#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: false)]
private ?Company $company = null;
#[ORM\Column(length: 255)]
private ?string $title = null;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $text = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
private ?\DateTimeInterface $updated = null;
#[ORM\Column(type: Types::JSON, enumType: DocumentExtras::class, nullable: true)]
private array $extras = [];
public function getId(): ?Uuid
{
return $this->id;
}
public function getCompany(): ?Company
{
return $this->company;
}
public function setCompany(?Company $company): static
{
$this->company = $company;
return $this;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): static
{
$this->title = $title;
return $this;
}
public function getText(): ?string
{
return $this->text;
}
public function setText(?string $text): static
{
$this->text = $text;
return $this;
}
public function getUpdated(): ?\DateTimeInterface
{
return $this->updated;
}
public function setUpdated(\DateTimeInterface $updated): static
{
$this->updated = $updated;
return $this;
}
public function getExtras(): array
{
return $this->extras;
}
public function setExtras(array $extras): static
{
$this->extras = $extras;
return $this;
}
public function inExtras(DocumentExtras $field): bool
{
return in_array($field, $this->extras);
}
public function renderHtml(): string
{
$text = $this->text;
if ($this->inExtras(DocumentExtras::EMAIL)) {
$text = str_replace('{{ email }}', "<input type='email' name='email' id='email' value='{{ doc.client.email }}'/>", $text);
$text = str_replace('{{ checkbox|email }}', "<input type='checkbox' name='emailClient' id='emailClient' value='1'/>", $text);
}
if ($this->inExtras(DocumentExtras::PHONE)) {
$text = str_replace('{{ phone }}', "<input type='tel' name='phone' id='phone' value='{{ doc.client.phone }}'/>", $text);
$text = str_replace('{{ checkbox|phone }}', "<input type='checkbox' name='callClient' id='callClient' value='1'/>", $text);
$text = str_replace('{{ checkbox|text }}', "<input type='checkbox' name='textClient' id='textClient' value='1'/>", $text);
}
return <<<HTML
$text
HTML;
}
}

View File

@ -4,6 +4,7 @@ namespace App\Entity;
use App\Enums\CaseLevel;
use App\Enums\County;
use App\Enums\Case\ReferralType;
use App\Repository\MemberCaseRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
@ -31,7 +32,7 @@ class MemberCase
private ?string $lastName = null;
#[ORM\Column(length: 45)]
private ?string $referralType = null;
private ?ReferralType $referralType = null;
#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: false)]
@ -109,8 +110,6 @@ class MemberCase
#[ORM\OneToMany(targetEntity: StaffNote::class, mappedBy: 'memberCase')]
private Collection $staffNotes;
private array $docs;
public function __construct()
{
$this->userCases = new ArrayCollection();
@ -166,12 +165,12 @@ class MemberCase
return "{$this->lastName}, {$this->firstName}";
}
public function getReferralType(): ?string
public function getReferralType(): ?ReferralType
{
return $this->referralType;
}
public function setReferralType(string $referralType): static
public function setReferralType(ReferralType $referralType): static
{
$this->referralType = $referralType;
@ -507,9 +506,4 @@ class MemberCase
return $this;
}
public function getDocs(): array
{
return $this->docs;
}
}

View File

@ -0,0 +1,132 @@
<?php
namespace App\Entity;
use App\Repository\MemberDocumentRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid;
#[ORM\Entity(repositoryClass: MemberDocumentRepository::class)]
class MemberDocument
{
#[ORM\Id]
#[ORM\Column(type: UuidType::NAME, unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')]
private ?Uuid $id = null;
#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: false)]
private ?Member $client = null;
#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: false)]
private ?User $caseWorker = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
private ?\DateTimeInterface $clientSigned = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
private ?\DateTimeInterface $workerSigned = null;
#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: false)]
private ?CompanyDocument $document = null;
#[ORM\Column(nullable: true)]
private ?array $clientSignature = null;
#[ORM\Column(nullable: true)]
private ?array $workerSignature = null;
public function getId(): ?Uuid
{
return $this->id;
}
public function getClient(): ?Member
{
return $this->client;
}
public function setClient(?Member $client): static
{
$this->client = $client;
return $this;
}
public function getCaseWorker(): ?User
{
return $this->caseWorker;
}
public function setCaseWorker(?User $caseWorker): static
{
$this->caseWorker = $caseWorker;
return $this;
}
public function getClientSigned(): ?\DateTimeInterface
{
return $this->clientSigned;
}
public function setClientSigned(?\DateTimeInterface $clientSigned): static
{
$this->clientSigned = $clientSigned;
return $this;
}
public function getWorkerSigned(): ?\DateTimeInterface
{
return $this->workerSigned;
}
public function setWorkerSigned(?\DateTimeInterface $workerSigned): static
{
$this->workerSigned = $workerSigned;
return $this;
}
public function getDocument(): ?CompanyDocument
{
return $this->document;
}
public function setDocument(?CompanyDocument $document): static
{
$this->document = $document;
return $this;
}
public function getClientSignature(): ?array
{
return $this->clientSignature;
}
public function setClientSignature(?array $clientSignature): static
{
$this->clientSignature = $clientSignature;
return $this;
}
public function getWorkerSignature(): ?array
{
return $this->workerSignature;
}
public function setWorkerSignature(?array $workerSignature): static
{
$this->workerSignature = $workerSignature;
return $this;
}
}

View File

@ -63,20 +63,6 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
#[ORM\Column(enumType: CaseLevel::class)]
private ?CaseLevel $level = null;
private ?User $supervisor = null;
#[ORM\Column]
private ?bool $caseWorker = null;
#[ORM\Column]
private ?bool $caseManager = null;
#[ORM\Column]
private ?bool $therapist = null;
#[ORM\Column]
private ?bool $su = null;
/**
* @var Collection<int, UserCase>
*/
@ -107,6 +93,8 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
private ?\DateTimeInterface $lastLogin = null;
private ?User $supervisor = null;
public function __construct()
{
$this->userCases = new ArrayCollection();
@ -267,36 +255,6 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
return $this;
}
public function retrieveUnreadNotifications(): array
{
return [
[
'id' => 1,
'title' => 'Welcome',
'from' => 'Admin',
'type' => 'info',
'message' => 'Welcome to the dashboard.',
'timestamp' => new \DateTime('2024-11-12 10:00:00'),
],
[
'id' => 2,
'title' => 'New Case',
'from' => 'Admin',
'type' => 'info',
'message' => 'You have a new case.',
'timestamp' => new \DateTime('2024-11-13 10:19:56'),
],
[
'id' => 3,
'title' => 'New Message',
'from' => 'Admin',
'type' => 'warning',
'message' => 'You have a new message.',
'timestamp' => new \DateTime('2024-11-16 11:13:25'),
],
];
}
public function getSupervisor(): ?User
{
return $this->supervisor;
@ -311,68 +269,40 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
public function isCaseWorker(): ?bool
{
return $this->caseWorker;
}
public function setCaseWorker(bool $caseWorker): static
{
$this->caseWorker = $caseWorker;
return $this;
return in_array('ROLE_CASE_WORKER', $this->roles);
}
public function isCaseManager(): ?bool
{
return $this->caseManager;
}
public function setCaseManager(bool $caseManager): static
{
$this->caseManager = $caseManager;
return $this;
return in_array('ROLE_CASE_MANAGER', $this->roles);
}
public function isTherapist(): ?bool
{
return $this->therapist;
return in_array('ROLE_THERAPIST', $this->roles);
}
public function setTherapist(bool $therapist): static
public function isAdmin(): ?bool
{
$this->therapist = $therapist;
return $this;
}
public function isSu(): ?bool
{
return $this->su;
}
public function setSu(bool $su): static
{
$this->su = $su;
return $this;
return in_array('ROLE_ADMIN', $this->roles);
}
public function getJobs(): array
{
$jobs = [];
if ($this->caseWorker) {
if (in_array('ROLE_CASE_WORKER', $this->roles)) {
$jobs[] = 'Case Worker';
}
if ($this->caseManager) {
if (in_array('ROLE_CASE_MANAGER', $this->roles)) {
$jobs[] = 'Case Manager';
}
if ($this->therapist) {
if (in_array('ROLE_THERAPIST', $this->roles)) {
$jobs[] = 'Therapist';
}
if ($this->su) {
if (in_array('ROLE_ADMIN', $this->roles)) {
$jobs[] = 'Admin';
}
@ -484,4 +414,18 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
return $this;
}
public function generateVCard(): string
{
list($fname, $lname) = explode(' ', $this->name, 2);
return 'BEGIN:VCARD' .
"\nVERSION:3.0" .
"\nN:{$lname};{$fname}" .
"\nFN:$this->name" .
"\nORG:{$this->company->getName()}" .
($this->workPhone ? "\nTEL;TYPE=WORK,VOICE:$this->workPhone" : null) .
($this->email ? "\nEMAIL;TYPE=WORK,INTERNET:$this->email" : null) .
"\nREV:" . date('c') .
"\nEND:VCARD";
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace App\Enums\Case;
enum ReferralType: string
{
case DCS = 'DCS';
case PO = 'PO';
}

View File

@ -38,7 +38,7 @@ class MessageFactory
return $msg;
}
public static function createNewCase(User $sender, User $recipient): Messages
public static function createNewCase(User $sender, User $recipient, string $link): Messages
{
$msg = new Messages();
$msg->setSent(new DateTimeImmutable())
@ -46,6 +46,7 @@ class MessageFactory
->setSender($sender)
->setRecipient($recipient)
->setTitle('New Case')
->setLink($link)
->setMessage("You've been assigned a new case")
;

View File

@ -38,10 +38,20 @@ class EditUserFormType extends AbstractType
])
->add('workPhone', TextType::class)
->add('personalPhone', TextType::class)
->add('caseWorker', CheckboxType::class)
->add('caseManager', CheckboxType::class)
->add('therapist', CheckboxType::class)
->add('su', CheckboxType::class, ['label' => 'Admin'])
->add('active', CheckboxType::class)
->add('caseWorker', CheckboxType::class, [
'mapped' => false
])
->add('caseManager', CheckboxType::class, [
'mapped' => false
])
->add('therapist', CheckboxType::class, [
'mapped' => false
])
->add('su', CheckboxType::class, [
'mapped' => false,
'label' => 'Admin'
])
->add('rateType', EnumType::class, [
'class' => RateType::class
])

View File

@ -2,14 +2,13 @@
namespace App\Form;
use App\Entity\CompanyDocument;
use App\Entity\MemberCase;
use App\Entity\ReferralSource;
use App\Enums\CaseLevel;
use App\Enums\County;
use App\Enums\Case\ReferralType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EnumType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
@ -19,6 +18,8 @@ class MemberCaseFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$docs = $options['docs'];
$builder
->add('caseNumber', TextType::class, [
'required' => true
@ -29,7 +30,9 @@ class MemberCaseFormType extends AbstractType
->add('lastName', TextType::class, [
'required' => true
])
->add('referralType')
->add('referralType', EnumType::class, [
'class' => ReferralType::class
])
->add('admitDate', null, [
'widget' => 'single_text',
'required' => true,
@ -62,11 +65,6 @@ class MemberCaseFormType extends AbstractType
->add('county', EnumType::class, [
'class' => County::class,
])
->add('docs', ChoiceType::class, [
'data_class' => CompanyDocument::class,
'multiple' => true,
'expanded' => true,
])
;
}

View File

@ -2,10 +2,12 @@
namespace App\Form;
use App\Entity\CompanyDocument;
use App\Entity\Member;
use App\Enums\GenderType;
use App\Enums\RaceType;
use App\Enums\RelationshipType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
@ -18,6 +20,7 @@ class MemberFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$docs = $options['docs'];
$builder
->add('lastName', null, ['required' => true])
->add('firstName', null, ['required' => true])
@ -68,6 +71,14 @@ class MemberFormType extends AbstractType
->add('dcsApproved', CheckboxType::class, [
'mapped' => false
])
->add('docs', EntityType::class, [
'class' => CompanyDocument::class,
'choices' => $docs,
'multiple' => true,
'expanded' => true,
'choice_label' => 'title',
'mapped' => false,
])
;
}
@ -75,6 +86,7 @@ class MemberFormType extends AbstractType
{
$resolver->setDefaults([
'data_class' => Member::class,
'docs' => [],
'csrf_protection' => true,
'csrf_field_name' => '_token',
'csrf_token_id' => 'member',

View File

@ -61,10 +61,17 @@ class UserFormType extends AbstractType
])
->add('workPhone', TextType::class)
->add('personalPhone', TextType::class)
->add('caseWorker', CheckboxType::class)
->add('caseManager', CheckboxType::class)
->add('therapist', CheckboxType::class)
->add('caseWorker', CheckboxType::class, [
'mapped' => false
])
->add('caseManager', CheckboxType::class, [
'mapped' => false
])
->add('therapist', CheckboxType::class, [
'mapped' => false
])
->add('su', CheckboxType::class, [
'mapped' => false,
'label' => 'Admin',
])
->add('level', EnumType::class, [

View File

@ -21,6 +21,7 @@ class NavList
'staff_notes' => self::DEFAULT,
'case_itinerary' => self::DEFAULT,
'company_nav' => self::DEFAULT,
'company_directory' => self::DEFAULT,
];
public const PRESENT_LINK = 'nav-link text-white active bg-gradient-dark';

View File

@ -0,0 +1,43 @@
<?php
namespace App\Repository;
use App\Entity\CompanyDocument;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<CompanyDocument>
*/
class CompanyDocumentRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, CompanyDocument::class);
}
// /**
// * @return CompanyDocument[] Returns an array of CompanyDocument objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('c')
// ->andWhere('c.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('c.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?CompanyDocument
// {
// return $this->createQueryBuilder('c')
// ->andWhere('c.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View File

@ -0,0 +1,45 @@
<?php
namespace App\Repository;
use App\Entity\MemberDocument;
use App\Entity\Member;
use App\Entity\MemberCase;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<CaseDocument>
*/
class MemberDocumentRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, MemberDocument::class);
}
// /**
// * @return CaseDocument[] Returns an array of CaseDocument objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('m')
// ->andWhere('m.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('m.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?CaseDocument
// {
// return $this->createQueryBuilder('m')
// ->andWhere('m.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View File

@ -53,9 +53,9 @@ class UserRepository extends ServiceEntityRepository implements PasswordUpgrader
public function getCaseManagers(Company $company): array
{
return $this->createQueryBuilder('u')
->andWhere('u.caseManager = :case_manager')
->andWhere('u.roles LIKE :role')
->andWhere('u.company = :company')
->setParameter('case_manager', true)
->setParameter('role', '%ROLE_CASE_MANAGER%')
->setParameter('company', $company->getId()->toBinary())
->getQuery()
->getResult()
@ -65,9 +65,9 @@ class UserRepository extends ServiceEntityRepository implements PasswordUpgrader
public function getTherapists(Company $company): array
{
return $this->createQueryBuilder('u')
->andWhere('u.therapist = :therapist')
->andWhere('u.roles LIKE :role')
->andWhere('u.company = :company')
->setParameter('therapist', true)
->setParameter('role', '%ROLE_THERAPIST%')
->setParameter('company', $company->getId()->toBinary())
->getQuery()
->getResult()
@ -77,9 +77,9 @@ class UserRepository extends ServiceEntityRepository implements PasswordUpgrader
public function getAdmins(Company $company): array
{
return $this->createQueryBuilder('u')
->andWhere('u.su = :su')
->andWhere('u.roles LIKE :role')
->andWhere('u.company = :company')
->setParameter('su', true)
->setParameter('role', '%ROLE_ADMIN%')
->setParameter('company', $company->getId()->toBinary())
->getQuery()
->getResult()
@ -100,40 +100,11 @@ class UserRepository extends ServiceEntityRepository implements PasswordUpgrader
public function getCaseWorkers(): array
{
return $this->createQueryBuilder('u')
->orWhere('u.caseWorker = :case_worker')
->orWhere('u.caseManager = :case_manager')
->orWhere('u.therapist = :therapist')
->setParameter('case_worker', true)
->setParameter('case_manager', true)
->setParameter('therapist', true)
->andWhere('u.roles LIKE :role')
->setParameter('role', '%ROLE_CASE_WORKER%')
->orderBy('u.name', 'ASC')
->getQuery()
->getResult()
;
}
// /**
// * @return User[] Returns an array of User objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('u')
// ->andWhere('u.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('u.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?User
// {
// return $this->createQueryBuilder('u')
// ->andWhere('u.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View File

@ -33,7 +33,7 @@
{% block page_css %}{% endblock %}
</head>
<body class="bg-gray-200"> {% block body %}{% endblock %}
<body class="g-sidenav-show bg-gray-200"> {% block body %}{% endblock %}
{% block javascripts %}
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<script>

View File

@ -30,14 +30,14 @@
<input type='text' name='{{ field_name(form.dcsCaseId) }}' id='case_form_dcsCaseId' class='form-control' required='required'/>
</div>
<div class='input-group input-group-outline mb-3 is-filled'>
<label for='case_form_admitDate' class='form-label'>Admit Date</label>
<input type='date' name='{{ field_name(form.admitDate) }}' id='case_form_admitDate' class='form-control'/>
<div class='input-group input-group-outline mb-3'>
<label for='case_form_admitDate'></label>
<input type='date' name='{{ field_name(form.admitDate) }}' id='case_form_admitDate' class='form-control' title='Admit Date'/>
</div>
<div class='input-group input-group-outline mb-3 is-filled'>
<label for='case_form_closeDate' class='form-label'>Close Date</label>
<input type='date' name='{{ field_name(form.closeDate) }}' id='case_form_closeDate' class='form-control'/>
<div class='input-group input-group-outline mb-3'>
<label for='case_form_closeDate'></label>
<input type='date' name='{{ field_name(form.closeDate) }}' id='case_form_closeDate' class='form-control' title='Close Date'/>
</div>
<div class='input-group input-group-outline mb-3'>
@ -46,24 +46,30 @@
</div>
<div class='input-group input-group-outline mb-3'>
<label for='case_form_referralType' class='form-label'>Referral Type</label>
<input type='text' name='{{ field_name(form.referralType) }}' id='case_form_referralType' class='form-control'/>
<label for='case_form_referralType'></label>
<select name='{{ field_name(form.referralType) }}' id='case_form_referralType' class='form-control' title='Referral Type'>
<option value=''>-- Referral Type --</option>
{% for r in enum('App\\Enums\\Case\\ReferralType').cases() %}
<option value='{{ r.name }}'>{{ r.name }}</option>
{% endfor %}
</select>
</div>
<div class='input-group input-group-outline mb-3 is-filled'>
<label for='case_form_level' class='form-label'>Level</label>
<select name='{{ field_name(form.level) }}' id='case_form_level' class='form-control'>
<option value=''></option>
<div class='input-group input-group-outline mb-3'>
<label for='case_form_level'></label>
<select name='{{ field_name(form.level) }}' id='case_form_level' class='form-control' title='Case Level'>
<option value=''>-- Case Level --</option>
{% for l in enum('App\\Enums\\CaseLevel').cases() %}
<option value='{{ l.value }}'>{{ l.name|replace({'_': ' '})|lower|capitalize }}</option>
{% endfor %}
</select>
</div>
<div class='input-group input-group-outline mb-3 is-filled'>
<label for='case_form_referralSource' class='form-label'>Referral Source</label>
<div class='input-group input-group-outline mb-3'>
<label for='case_form_referralSource'></label>
<select name='{{ field_name(form.referralSource) }}' id='case_form_referralSource' class='form-control'>
<option value=''></option>
<option value=''>-- Referral Source --</option>
{% for src in sources %}
<option value='{{ src.id }}'>{{ src.name}}</option>
@ -72,24 +78,15 @@
</div>
<div class='input-group input-group-outline mb-3'>
<label for='case_form_referralSources2' class='form-label'>2nd Referral Source</label>
<label for='case_form_referralSources2'></label>
<select name='{{ field_name(form.referralSource2) }}' id='case_form_referralSources2' class='form-control'>
<option value=''></option>
<option value=''>-- 2nd Referral Source --</option>
{% for src in sources %}
<option value='{{ src.id }}'>{{ src.name }}</option>
{% endfor %}
</select>
</div>
<div class='input-group input-group-outline mb-3'>
{% for d in docs %}
<span class='check'>
<input type='checkbox' name='{{ field_name(form.docs) }}[]' id='{{ d.title|replace({' ': '-'}) }}' value='{{ d.id }}'/>
<label for='{{ d.title|replace({' ': '-'}) }}'>{{ d.title }}</label>
</span>
{% endfor %}
</div>
</div>
<div class='col'>
<div class='input-group input-group-outline mb-3'>
@ -127,12 +124,12 @@
<input type='text' name='{{ field_name(form.zip) }}' id='case_form_zip' class='form-control'/>
</div>
<div class='input-group input-group-outline mb-3 is-filled'>
<label for='case_form_county' class='form-label'>County</label>
<div class='input-group input-group-outline mb-3'>
<label for='case_form_county'></label>
<select name='{{ field_name(form.county) }}' id='case_form_county' class='form-control'>
<option value=''></option>
<option value=''>-- County --</option>
{% for c in enum('App\\Enums\\County').cases() %}
<option value='{{ c.value }}'>{{ c.name }}</option>
<option value='{{ c.value }}'>{{ c.name|lower|capitalize }}</option>
{% endfor %}
</select>
</div>

View File

@ -32,7 +32,7 @@
<option value=''></option>
{% for w in caseWorkers %}
{% set selected = (w.id == assignedWorkerId) %}
<option value='{{ w.id }}' {% if selected %} selected="true" {% endif %}>{{ w.name }}</option>
<option value='{{ w.id }}' {% if selected %} selected="true" {% endif %}>{{ w.name }} ({{ w.userCases|length }})</option>
{% endfor %}
</select>
</div>

View File

@ -67,7 +67,7 @@
</td>
<td>
<p class='text-xs font-weight-bold mb-0'>
{{ c.referralType }}/{{ c.referralSource.name }}<br/>
{{ c.referralType.value }}/{{ c.referralSource.name }}<br/>
<a href='mailto:{{ c.referralSource.email }}'>{{ c.referralSource.email }}</a>
</p>
</td>

View File

@ -0,0 +1,97 @@
{% extends 'base.html.twig' %}
{% block title %}Edit Company
{% endblock %}
{% block body %}
<div class="container position-sticky z-index-sticky top-0">
<div class="row">
<div class="col-12">
{{ block("nav", "libs/nav.html.twig") }}
</div>
</div>
</div>
<main class="main-content mt-0">
<section>
<div class="page-header min-vh-100">
<div class="container">
<div class="row">
<div class="col-6 d-lg-flex d-none h-100 my-auto pe-0 position-absolute top-0 start-0 text-center justify-content-center flex-column" style='margin-top:75px!important;'>
<div id='bg-image' class="position-relative bg-gradient-primary h-100 m-3 px-7 border-radius-lg d-flex flex-column justify-content-center"></div>
</div>
<div class="col-xl-4 col-lg-5 col-md-7 d-flex flex-column ms-auto me-auto ms-lg-auto me-lg-5">
<div class="card card-plain">
<div class="card-header">
<h4 class="font-weight-bolder">Edit {{ company.name }}</h4>
<p class="mb-0">Edit Company Data</p>
</div>
<div class="card-body">
{{ form_errors(form) }}
{{ form_start(form) }}
<div class="input-group input-group-outline mb-3 is-filled">
<label for="company_form_name" class="form-label">Name</label>
<input type="text" name="{{ field_name(form.name) }}" value='{{ field_value(form.name) }}' id='company_form_name' class="form-control" required="required"/>
</div>
<div class="input-group input-group-outline mb-3 is-filled">
<label for="company_form_address" class="form-label">Address</label>
<input type="text" name="{{ field_name(form.address) }}" value='{{ field_value(form.address) }}' id='company_form_address' class="form-control" required="required"/>
</div>
<div class="input-group input-group-outline mb-3 is-filled">
<label for="company_form_city" class="form-label">City</label>
<input type="text" name="{{ field_name(form.city) }}" value='{{ field_value(form.city) }}' id='company_form_city' class="form-control" required="required"/>
</div>
<div class="input-group input-group-outline mb-3 is-filled">
<label for="company_form_state" class="form-label">State</label>
<input type="text" name="{{ field_name(form.state) }}" value='{{ field_value(form.state) }}' id='company_form_state' class="form-control" required="required"/>
</div>
<div class="input-group input-group-outline mb-3 is-filled">
<label for="company_form_zip" class="form-label">Zip</label>
<input type="text" name="{{ field_name(form.zip) }}" value='{{ field_value(form.zip) }}' id='company_form_zip' class="form-control" required="required"/>
</div>
<div class="input-group input-group-outline mb-3 is-filled">
<label for="company_form_phone" class="form-label">Phone</label>
<input type="text" name="{{ field_name(form.phone) }}" value='{{ field_value(form.phone) }}' id='company_form_phone' class="form-control" required="required"/>
</div>
<div class="input-group input-group-outline mb-3 is-filled">
<label for="company_form_email" class="form-label">Email</label>
<input type="email" name="{{ field_name(form.email) }}" value='{{ field_value(form.email) }}' id='company_form_email' class="form-control" required="required"/>
</div>
<div class="input-group input-group-outline mb-3{% if field_value(form.url) %} is-filled{% endif %}">
<label for="company_form_url" class="form-label">URL</label>
<input type="text" name="{{ field_name(form.url) }}" value='{{ field_value(form.url) }}' id='company_form_url' class="form-control"/>
</div>
<div class='input-group input-group-outline mb-3' id='company-logo'>
{{ form_row(form.companyLogo) }}
</div>
<div class="text-center">
<button type="submit" class="btn btn-lg bg-gradient-dark btn-lg w-100 mt-4 mb-0">Save Company Data</button>
</div>
{{ form_end(form) }}
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
{% endblock %}
{% block page_js %}
{% endblock %}
{% block page_css %}
{% set bg_image = asset('img/illustrations/illustration-signup.jpg') %}
{% if company.companyLogo %}
{% set bg_image = company_image_path~"/"~company.companyLogo %}
{% endif %}
<style type='text/css'>
#bg-image {
background-repeat: no-repeat;
background-size: contain;
background-image: url('{{ bg_image }}');
}
</style>
{% endblock %}

View File

@ -0,0 +1,69 @@
{% extends 'base.html.twig' %}
{% block body %}
{{ block('nav', 'internal/libs/nav.html.twig') }}
<main class="main-content position-relative max-height-vh-100 h-100 border-radius-lg ">
{{ block('topnav', 'internal/libs/top-nav.html.twig') }}
<div class="container-fluid py-2">
<div class="row">
<div class="col-12">
<div class="card my-4">
<div class="card-header p-0 position-relative mt-n4 mx-3 z-index-2">
<div class="d-flex justify-content-between bg-gradient-dark shadow-dark border-radius-lg pt-4 pb-3 ps-3 p-2">
<div>
<h6 class="text-white text-capitalize ps-3">Company Directory</h6>
</div>
</div>
</div>
<div class="card-body px-0 pb-2">
<div class="table-responsive p-0">
<table class="table align-items-center mb-0">
<thead>
<tr>
<th class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7">Name</th>
<th class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7 ps-2">Phone</th>
<th class="text-secondary opacity-7"></th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>
<div class='d-flex px-2 py-1'>
<div>
{% if user.imageName %}<img src='{{ user_image_path }}/{{ user.imageName }}' class='avatar avatar-sm me-3 border-radius-large' alt='{{ user.name }}'>{% endif %}
</div>
<div class='d-flex flex-column justify-content-center{% if not user.active %} text-muted {% endif %}'>
<h6 class='mb-0 text-small'>{{ user.name }}</h6>
<p class='text-xs text-secondary mb-0'>
<a href='mailto:{{ user.email }}'>{{ user.email }}</a>
</p>
</div>
</div>
</td>
<td>
{% if user.workPhone %}<a href='tel:{{ user.workPhone }}'>{{ user.getFormattedPhone() }}</a>{% endif %}
</td>
<td class='align-middle text-center text-xs'>
</td>
<td class='align-middle text-center text-xs'>
</td>
<td class='align-middle'>
<a href='{{ path('app_download_user_vcard', {id: user.id}) }}' class='text-secondary text-xs' tooltip="Download vCard">
<i class='material-symbols-rounded opacity-5'>badge</i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock %}

View File

@ -0,0 +1,103 @@
{% extends 'base.html.twig' %}
{% block body %}
{{ block('nav', 'internal/libs/nav.html.twig') }}
<main class="main-content position-relative max-height-vh-100 h-100 border-radius-lg ">
{{ block('topnav', 'internal/libs/top-nav.html.twig') }}
<section>
<div class="card card-plain">
<div class="card-header">
<h4 class="font-weight-bolder">Add New Document</h4>
<p class="mb-0"></p>
</div>
<div class="card-body">
<div class="container">
{{ form_errors(form) }}
{{ form_start(form) }}
<div class="row">
<div class='col'>
<div class='input-group input-group-outline mb-3'>
<label for='doc_form_title' class='form-label'>Title</label>
<input type='text' name='{{ field_name(form.title) }}' id='doc_form_title' class='form-control' required='required'/>
</div>
<div class='input-group input-group-outline mb-3'>
{#{{ form_row(form.extras) }}#}
{% for e in enum('App\\Enums\\DocumentExtras').cases() %}
<input type='checkbox' name='{{ field_name(form.extras) }}[]' id='{{ e.name }}' value='{{ e.value }}'/>
<label for='{{ e.name }}' class='extras'>{{ e.name|lower|replace({'_': ' '})|capitalize }}</label>
{% endfor %}
</div>
<div class='input-group input-group-outline mb-3 is-filled'>
<textarea name='{{ field_name(form.text) }}' id='doc-text' placeholder='Document Text'></textarea>
</div>
</div>
</div>
<div class='row'>
<div class="text-center">
<button type="submit" class="btn btn-lg bg-gradient-dark btn-lg w-100 mt-4 mb-0">Save Document</button>
</div>
</div>
{{ form_end(form) }}
</div>
</div>
</div>
</section>
</main>
{% endblock %}
{% block page_js %}
<script src="https://cdn.jsdelivr.net/npm/tinymce@7.6.0/tinymce.min.js"></script>
<script type='module'>
window.onload = function () {
tinymce.init({
selector: '#doc-text',
height: 500,
width: 1200,
plugins: ['advlist',
'autolink',
'lists',
'link',
'image',
'charmap',
'preview',
'anchor',
'searchreplace',
'visualblocks',
'code',
'fullscreen',
'insertdatetime',
'media',
'table',
'help',
'wordcount'/**/
],
toolbar: 'undo redo | ' +
'blocks | ' +
'bold italic underline forecolor | ' +
'alignleft aligncenter alignright | ' +
'bullist numlist outdent indent | ' +
'removeformat | help',
content_style: '' // 'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }'
});
}
</script>
{% endblock %}
{% block page_css %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.5/skins/lightgray/content.min.css">
<style type='text/css'>
.extras {
margin: 0 5px !important;
}
#doc-text {
width: 100%;
height: 300px;
}
</style>
{% endblock %}

View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">
<head>
<style type='text/css' rel='stylesheet'>
body {
margin: 0;
}
.sheet-outer {
margin: 0;
}
.sheet {
margin: 0;
overflow: hidden;
page-break-after: always;
}
@media screen {
body {
background: #e0e0e0;
}
.sheet {
background: #ffffff;
box-shadow: 0 .5mm 2mm rgba(0,0,0,.3);
margin: 5mm auto;
}
}
@media print {
}
@page {
size: letter;
margin: 0;
}
</style>
</head>
<body>
<header id="header" style='height:100px;'>
<img id="companyLogo" src='{{ company_image_path }}/{{ company.companyLogo }}' style='height:100px;width:100px;'/>
</header>
<main id="body">
<section id='doc-content'></section>
</main>
<footer id='footer'>
</footer>
</body>
</html>

View File

@ -0,0 +1,109 @@
{% extends 'base.html.twig' %}
{% block body %}
{{ block('nav', 'internal/libs/nav.html.twig') }}
<main class="main-content position-relative max-height-vh-100 h-100 border-radius-lg ">
{{ block('topnav', 'internal/libs/top-nav.html.twig') }}
<section>
<div class="card card-plain">
<div class="card-header">
<h4 class="font-weight-bolder">Edit Document</h4>
<p class="mb-0"></p>
</div>
<div class="card-body">
<div class="container">
{{ form_errors(form) }}
{{ form_start(form) }}
<div class="row">
<div class='col'>
<div class='input-group input-group-outline mb-3 is-filled'>
<label for='doc_form_title' class='form-label'>Title</label>
<input type='text' name='{{ field_name(form.title) }}' value='{{ doc.title }}' id='doc_form_title' class='form-control' required='required'/>
</div>
<div class='input-group input-group-outline mb-3'>
{{ form_row(form.extras) }}
{# for e in enum('App\\Enums\\DocumentExtras').cases %}
<input type='checkbox' name='{{ field_name(form.extras) }}[]' id='{{ e.name }}' value='{{ e.value }}'/>
<label for='{{ e.name }}' class='extras'>{{ e.name|lower|replace({'_': ' '})|capitalize }}</label>
{% endfor #}
</div>
<div class='input-group input-group-outline mb-3 is-filled'>
<textarea name='{{ field_name(form.text) }}' id='doc-text' placeholder='Document Text'></textarea>
</div>
</div>
</div>
<div class='row'>
<div class="text-center">
<button type="submit" class="btn btn-lg bg-gradient-dark btn-lg w-100 mt-4 mb-0">Save Document</button>
</div>
</div>
{{ form_end(form) }}
</div>
</div>
</div>
</section>
</main>
{% endblock %}
{% block page_js %}
<script src="https://cdn.jsdelivr.net/npm/tinymce@7.6.0/tinymce.min.js"></script>
<script type='module'>
window.onload = function () {
tinymce.init({
license_key: 'gpl',
selector: '#doc-text',
height: 500,
width: 1200,
plugins: ['advlist',
'autolink',
'lists',
'link',
'image',
'charmap',
'preview',
'anchor',
'searchreplace',
'visualblocks',
'code',
'fullscreen',
'insertdatetime',
'media',
'table',
'help',
'wordcount'/**/
],
toolbar: 'undo redo | ' +
'blocks | ' +
'bold italic underline forecolor | ' +
'alignleft aligncenter alignright | ' +
'bullist numlist outdent indent | ' +
'removeformat | help',
content_style: '',
setup: function(editor) {
editor.on('init', function(e) {
editor.setContent("{{ docText|raw }}");
});
}
});
}
</script>
{% endblock %}
{% block page_css %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.5/skins/lightgray/content.min.css">
<style type='text/css'>
.extras {
margin: 0 5px !important;
}
#doc-text {
width: 100%;
height: 300px;
}
</style>
{% endblock %}

View File

@ -0,0 +1,66 @@
{% extends 'base.html.twig' %}
{% block body %}
{{ block('nav', 'internal/libs/nav.html.twig') }}
<main class="main-content position-relative max-height-vh-100 h-100 border-radius-lg ">
{{ block('topnav', 'internal/libs/top-nav.html.twig') }}
<div class="container-fluid py-2">
<div class="row">
<div class="col-12">
<div class="card my-4">
<div class="card-header p-0 position-relative mt-n4 mx-3 z-index-2">
<div class="d-flex justify-content-between bg-gradient-dark shadow-dark border-radius-lg pt-4 pb-3 ps-3 p-2">
<div>
<h6 class="text-white text-capitalize ps-3">Document List</h6>
</div>
{% if is_granted('ROLE_ADMIN') %}
<div>
<button type="button" class="btn btn-block btn-light mb-3" onclick="window.open('{{ path('app_add_doc') }}', '_self')">Add Document</button>
</div>
{% endif %}
</div>
</div>
<div class="card-body px-0 pb-2">
<div class="table-responsive p-0">
<table class="table align-items-center mb-0">
<thead>
<tr>
<th class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7">Title</th>
<th class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7 ps-2">Last Update</th>
<th class="text-secondary opacity-7"></th>
</tr>
</thead>
<tbody id='doc-list'>
{% for d in docs %}
<tr>
<td>
<div class='d-flex px-2 py-1'>
<div class='d-flex flex-column justify-content-center'>
<h6 class='mb-0 text-small'>{{ d.title }}</h6>
</div>
</div>
</td>
<td>
<p class='text-xs font-weight-bold mb-0'>{{ d.updated|date('F j, Y', company_timezone) }}</p>
</td>
<td class='align-right'>
{% if is_granted('ROLE_ADMIN') %}
<a href='{{ path('app_edit_doc', {docId: d.id}) }}' class='' title='Edit Document' data-toggle='tooltip'>
<i class="material-symbols-rounded opacity-5">edit</i>
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock %}

View File

@ -11,7 +11,7 @@
<div class='container'>
<div class="row">
<div class="col-6 d-lg-flex d-none h-100 my-auto pe-0 position-absolute top-0 start-0 text-center justify-content-center flex-column">
<div class="position-relative bg-gradient-primary h-100 m-3 px-7 border-radius-lg d-flex flex-column justify-content-center" style="background-image: url('/assets/img/illustrations/illustration-signup.jpg'); background-size: cover;"></div>
<div class="position-relative bg-gradient-primary h-100 m-3 px-7 border-radius-lg d-flex flex-column justify-content-center" style="background-image: url('{{ asset('/img/illustrations/illustration-signup.jpg') }}'); background-size: cover;"></div>
</div>
<div class="col-xl-4 col-lg-5 col-md-7 d-flex flex-column ms-auto me-auto ms-lg-auto me-lg-5">
<div class="card card-plain">

View File

@ -11,7 +11,7 @@
<div class='container'>
<div class="row">
<div class="col-6 d-lg-flex d-none h-100 my-auto pe-0 position-absolute top-0 start-0 text-center justify-content-center flex-column">
<div class="position-relative bg-gradient-primary h-100 m-3 px-7 border-radius-lg d-flex flex-column justify-content-center" style="background-image: url('/assets/img/illustrations/illustration-signup.jpg'); background-size: cover;"></div>
<div class="position-relative bg-gradient-primary h-100 m-3 px-7 border-radius-lg d-flex flex-column justify-content-center" style="background-image: url('{{ asset('/img/illustrations/illustration-signup.jpg') }}'); background-size: cover;"></div>
</div>
<div class="col-xl-4 col-lg-5 col-md-7 d-flex flex-column ms-auto me-auto ms-lg-auto me-lg-5">
<div class="card card-plain">
@ -30,32 +30,36 @@
<label for="user_form_email" class="form-label">Email</label>
<input type="email" name="{{ field_name(form.email) }}" value='{{ field_value(form.email) }}' class="form-control" required="required"/>
</div>
<div class='input-group input-group-outline mb-3'>
<div class='input-group input-group-outline mb-3{% if field_value(form.workPhone) %} is-filled {% endif %}'>
<label for='user_form_workPhone' class='form-label'>Work Phone</label>
<input type="text" name="{{ field_name(form.workPhone) }}" value='{{ field_value(form.workPhone) }}' class="form-control" required="required"/>
</div>
<div class='input-group input-group-outline mb-3'>
<div class='input-group input-group-outline mb-3{% if field_value(form.personalPhone) %} is-filled {% endif %}'>
<label for='user_form_personalPhone' class='form-label'>Personal Phone</label>
<input type="text" name="{{ field_name(form.personalPhone) }}" value='{{ field_value(form.personalPhone) }}' class="form-control"/>
</div>
<div class='input-group input-group-outline mb-3'>
<input type='checkbox' name='{{ field_name(form.active) }}' value='1' {% if data.active %} checked="checked" {% endif %}/>
<label for='user_form_active'>Active</label>
</div>
<div class='input-group input-group-outline mb-3'>
<div class='row justify-content-center flex-column'>
<div class='col'>
<input type='checkbox' name='{{ field_name(form.caseWorker) }}' id='user_form_job_CASE_WORKER' value='CASE_WORKER' {% if data.caseWorker %} checked="checked" {% endif %}/>
<input type='checkbox' name='{{ field_name(form.caseWorker) }}' id='user_form_job_CASE_WORKER' value='CASE_WORKER' {% if data.isCaseWorker() %} checked="checked" {% endif %}/>
<label for='user_form_job_CASE_WORKER'>Case Worker</label><br/>
</div>
<div class='col'>
<input type='checkbox' name='{{ field_name(form.therapist) }}' id='user_form_job_THERAPIST' value='THERAPIST' {% if data.therapist %} checked="checked" {% endif %}/>
<input type='checkbox' name='{{ field_name(form.therapist) }}' id='user_form_job_THERAPIST' value='THERAPIST' {% if data.isTherapist() %} checked="checked" {% endif %}/>
<label for='user_form_job_THERAPIST'>Therapist</label><br/>
</div>
</div>
<div class='row justify-content-center flex-column'>
<div class='col'>
<input type='checkbox' name='{{ field_name(form.caseManager) }}' id='user_form_job_CASE_MANAGER' value='CASE_MANAGER' {% if data.caseManager %} checked="checked" {% endif %}/>
<input type='checkbox' name='{{ field_name(form.caseManager) }}' id='user_form_job_CASE_MANAGER' value='CASE_MANAGER' {% if data.isCaseManager() %} checked="checked" {% endif %}/>
<label for='user_form_job_CASE_MANAGER'>Case Manager</label>
</div>
<div class='col'>
<input type='checkbox' name='{{ field_name(form.su) }}' id='user_form_job_ADMIN' value='ADMIN' {% if data.su %} checked="checked" {% endif %}/>
<input type='checkbox' name='{{ field_name(form.su) }}' id='user_form_job_ADMIN' value='ADMIN' {% if data.isAdmin() %} checked="checked" {% endif %}/>
<label for='user_form_job_ADMIN'>Admin</label><br/>
</div>
</div>

View File

@ -38,9 +38,9 @@
<td>
<div class='d-flex px-2 py-1'>
<div>
<img src='' class='avatar avatar-sm me-3 border-radius-large' alt='{{ user.name }}'>
{% if user.imageName %}<img src='{{ user_image_path }}/{{ user.imageName }}' class='avatar avatar-sm me-3 border-radius-large' alt='{{ user.name }}'>{% endif %}
</div>
<div class='d-flex flex-column justify-content-center'>
<div class='d-flex flex-column justify-content-center{% if not user.active %} text-muted {% endif %}'>
<h6 class='mb-0 text-small'>{{ user.name }}</h6>
<p class='text-xs text-secondary mb-0'>
<a href='mailto:{{ user.email }}'>{{ user.email }}</a>

View File

@ -74,6 +74,15 @@
<label for='member_form_school' class='form-label'>School</label>
<input type='text' name='{{ field_name(form.school) }}' id='member_form_school' class='form-control'/>
</div>
<div class='input-group input-group-outline mb-3'>
{% for d in docs %}
<span class='check'>
<input type='checkbox' name='{{ field_name(form.docs) }}[]' id='{{ d.title|lower|replace({' ': '-'}) }}' value='{{ d.id }}'/>
<label for='{{ d.title|lower|replace({' ': '-'}) }}'>{{ d.title }}</label>
</span>
{% endfor %}
</div>
</div>
<div class='col'>
<div class='input-group input-group-outline mb-3'>

View File

@ -0,0 +1,59 @@
{% extends 'base.html.twig' %}
{% block title %}{% endblock %}
{% block body %}
{{ block('nav', 'internal/libs/nav.html.twig') }}
<main class="main-content position-relative max-height-vh-100 h-100 border-radius-lg ">
{{ block('topnav', 'internal/libs/top-nav.html.twig') }}
<div class="container-fluid py-2">
<div class="row">
<div class="col-12">
<div class="card my-4">
<div class="card-header p-0 position-relative mt-n4 mx-3 z-index-2">
<div class="d-flex justify-content-between bg-gradient-dark shadow-dark border-radius-lg pt-4 pb-3 ps-3 p-2">
<div>
<h6 class="text-white text-capitalize ps-3">Assigned Case Documents</h6>
</div>
</div>
</div>
<div class="card-body px-0 pb-2">
<div class="table-responsive p-0">
<table class="table align-items-center mb-0">
<thead>
<tr>
<th class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7">Title</th>
<th class='text-center text-uppercase text-secondary text-xxs font-weight-bolder opacity-7'>Client Signed</th>
<th class='text-center text-uppercase text-secondary text-xxs font-weight-bolder opacity-7'>Case Worker Signed</th>
<th class="text-secondary opacity-7"></th>
</tr>
</thead>
<tbody>
{% for d in docs %}
<tr>
<td>{{ d.document.title }}</td>
<td class='text-center'>{% if d.clientSigned %}{{ d.clientSigned|date('M j, Y H:i:s', company_timezone) }}{% endif %}</td>
<td class='text-center'>{% if d.workerSigned %}{{ d.workerSigned|date('M j, Y H:i:s', company_timezone) }}{% endif %}</td>
<td>
<a href='{{ path('app_member_sign_case_doc', {memberId: d.client.id, docId: d.document.id}) }}' class='text-secondary' title='Edit Member'>
<i class="material-symbols-rounded opacity-5">edit</i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block page_js %}{% endblock %}
{% block page_css %}{% endblock %}

View File

@ -0,0 +1,119 @@
{% extends 'base.html.twig' %}
{% block title %}{% endblock %}
{% block body %}
<div class="container">
<h1>Sign Member Document</h1>
<h3>{{ doc.document.title }}</h3>
<p>{{ doc.document.updated|date('M j, Y h:i:s a', company_timezone) }}</p>
<form action="" method="post" enctype="multipart/form-data">
<div class='row'>
{{ doc.document.renderHtml()|
replace({'{{ doc.client.email }}': doc.client.email})|
replace({'{{ doc.client.phone }}': doc.client.phone})|
raw
}}
</div>
<div class='row'>
<div class='col'>
<div class='input-group input-group-outline mb-3'>
{% if doc.document.inExtras(enum('App\\Enums\\DocumentExtras').CLIENT_NAME) %}
<input type='text' name='clientName' id='clientName' value='{{ doc.client.name }}'/>
{% endif %}
{% if doc.document.inExtras(enum('App\\Enums\\DocumentExtras').CLIENT_SIGNATURE) %}
<button id='clearClientSignature'>Clear Signature</button><br />
<canvas id='clientSignatureCanvas'></canvas>
{% endif %}
</div>
</div>
</div>
{% if doc.document.inExtras(enum('App\\Enums\\DocumentExtras').PROVIDER_SIGNATURE) %}
<div class='row'>
<div class='col'>
<div class='input-group input-group-outline mb-3'>
{% if doc.document.inExtras(enum('App\\Enums\\DocumentExtras').PROVIDER_NAME) %}
<input type='text' name='providerName' id='providerName' value='{{ doc.caseWorker.name }}'/>
{% endif %}
<button id='clearProviderSignature'>Clear Signature</button><br/>
<canvas id='providerSignatureCanvas'></canvas>
</div>
</div>
</div>
{% endif %}
<button type="submit" class="btn btn-primary">Complete</button>
</form>
</div>
{% endblock %}
{% block page_js %}
<script src="https://cdn.jsdelivr.net/npm/signature_pad@5.0.4/dist/signature_pad.umd.min.js"></script>
<script type='text/javascript'>
window.onload = initializeSignatureBlocks;
var clientCanvas = document.getElementById('clientSignatureCanvas');
var providerCanvas = document.getElementById('providerSignatureCanvas');
var providerSaveSignature = JSON.parse('{{ caseWorkerSignature|raw }}');
var clientPad = null;
var providerPad = null
function initializeSignatureBlocks() {
if (providerCanvas) {
createProviderSignatureBlock();
}
if (clientCanvas) {
createClientSignatureBlock();
}
}
function createProviderSignatureBlock() {
providerPad = new SignaturePad(providerCanvas);
const ratio = Math.max(window.devicePixelRatio || 1, 1);
providerCanvas.width = providerCanvas.offsetWidth * ratio;
providerCanvas.height = providerCanvas.offsetHeight * ratio;
providerCanvas.getContext("2d").scale(ratio, ratio);
if (providerSaveSignature) {providerPad.fromData(providerSaveSignature);}
document.getElementById('clearProviderSignature').addEventListener('click', clearProviderSignature);
}
function createClientSignatureBlock() {
clientPad = new SignaturePad(clientCanvas);
const ratio = Math.max(window.devicePixelRatio || 1, 1);
clientCanvas.width = clientCanvas.offsetWidth * ratio;
clientCanvas.height = clientCanvas.offsetHeight * ratio;
clientCanvas.getContext("2d").scale(ratio, ratio);
document.getElementById('clearClientSignature').addEventListener('click', clearClientSignature);
}
function clearClientSignature(e) {
e.preventDefault();
clientPad.clear();
}
function clearProviderSignature(e) {
e.preventDefault();
providerPad.clear();
}
function saveSignatureBlock() {
document.getElementById('signature').value = JSON.stringify(pad.toData());
return true;
}
</script>
{% endblock %}
{% block page_css %}
<style rel='stylesheet'>
#clientSignatureCanvas, #providerSignatureCanvas {
width: 100%;
height: 300px;
background-color: white;
border: solid 1px black;
}
</style>
{% endblock %}

View File

@ -76,7 +76,7 @@
<a href='{{ path('app_case_edit_member', {caseId: case.id, memberId: member.id}) }}' class='text-secondary' title='Edit Member'>
<i class="material-symbols-rounded opacity-5">edit</i>
</a>
<a href='{{ path('app_assign_case_documents', {caseId: case.id, memberId: member.id}) }}' class='text-secondary' title='Assign Case Document'>
<a href='{{ path('app_display_case_doc', {memberId: member.id}) }}' class='text-secondary' title='Sign Case Document'>
<i class='material-symbols-rounded opacity-5'>content_copy</i>
</a>
</td>

View File

@ -49,7 +49,7 @@
</td>
<td>
<p class='text-xs font-weight-bold mb-0'>
{{ c.referralType }}/{{ c.referralSource.name }}<br/>
{{ c.referralType.value }}/{{ c.referralSource.name }}<br/>
<a href='mailto:{{ c.referralSource.email }}'>{{ c.referralSource.email }}</a>
</p>
</td>

View File

@ -43,7 +43,7 @@
<div class='input-group input-group-outline mb-3 is-filled'>
<label for='case_form_referralType' class='form-label'>Referral Type</label>
<input type='text' name='referralType' id='case_form_referralType' value='{{ case.referralType }}' class='form-control'/>
<input type='text' name='referralType' id='case_form_referralType' value='{{ case.referralType.value }}' class='form-control'/>
</div>
<div class='input-group input-group-outline mb-3 is-filled'>

View File

@ -6,7 +6,7 @@
{% block body %}
{{ block('nav', 'internal/libs/nav.html.twig') }}
<main class="main-content position-relative max-height-vh-100 h-100 border-radius-lg ">
<main class="main-content position-relative max-height-vh-100 h-100 border-radius-lg">
{{ block('topnav', 'internal/libs/top-nav.html.twig') }}
<div class='container-fluid py-2'>
@ -50,9 +50,9 @@
<div>
<p class='text-sm mb-0 text-capitalize'>Time Travelled</p>
<h4 class='mb-0'>
{{ totalTimeTravelled30Days|date("%d:%H:%i'%s''") }}
{{ totalTimeTravelled30Days|date("%a %H:%I'%S''") }}
/
{{ totalTimeTravelledYTD|date("%d:%H:%i'%s''") }}
{{ totalTimeTravelledYTD|date("%a %H:%I'%S''") }}
</h4>
</div>
<div class="icon icon-md icon-shape bg-gradient-dark shadow-dark shadow text-center border-radius-lg">

View File

@ -107,6 +107,12 @@
<span class='nav-link-text ms-1'>Resources</span>
</a>
</li>
<li class='nav-item'>
<a class='{{ company_directory }}' href='{{ path('app_company_directory') }}'>
<i class='material-symbols-rounded opacity-5'>lists</i>
<span class='nav-link-text ms-1'>Company Directory</span>
</a>
</li>
<li class="nav-item mt-3">
<h6 class="ps-4 ms-2 text-uppercase text-xs text-dark font-weight-bolder opacity-5">Account pages</h6>
</li>

View File

@ -1,5 +1,5 @@
{% block topnav %}
<nav class="navbar navbar-main navbar-expand-lg px-0 mx-3 border-radius-xl blur shadow-blur left-auto position-sticky mt-4 top-1 z-index-sticky" id="navbarBlur" data-scroll="true">
<nav class="navbar navbar-main navbar-expand-lg px-0 mx-3 shadow-none border-radius-xl" id="navbarBlur" data-scroll="true">
<div class="container-fluid py-1 px-3">
{{ block('breadcrumb', 'internal/libs/breadcrumb.html.twig') }}
<div class="collapse navbar-collapse mt-sm-0 mt-2 me-md-0 me-sm-4" id="navbar">