diff --git a/.htaccess b/.htaccess index e2bbc23..20ea1a8 100644 --- a/.htaccess +++ b/.htaccess @@ -11,6 +11,7 @@ RewriteRule ^ - [L] # 1) Internal map: /page or /page/ -> /page.php (if such PHP file exists) RewriteCond %{REQUEST_FILENAME}.php -f +RewriteCond %{REQUEST_URI} !\.php$ RewriteRule ^(.+?)/?$ $1.php [L] # 2) Optional: strip trailing slash for non-directories (keeps .php links working) diff --git a/_sidebar.php b/_sidebar.php index 68005ff..b032feb 100644 --- a/_sidebar.php +++ b/_sidebar.php @@ -9,6 +9,12 @@ function render_nav_link($href, $icon, $label, $active_page) { $current_page = basename($_SERVER['PHP_SELF']); ?>
+ +
+

Viewing as Employee

+ Return to Your View +
+
FinMox Logo @@ -20,7 +26,7 @@ $current_page = basename($_SERVER['PHP_SELF']); render_nav_link('candidates.php', 'users', 'Candidates', $current_page); render_nav_link('hr_cases.php', 'briefcase', 'HR Cases', $current_page); render_nav_link('onboarding.php', 'clipboard-list', 'Onboarding', $current_page); - render_nav_link('employee_view.php', 'user-square', 'Employee View', $current_page); + render_nav_link('hr_employee_overview.php', 'user-cog', 'HR Overview', $current_page); render_nav_link('weekly_summary.php', 'bar-chart-2', 'Weekly Summary', $current_page); render_nav_link('workflows.php', 'bot', 'Automation', $current_page); render_nav_link('chat.php', 'sparkles', 'AI Copilot', $current_page); diff --git a/assets/pasted-20251217-043322-a3b56103.png b/assets/pasted-20251217-043322-a3b56103.png new file mode 100644 index 0000000..c5965ca Binary files /dev/null and b/assets/pasted-20251217-043322-a3b56103.png differ diff --git a/db/migrations/015_add_magic_link_to_users.sql b/db/migrations/015_add_magic_link_to_users.sql new file mode 100644 index 0000000..158448b --- /dev/null +++ b/db/migrations/015_add_magic_link_to_users.sql @@ -0,0 +1,3 @@ +ALTER TABLE `users` +ADD COLUMN `magic_token` VARCHAR(255) NULL UNIQUE, +ADD COLUMN `magic_token_expires_at` DATETIME NULL; diff --git a/db/migrations/016_fix_tasks_table_for_employees.sql b/db/migrations/016_fix_tasks_table_for_employees.sql new file mode 100644 index 0000000..6bc65db --- /dev/null +++ b/db/migrations/016_fix_tasks_table_for_employees.sql @@ -0,0 +1,12 @@ +-- Drop the old foreign key constraint that links tasks to candidates. +-- The name 'tasks_ibfk_1' is the default name generated by MySQL. +ALTER TABLE `tasks` DROP FOREIGN KEY `tasks_ibfk_1`; + +-- Drop the old column linking to candidates. +ALTER TABLE `tasks` DROP COLUMN `candidate_id`; + +-- Add the new column to link tasks to employees (users). +ALTER TABLE `tasks` ADD COLUMN `assignee_id` INT; + +-- Add the new foreign key constraint. +ALTER TABLE `tasks` ADD FOREIGN KEY (`assignee_id`) REFERENCES `users`(`id`) ON DELETE SET NULL; diff --git a/employee_view.php b/employee_view.php index 8f4d2f2..59e5929 100644 --- a/employee_view.php +++ b/employee_view.php @@ -1,14 +1,34 @@ 'Alex', - 'initials' => 'AR', - 'title' => 'Senior Product Designer', - 'manager' => 'Sarah Johnson', - 'start_date' => '12/14/2024' -]; +require_once 'db/config.php'; +// 1. Check for a valid user session +if (!isset($_SESSION['user_id'])) { + header('Location: login.php'); + exit; +} + +// 2. Fetch user data from the database +$pdo = db(); +$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); +$stmt->execute([$_SESSION['user_id']]); +$user = $stmt->fetch(); + +if (!$user) { + // If user not found, destroy session and redirect + session_destroy(); + header('Location: login.php'); + exit; +} + +// Create initials from the username +$initials = ''; +$parts = explode(' ', $user['username']); +foreach ($parts as $part) { + $initials .= strtoupper(substr($part, 0, 1)); +} + +// 3. Task data remains static for now, but will be moved to database later. $tasks = [ [ 'name' => 'Complete Tax Forms (W-4)', @@ -59,6 +79,10 @@ $total_tasks = count($tasks); $completed_count = count($completed_tasks); $progress_percent = $total_tasks > 0 ? ($completed_count / $total_tasks) * 100 : 0; +// For display purposes, placeholder data for manager and start date +$display_manager = 'Sarah Johnson'; +$display_start_date = '12/14/2024'; + ?> @@ -83,12 +107,12 @@ $progress_percent = $total_tasks > 0 ? ($completed_count / $total_tasks) * 100 :
- +
-

Welcome, !

-

+

Welcome, !

+

New Employee

Logout @@ -166,8 +190,8 @@ $progress_percent = $total_tasks > 0 ? ($completed_count / $total_tasks) * 100 :
-

Questions? Reach out to your manager or contact HR.

-

Start Date:

+

Questions? Reach out to your manager or contact HR.

+

Start Date:

diff --git a/employee_welcome.php b/employee_welcome.php new file mode 100644 index 0000000..c904fb4 --- /dev/null +++ b/employee_welcome.php @@ -0,0 +1,94 @@ +prepare("SELECT * FROM users WHERE magic_token = ? AND magic_token_expires_at > NOW()"); + $stmt->execute([$token]); + $user = $stmt->fetch(); + + if ($user) { + // Token is valid, log the user in + session_start(); + $_SESSION['user_id'] = $user['id']; + $_SESSION['role_id'] = $user['role_id']; // Store role for future use + + // Invalidate the token so it can't be reused + $stmt = $pdo->prepare("UPDATE users SET magic_token = NULL, magic_token_expires_at = NULL WHERE id = ?"); + $stmt->execute([$user['id']]); + + } else { + // Token is invalid or expired + $error_message = "This link is invalid or has expired. Please request a new one from HR."; + } +} else if (!isset($_SESSION['user_id'])){ + // Only show an error if no token and not already logged in. + $error_message = "No authentication token provided. This page is only accessible via a special link."; +} + +// If there's an error, display it and stop rendering the page. +if ($error_message) { + echo "

" . htmlspecialchars($error_message) . "

"; + exit; +} + +// The magic link token would be validated here in a real scenario. +// For now, we just display the page. +?> + + + + + + Welcome to <?php echo htmlspecialchars($companyName); ?> + + + + + +
+ + +
+ <?php echo htmlspecialchars($companyName); ?> Logo +
+ + +

Welcome Aboard!

+

+ We are thrilled to have you join the team. We've prepared a few things to get you started. +

+ + +
+ + Start Your Onboarding + +
+ + +
+

Need to review some documents before you start?

+ + Read the Employee Handbook + +
+ +
+ + + diff --git a/generate_magic_link.php b/generate_magic_link.php new file mode 100644 index 0000000..6936eb7 --- /dev/null +++ b/generate_magic_link.php @@ -0,0 +1,47 @@ +modify('+7 days'); +$expiresAtFormatted = $expiresAt->format('Y-m-d H:i:s'); + +// 3. Update the user's record in the database +$stmt = $pdo->prepare("UPDATE users SET magic_token = ?, magic_token_expires_at = ? WHERE id = ?"); +$success = $stmt->execute([$token, $expiresAtFormatted, $userId]); + +// 4. Display the generated link +if ($success) { + // Construct the full URL. In a real environment, use a config for the base URL. + $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https" : "http"; + $host = $_SERVER['HTTP_HOST']; + $magicLink = "{$protocol}://{$host}/employee_welcome.php?token={$token}"; + + echo "

Magic Link Generated Successfully!

"; + echo "

You can share this link with the new employee or click the button below to open it directly. It is valid for 7 days.

"; + echo "Open Employee View in New Tab"; + echo "

Or, manually copy the link:

"; + echo ""; +} else { + echo "

Error

"; + echo "

Could not generate the magic link. Please try again.

"; +} diff --git a/hr_employee_overview.php b/hr_employee_overview.php new file mode 100644 index 0000000..c789f28 --- /dev/null +++ b/hr_employee_overview.php @@ -0,0 +1,231 @@ +query("SELECT u.id, u.username, u.email, r.name as role_name FROM users u LEFT JOIN roles r ON u.role_id = r.id ORDER BY u.username"); + $users = $stmt->fetchAll(); + ?> + + + + + + HR Employee Directory - FinMox + + + + +
+ +
+
+

Employee Directory

+
+
+ + + + + + + + + + + + + + + + + + + +
NameEmailRole + View +
+ View Overview +
+
+
+
+
+
+ + + prepare("SELECT u.username, r.name as role_name FROM users u JOIN roles r ON u.role_id = r.id WHERE u.id = ?"); +$stmt->execute([$userId]); +$user = $stmt->fetch(); + +if (!$user) { + exit('Employee not found.'); +} + +// Fetch tasks for the user +$task_stmt = $pdo->prepare("SELECT * FROM tasks WHERE assignee_id = ? ORDER BY due_date"); +$task_stmt->execute([$userId]); +$tasks = $task_stmt->fetchAll(); + +$pending_tasks = array_filter($tasks, fn($task) => $task['status'] !== 'completed'); +$completed_tasks = array_filter($tasks, fn($task) => $task['status'] === 'completed'); +$total_tasks = count($tasks); +$progress = ($total_tasks > 0) ? (count($completed_tasks) / $total_tasks) * 100 : 0; + +// The rest of the data is still static for now +$employee = [ + 'id' => $userId, + 'name' => $user['username'], + 'role' => $user['role_name'], + 'manager' => 'Sarah Johnson', // Static for now + 'startDate' => '2024-12-14', // Static for now + 'progress' => round($progress), + 'pending_tasks' => array_map(function($task) { + return ['name' => $task['task_name'], 'due' => $task['due_date'], 'description' => $task['description']]; + }, $pending_tasks), + 'completed_tasks' => array_map(function($task) { + return ['name' => $task['task_name'], 'completed_on' => $task['updated_at']]; + }, $completed_tasks), + 'activity_log' => [ + ['date' => 'Dec 16, 2024', 'event' => 'Magic link generated and sent to employee.'], + ['date' => 'Dec 15, 2024', 'event' => 'Onboarding process initiated by HR.'], + ] +]; +?> + + + + + + HR Employee Overview - FinMox + + + + + +
+ + +
+
+ + +
+

HR Employee Overview

+

Detailed onboarding progress for .

+
+ + +
+ + +
+ + +
+

Onboarding Task Checklist

+
+ + +
+
+

+ Pending +
+

+

Due:

+
+ + + +
+
+

+ Completed +
+

Completed On:

+
+ +
+
+ + +
+

Activity Log

+
    + +
  • +
    +
    +
  • + +
+
+ +
+ + +
+ + +
+

Employee Details

+
+

Role:

+

Manager:

+

Start Date:

+
+
+ + +
+

HR Actions

+
+ Generate Magic Link + View as Employee + + +
+
+ + +
+

Onboarding Progress

+

%

+
+
+
+
+ +
+
+
+
+
+ + + diff --git a/impersonate.php b/impersonate.php new file mode 100644 index 0000000..341089a --- /dev/null +++ b/impersonate.php @@ -0,0 +1,27 @@ + +
+

Test Page

+

If you see the sidebar to the left and this message, the test is successful.

+
\ No newline at end of file