diff --git a/api/pexels.php b/api/pexels.php new file mode 100644 index 0000000..fccbde6 --- /dev/null +++ b/api/pexels.php @@ -0,0 +1,29 @@ + 'assets/images/pexels/'.$p['id'].'.jpg', + 'photographer' => $p['photographer'] ?? 'Unknown', + 'photographer_url' => $p['photographer_url'] ?? '', + ]; + } else { + // Fallback: Picsum + $out[] = [ + 'src' => 'https://picsum.photos/1200/800?random='.rand(), + 'photographer' => 'Random Picsum', + 'photographer_url' => 'https://picsum.photos/' + ]; + } +} +echo json_encode($out); +?> \ No newline at end of file diff --git a/assets/css/custom.css b/assets/css/custom.css index ec38839..0bd0c98 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -1,4 +1,3 @@ - /* General Body Styles */ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; @@ -59,8 +58,7 @@ h2 { /* Hero Section */ #hero { - background: linear-gradient(180deg, #FFFFFF 0%, #F2F2F7 100%); - padding: 120px 0; + padding: 0; } /* Card Styles */ @@ -92,3 +90,72 @@ footer { background-color: #FFFFFF; padding: 40px 0; } + +/* Pricing Table */ +#pricing .card { + border: 1px solid #e5e5e5; + transition: all .2s; +} + +#pricing .card:hover { + transform: scale(1.02); + box-shadow: 0 12px 40px rgba(0, 0, 0, 0.1); +} + +#pricing .card-popular { + border-color: #007AFF; + border-width: 2px; +} + +#pricing .card-price { + font-size: 3rem; + font-weight: 700; +} + +#pricing .period { + font-size: 0.8rem; + font-weight: normal; + color: #6c757d; +} + +#pricing .fa-ul { + list-style: none; + padding-left: 0; + margin-bottom: 2rem; +} + +#pricing .fa-li { + position: relative; + left: 0; + margin-bottom: 0.75rem; + padding-left: 2em; /* Add padding to align text */ +} + +#pricing .fa-li .fas { + position: absolute; + left: 0; + width: 2em; + text-align: center; + color: #007AFF; +} + +#pricing .text-muted .fa-li .fas { + color: #6c757d; +} + + +/* Hero Overlay */ +#hero { + position: relative; + background-size: cover; + background-position: center; + color: white; + text-shadow: 0 2px 4px rgba(0,0,0,0.5); +} + +.hero-overlay { + position: relative; + z-index: 1; + background-color: rgba(0, 0, 0, 0.5); + padding: 120px 0; +} \ No newline at end of file diff --git a/assets/css/portal.css b/assets/css/portal.css new file mode 100644 index 0000000..60f4970 --- /dev/null +++ b/assets/css/portal.css @@ -0,0 +1,37 @@ +body { + background-color: #f8f9fa; +} + +.portal-nav { + background-color: #fff; + border-bottom: 1px solid #dee2e6; +} + +.portal-main { + min-height: calc(100vh - 56px); + display: flex; +} + +.sidebar { + width: 250px; + background-color: #fff; + border-right: 1px solid #dee2e6; +} + +.sidebar .nav-link { + color: #333; + padding: 1rem; + border-left: 3px solid transparent; +} + +.sidebar .nav-link.active, +.sidebar .nav-link:hover { + color: #007bff; + background-color: #e9ecef; + border-left-color: #007bff; +} + +.content { + flex-grow: 1; + padding: 2rem; +} diff --git a/assets/images/pexels/185576.jpg b/assets/images/pexels/185576.jpg new file mode 100644 index 0000000..3edc76f Binary files /dev/null and b/assets/images/pexels/185576.jpg differ diff --git a/assets/images/pexels/256514.jpg b/assets/images/pexels/256514.jpg new file mode 100644 index 0000000..7dc8fcf Binary files /dev/null and b/assets/images/pexels/256514.jpg differ diff --git a/assets/images/pexels/607812.jpg b/assets/images/pexels/607812.jpg new file mode 100644 index 0000000..279b354 Binary files /dev/null and b/assets/images/pexels/607812.jpg differ diff --git a/assets/images/pexels/669612.jpg b/assets/images/pexels/669612.jpg new file mode 100644 index 0000000..311e13d Binary files /dev/null and b/assets/images/pexels/669612.jpg differ diff --git a/assets/images/pexels/887843.jpg b/assets/images/pexels/887843.jpg new file mode 100644 index 0000000..6f89553 Binary files /dev/null and b/assets/images/pexels/887843.jpg differ diff --git a/auth_handler.php b/auth_handler.php new file mode 100644 index 0000000..d51a958 --- /dev/null +++ b/auth_handler.php @@ -0,0 +1,72 @@ +prepare('SELECT id FROM users WHERE email = ?'); + $stmt->execute([$email]); + if ($stmt->fetch()) { + header('Location: register.php?error=email_taken'); + exit(); + } + + $hashed_password = password_hash($password, PASSWORD_DEFAULT); + + // Default new registrations to the 'Client' role + $stmt = $db->prepare("SELECT id FROM roles WHERE name = 'Client'"); + $stmt->execute(); + $client_role = $stmt->fetch(PDO::FETCH_ASSOC); + + $stmt = $db->prepare('INSERT INTO users (name, email, password, role_id) VALUES (?, ?, ?, ?)'); + if ($stmt->execute([$name, $email, $hashed_password, $client_role['id'] ?? null])) { + $user_id = $db->lastInsertId(); + $_SESSION['user_id'] = $user_id; + header('Location: portal/'); + exit(); + } else { + header('Location: register.php?error=registration_failed'); + exit(); + } + +} elseif ($action === 'login') { + $email = $_POST['email'] ?? ''; + $password = $_POST['password'] ?? ''; + + if (empty($email) || empty($password)) { + header('Location: login.php?error=missing_fields'); + exit(); + } + + $db = db(); + $stmt = $db->prepare('SELECT * FROM users WHERE email = ?'); + $stmt->execute([$email]); + $user = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($user && password_verify($password, $user['password'])) { + $_SESSION['user_id'] = $user['id']; + header('Location: portal/'); + exit(); + } else { + header('Location: login.php?error=invalid_credentials'); + exit(); + } +} else { + header('Location: index.php'); + exit(); +} diff --git a/db/migrations/002_create_users_and_roles.sql b/db/migrations/002_create_users_and_roles.sql new file mode 100644 index 0000000..49f479c --- /dev/null +++ b/db/migrations/002_create_users_and_roles.sql @@ -0,0 +1,26 @@ + +CREATE TABLE IF NOT EXISTS `roles` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `name` VARCHAR(50) NOT NULL UNIQUE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Insert default roles +INSERT IGNORE INTO `roles` (`name`) VALUES +('Super Admin'), +('Agency Admin'), +('Account Manager'), +('Client'), +('Content Creator'), +('Analyst'), +('Billing'), +('Support'); + +CREATE TABLE IF NOT EXISTS `users` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `name` VARCHAR(100) NOT NULL, + `email` VARCHAR(100) NOT NULL UNIQUE, + `password` VARCHAR(255) NOT NULL, + `role_id` INT, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/db/migrations/003_create_portal_tables.sql b/db/migrations/003_create_portal_tables.sql new file mode 100644 index 0000000..48638e3 --- /dev/null +++ b/db/migrations/003_create_portal_tables.sql @@ -0,0 +1,61 @@ + +-- Projects table to store project information +CREATE TABLE IF NOT EXISTS `projects` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `name` VARCHAR(255) NOT NULL, + `client_id` INT NOT NULL, + `status` VARCHAR(50) DEFAULT 'Pending', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (`client_id`) REFERENCES `users`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Assets table for creative assets linked to projects +CREATE TABLE IF NOT EXISTS `assets` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `project_id` INT NOT NULL, + `name` VARCHAR(255) NOT NULL, + `file_path` VARCHAR(255) NOT NULL, + `status` VARCHAR(50) DEFAULT 'Pending Approval', + `uploaded_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (`project_id`) REFERENCES `projects`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Comments on assets +CREATE TABLE IF NOT EXISTS `asset_comments` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `asset_id` INT NOT NULL, + `user_id` INT NOT NULL, + `comment` TEXT NOT NULL, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (`asset_id`) REFERENCES `assets`(`id`) ON DELETE CASCADE, + FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Courses available for purchase +CREATE TABLE IF NOT EXISTS `courses` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `name` VARCHAR(255) NOT NULL, + `description` TEXT, + `price` DECIMAL(10, 2) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Link table for users who have access to courses +CREATE TABLE IF NOT EXISTS `user_courses` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `user_id` INT NOT NULL, + `course_id` INT NOT NULL, + `purchased_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE, + FOREIGN KEY (`course_id`) REFERENCES `courses`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Invoices for billing +CREATE TABLE IF NOT EXISTS `invoices` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `client_id` INT NOT NULL, + `amount` DECIMAL(10, 2) NOT NULL, + `status` VARCHAR(50) DEFAULT 'Unpaid', + `due_date` DATE, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (`client_id`) REFERENCES `users`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/db/migrations/004_create_extended_portal_tables.sql b/db/migrations/004_create_extended_portal_tables.sql new file mode 100644 index 0000000..62310a6 --- /dev/null +++ b/db/migrations/004_create_extended_portal_tables.sql @@ -0,0 +1,63 @@ +-- Messaging system tied to projects +CREATE TABLE IF NOT EXISTS `messages` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `project_id` INT NOT NULL, + `user_id` INT NOT NULL, + `message` TEXT NOT NULL, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (`project_id`) REFERENCES `projects`(`id`) ON DELETE CASCADE, + FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Calendar events +CREATE TABLE IF NOT EXISTS `calendar_events` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `title` VARCHAR(255) NOT NULL, + `start_event` DATETIME NOT NULL, + `end_event` DATETIME NOT NULL, + `project_id` INT, + `user_id` INT, + `description` TEXT, + FOREIGN KEY (`project_id`) REFERENCES `projects`(`id`) ON DELETE CASCADE, + FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Approvals for assets +CREATE TABLE IF NOT EXISTS `approvals` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `asset_id` INT NOT NULL, + `user_id` INT NOT NULL, + `status` ENUM('Pending', 'Approved', 'Rejected') NOT NULL DEFAULT 'Pending', + `comments` TEXT, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (`asset_id`) REFERENCES `assets`(`id`) ON DELETE CASCADE, + FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Metrics from ad platforms +CREATE TABLE IF NOT EXISTS `metrics` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `project_id` INT NOT NULL, + `platform` VARCHAR(50) NOT NULL, -- e.g., 'Facebook', 'Google Ads' + `date` DATE NOT NULL, + `impressions` INT, + `clicks` INT, + `conversions` INT, + `spend` DECIMAL(10, 2), + `engagement` INT, + `reach` INT, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE KEY `project_platform_date` (`project_id`, `platform`, `date`), + FOREIGN KEY (`project_id`) REFERENCES `projects`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Secure storage for API tokens +CREATE TABLE IF NOT EXISTS `api_tokens` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `service` VARCHAR(50) NOT NULL UNIQUE, -- e.g., 'meta_ads', 'google_ads' + `access_token` TEXT NOT NULL, + `refresh_token` TEXT, + `expires_at` TIMESTAMP, + `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/includes/auth.php b/includes/auth.php new file mode 100644 index 0000000..4b4431d --- /dev/null +++ b/includes/auth.php @@ -0,0 +1,102 @@ +prepare('SELECT roles.name FROM users JOIN roles ON users.role_id = roles.id WHERE users.id = ?'); + $stmt->execute([$user_id]); + $role = $stmt->fetchColumn(); + + return in_array($role, ['Super Admin', 'Agency Admin']); +} + +// Function to require admin privileges +function require_admin() { + if (!is_admin()) { + // Redirect to portal index if not an admin + header('Location: /portal'); + exit(); + } +} + +// Function to start impersonating a user +function impersonate_user($user_id_to_impersonate) { + if (!is_admin()) { + return false; // Only admins can impersonate + } + // Prevent impersonating another admin for security + $db = db(); + $stmt = $db->prepare('SELECT roles.name FROM users JOIN roles ON users.role_id = roles.id WHERE users.id = ?'); + $stmt->execute([$user_id_to_impersonate]); + $role_to_impersonate = $stmt->fetchColumn(); + + if (in_array($role_to_impersonate, ['Super Admin', 'Agency Admin']) && $_SESSION['user_id'] != $user_id_to_impersonate) { + // Allow admins to view their own profile without triggering this rule + return false; + } + + if (!isset($_SESSION['original_user_id'])) { + $_SESSION['original_user_id'] = $_SESSION['user_id']; + } + $_SESSION['user_id'] = $user_id_to_impersonate; + return true; +} + +// Function to stop impersonating +function stop_impersonating() { + if (isset($_SESSION['original_user_id'])) { + $_SESSION['user_id'] = $_SESSION['original_user_id']; + unset($_SESSION['original_user_id']); + return true; + } + return false; +} + +// Function to check if currently impersonating +function is_impersonating() { + return isset($_SESSION['original_user_id']); +} + +// Function to get the current user's data (handles impersonation) +function current_user() { + if (!is_logged_in()) { + return null; + } + $db = db(); + $stmt = $db->prepare('SELECT users.*, roles.name AS role_name FROM users LEFT JOIN roles ON users.role_id = roles.id WHERE users.id = ?'); + $stmt->execute([$_SESSION['user_id']]); + return $stmt->fetch(PDO::FETCH_ASSOC); +} + +// Function to get the original admin user if impersonating +function original_user() { + if (!is_impersonating()) { + return null; + } + $db = db(); + $stmt = $db->prepare('SELECT users.*, roles.name AS role_name FROM users LEFT JOIN roles ON users.role_id = roles.id WHERE users.id = ?'); + $stmt->execute([$_SESSION['original_user_id']]); + return $stmt->fetch(PDO::FETCH_ASSOC); +} diff --git a/includes/pexels.php b/includes/pexels.php new file mode 100644 index 0000000..823ea99 --- /dev/null +++ b/includes/pexels.php @@ -0,0 +1,26 @@ + 0 ? $k : 'Vc99rnmOhHhJAbgGQoKLZtsaIVfkeownoQNbTj78VemUjKh08ZYRbf18'; +} +function pexels_get($url) { + $ch = curl_init(); + curl_setopt_array($ch, [ + CURLOPT_URL => $url, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_HTTPHEADER => [ 'Authorization: '. pexels_key() ], + CURLOPT_TIMEOUT => 15, + ]); + $resp = curl_exec($ch); + $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + if ($code >= 200 && $code < 300 && $resp) return json_decode($resp, true); + return null; +} +function download_to($srcUrl, $destPath) { + $data = file_get_contents($srcUrl); + if ($data === false) return false; + if (!is_dir(dirname($destPath))) mkdir(dirname($destPath), 0775, true); + return file_put_contents($destPath, $data) !== false; +} +?> \ No newline at end of file diff --git a/index.php b/index.php index 299cb8a..2f63c66 100644 --- a/index.php +++ b/index.php @@ -1,3 +1,22 @@ + @@ -23,10 +42,26 @@ + + @@ -41,9 +76,14 @@ +
+ Login + Register +
@@ -52,10 +92,12 @@
-
-

Automate Your Marketing with AI

-

We build intelligent systems to scale your social media, content creation, and client management. Focus on strategy, not busywork.

- Get a Demo +
+
+

Automate Your Marketing with AI

+

We build intelligent systems to scale your social media, content creation, and client management. Focus on strategy, not busywork.

+ Get a Demo +
@@ -69,8 +111,7 @@

Our platform provides a unified portal for your team and clients. Manage projects, approve content, and track performance—all in one place. We integrate with the tools you already love, like Stripe, Calendly, and Meta Ads, to create seamless, automated workflows.

- - Marketing Portal Screenshot + Marketing Professionals Collaborating
@@ -81,9 +122,82 @@

Our Work

-
Project One
Client A

Social Media Growth

-
Project Two
Client B

Content Automation

-
Project Three
Client C

Ad Campaign Management

+
Social Media Growth Project
Client A

Social Media Growth

+
Content Automation Project
Client B

Content Automation

+
Ad Campaign Management Project
Client C

Ad Campaign Management

+
+
+ + + +
+
+

Simple, Transparent Pricing

+

Choose the plan that's right for your business. All prices are placeholders.

+
+ +
+
+
+
Starter
+
$99/month
+
+
    +
  • 1 Client Portal
  • +
  • Content Calendar
  • +
  • Basic Reporting
  • +
  • AI Content Generation
  • +
  • Ad Integration
  • +
  • Dedicated Support
  • +
+ +
+
+
+ +
+ +
+ +
+
+
+
Enterprise
+
$599+/month
+
+
    +
  • Unlimited Client Portals
  • +
  • Content Calendar
  • +
  • Advanced Reporting
  • +
  • AI Content Generation
  • +
  • Ad Integration
  • +
  • Dedicated Support
  • +
+ +
+
+
diff --git a/login.php b/login.php new file mode 100644 index 0000000..2afd55f --- /dev/null +++ b/login.php @@ -0,0 +1,44 @@ + + + + + + + Login - AI-Powered Marketing Portal + + + + + +
+
+
+

Client Login

+
+ +
+ + +
+
+ + +
+ +
+
+

Don't have an account? Register here

+
+
+
+
+ + + + diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..8847e83 --- /dev/null +++ b/logout.php @@ -0,0 +1,7 @@ +query('SELECT users.id, users.name, users.email, roles.name AS role_name FROM users LEFT JOIN roles ON users.role_id = roles.id ORDER BY users.name'); +$users = $stmt->fetchAll(PDO::FETCH_ASSOC); + +$page_title = 'Manage Users'; +include __DIR__ . '/../includes/header.php'; +?> + +
+

Manage Users

+ +
+
+ + + + + + + + + + + + + + + + + + + +
NameEmailRoleActions
+ + Impersonate + + + +
+
+
+
+ + diff --git a/portal/approvals.php b/portal/approvals.php new file mode 100644 index 0000000..6e8b614 --- /dev/null +++ b/portal/approvals.php @@ -0,0 +1,12 @@ + + +
+

Approval Queue

+

This page will display a list of creative assets and other items pending approval. Clients and managers will be able to review and approve or reject work from this screen.

+ +
+ + diff --git a/portal/assets.php b/portal/assets.php new file mode 100644 index 0000000..8c37b5b --- /dev/null +++ b/portal/assets.php @@ -0,0 +1,14 @@ + + +
+

Creative Assets

+

Review and approve creative assets for your projects.

+ +
+
+

There are no assets available for review at this time.

+
+
+
+ + diff --git a/portal/billing.php b/portal/billing.php new file mode 100644 index 0000000..d8dda83 --- /dev/null +++ b/portal/billing.php @@ -0,0 +1,14 @@ + + +
+

Billing

+

View your invoices and manage your subscription.

+ +
+
+

You have no invoices.

+
+
+
+ + diff --git a/portal/calendar.php b/portal/calendar.php new file mode 100644 index 0000000..d3a9801 --- /dev/null +++ b/portal/calendar.php @@ -0,0 +1,12 @@ + + +
+

Project Calendar

+

This page will contain a calendar view of project milestones, deadlines, and other important events. The data will be dynamically loaded based on project and user roles.

+ +
+ + diff --git a/portal/courses.php b/portal/courses.php new file mode 100644 index 0000000..d3f37f5 --- /dev/null +++ b/portal/courses.php @@ -0,0 +1,14 @@ + + +
+

My Courses

+

Access your purchased courses here.

+ +
+
+

You have not purchased any courses yet.

+
+
+
+ + diff --git a/portal/includes/footer.php b/portal/includes/footer.php new file mode 100644 index 0000000..d004ce8 --- /dev/null +++ b/portal/includes/footer.php @@ -0,0 +1,6 @@ +
+ + + + + diff --git a/portal/includes/header.php b/portal/includes/header.php new file mode 100644 index 0000000..25e70b9 --- /dev/null +++ b/portal/includes/header.php @@ -0,0 +1,55 @@ + + + + + + + Client Portal + + + + + + + +
+ You are currently viewing as . + Return to your admin view. +
+ + +
+ Client Portal +
+ Welcome, ! + Logout +
+
+ +
+ +
diff --git a/portal/index.php b/portal/index.php new file mode 100644 index 0000000..704b5ce --- /dev/null +++ b/portal/index.php @@ -0,0 +1,31 @@ + +

Dashboard

+

Welcome to your client portal. Here you can manage your projects, view creative assets, access your courses, and handle billing.

+ +
+
+
+
+
Recent Projects
+

You have no active projects.

+ View Projects +
+
+
+
+
+
+
My Courses
+

You have not enrolled in any courses.

+ View Courses +
+
+
+
+ +
+ + \ No newline at end of file diff --git a/portal/profile.php b/portal/profile.php new file mode 100644 index 0000000..d419026 --- /dev/null +++ b/portal/profile.php @@ -0,0 +1,16 @@ + + +
+

My Profile

+

Your account information.

+ +
+
+

Name:

+

Email:

+

Role:

+
+
+
+ + diff --git a/portal/projects.php b/portal/projects.php new file mode 100644 index 0000000..646e333 --- /dev/null +++ b/portal/projects.php @@ -0,0 +1,14 @@ + + +
+

My Projects

+

Here is a list of your projects and their current status.

+ +
+
+

No projects have been assigned to you yet.

+
+
+
+ + diff --git a/register.php b/register.php new file mode 100644 index 0000000..16c79da --- /dev/null +++ b/register.php @@ -0,0 +1,48 @@ + + + + + + + Register - AI-Powered Marketing Portal + + + + + +
+
+
+

Create Account

+
+ +
+ + +
+
+ + +
+
+ + +
+ +
+
+

Already have an account? Login here

+
+
+
+
+ + + +