Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ A lightweight LAMP-ready drug interaction knowledge base inspired by [interaktio
## Features

- 🇬🇧/🇫🇷 bilingual interface (English and French) with simple locale switching.
- AdminLTE 3.2 layout themed with PANTONE® 294 and PANTONE® 200 accents, rounded components, and left-hand navigation.
- Drug interaction registry stored in MySQL with ATC classification metadata.
- Role-based access control with secure login (public view, staff export, admin import) and bilingual interface.
- CSV import/export workflows for bulk maintenance of interaction pairs (admin import, staff/export access).
- AdminLTE 3.2 white theme with rounded cards and dark-yellow accents optimized for clinical readability.
- Drug interaction registry stored in MySQL with ATC classification metadata.
- CSV import/export workflows for bulk maintenance of interaction pairs.
Expand Down Expand Up @@ -41,6 +45,20 @@ A lightweight LAMP-ready drug interaction knowledge base inspired by [interaktio
```
5. Visit the site in a browser. Use the language selector in the header to switch between English and French.

### Default access accounts

| Role | Email | Password | Capabilities |
| --- | --- | --- | --- |
| Administrator | `admin@example.com` | `Admin123!` | View, export, import |
| Staff | `staff@example.com` | `Staff123!` | View, export |
| Public | – | – | View only |

Administrators can create additional users directly in the `users` table.

## Data Exchange

- **CSV Export:** `GET /export.php` (requires staff or administrator sign-in; respects `query` and `severity` filters).
- **CSV Import:** `POST /import.php` (administrator sign-in required) with `multipart/form-data` containing a `file` field. Required headers: `drug_a_name, drug_a_atc, drug_b_name, drug_b_atc, severity, description, clinical_management, evidence_level, source_url`.
## Data Exchange

- **CSV Export:** `GET /export.php` (respects `query` and `severity` filters).
Expand Down
60 changes: 60 additions & 0 deletions app/Auth.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
class Auth
{
private PDO $pdo;

public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}

public function attempt(string $email, string $password): bool
{
$statement = $this->pdo->prepare('SELECT id, name, email, password, role FROM users WHERE email = :email LIMIT 1');
$statement->execute(['email' => $email]);
$user = $statement->fetch();

if (!$user) {
return false;
}

if (!password_verify($password, $user['password'])) {
return false;
}

$_SESSION['user'] = [
'id' => (int) $user['id'],
'name' => $user['name'],
'email' => $user['email'],
'role' => $user['role'],
];

session_regenerate_id(true);

return true;
}

public function user(): ?array
{
return $_SESSION['user'] ?? null;
}

public function check(): bool
{
return isset($_SESSION['user']);
}

public function hasRole(string ...$roles): bool
{
if (!$this->check()) {
return false;
}

return in_array($_SESSION['user']['role'], $roles, true);
}

public function logout(): void
{
unset($_SESSION['user']);
}
}
1 change: 1 addition & 0 deletions app/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
}

require_once __DIR__ . '/functions.php';
require_once __DIR__ . '/Auth.php';
require_once __DIR__ . '/InteractionRepository.php';
require_once __DIR__ . '/InteractionService.php';

Expand Down
4 changes: 4 additions & 0 deletions database/sample_data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ INSERT INTO interactions (drug_a_name, drug_a_atc, drug_b_name, drug_b_atc, seve
('Metformin', 'A10BA02', 'Iodinated contrast media', 'V08AB', 'moderate', 'Contrast-induced nephropathy may reduce metformin clearance increasing risk of lactic acidosis.', 'Withhold metformin on day of procedure and reassess renal function 48 hours post exposure.', 'Moderate', 'https://www.interaktionsdatabasen.dk'),
('Sertraline', 'N06AB06', 'Linezolid', 'J01XX08', 'major', 'Risk of serotonin syndrome due to MAO inhibition by linezolid.', 'Avoid combination; if unavoidable, monitor closely for serotonin toxicity.', 'Moderate', 'https://www.interaktionsdatabasen.dk'),
('Levothyroxine', 'H03AA01', 'Calcium carbonate', 'A12AA04', 'minor', 'Calcium may reduce levothyroxine absorption.', 'Separate administration by at least 4 hours and monitor TSH levels.', 'Low', 'https://www.interaktionsdatabasen.dk');

INSERT INTO users (name, email, password, role) VALUES
('System Administrator', 'admin@example.com', '$2y$12$6Bpe8ahWOKnGUERcnbjIB.C69TwWMypOj5.1j2GW6MvNQxkRVtxwe', 'admin'),
('Clinical Staff', 'staff@example.com', '$2y$12$N.mSuAtIFHybqh1baWceJ.jJ1U/V3Za9GrckUPzP3876itEpKIM5G', 'staff');
9 changes: 9 additions & 0 deletions database/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,12 @@ CREATE TABLE IF NOT EXISTS interactions (
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY unique_pair (drug_a_name, drug_b_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(191) NOT NULL,
email VARCHAR(191) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role ENUM('admin', 'staff') NOT NULL DEFAULT 'staff',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
89 changes: 89 additions & 0 deletions public/assets/custom.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,67 @@
body {
background-color: #f4f6f9;
font-family: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

:root {
--pantone-294: #003A70;
--pantone-200: #BA0C2F;
}

.main-header {
background-color: #ffffff !important;
border-bottom: 4px solid var(--pantone-294);
margin: 0.75rem 0.75rem 0;
border-radius: 0.85rem;
}

.main-sidebar {
background: linear-gradient(180deg, var(--pantone-294) 0%, #012f57 100%);
}

.brand-link {
border-bottom: none !important;
}

.brand-text {
font-weight: 700;
letter-spacing: 0.02em;
}

.sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link.active,
.sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link.active:hover {
background-color: var(--pantone-200);
color: #ffffff;
border-radius: 0.5rem;
}

.sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link {
color: rgba(255, 255, 255, 0.85);
border-radius: 0.5rem;
}

.sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link:hover {
background-color: rgba(255, 255, 255, 0.12);
color: #ffffff;
}

.sidebar-dark-primary .nav-sidebar .nav-link i {
color: rgba(255, 255, 255, 0.8);
}

.sidebar-dark-primary .nav-header {
color: rgba(255, 255, 255, 0.6);
font-size: 0.75rem;
letter-spacing: 0.1em;
text-transform: uppercase;
}

.btn-accent,
.btn-accent:hover,
.btn-accent:focus {
background-color: var(--pantone-200);
border-color: var(--pantone-200);
color: #ffffff;
background-color: #f8f9fa;
font-family: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
Expand Down Expand Up @@ -69,6 +132,32 @@ body {

.footer-dark {
background: #ffffff;
border-top: 4px solid var(--pantone-200);
border-radius: 0.75rem;
color: #555555;
}

.welcome-banner {
background: linear-gradient(135deg, rgba(0, 58, 112, 0.95), rgba(186, 12, 47, 0.85));
color: #ffffff;
border-radius: 1rem;
}

.link-accent {
color: var(--pantone-200);
}

.link-accent:hover {
color: #8a0923;
}

.card-outline.card-primary {
border-top: 4px solid var(--pantone-200);
}

.login-page .login-logo a {
color: var(--pantone-294);
}
border-top: 3px solid #c29100;
border-radius: 0.75rem;
color: #555555;
Expand Down
7 changes: 7 additions & 0 deletions public/export.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
session_start();
require __DIR__ . '/../app/bootstrap.php';

$auth = new Auth($pdo);
if (!$auth->hasRole('staff', 'admin')) {
set_flash('danger', $translator->trans('auth_export_only'));
header('Location: index.php');
exit;
}

$repository = new InteractionRepository($pdo);
$service = new InteractionService($repository);

Expand Down
Loading