diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..b77b249 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,88 @@ +# Installation Guide + +Follow these steps to set up the application on your server. + +## 1. Requirements + +Before you begin, ensure your server meets the following requirements: + +* **Operating System:** Linux, Windows, or macOS. +* **Web Server:** Apache 2.4+ (with `mod_rewrite` enabled). +* **PHP:** Version 8.0 or higher. +* **Database:** MariaDB 10.4+ or MySQL 5.7+. +* **PHP Extensions:** + * `pdo_mysql` + * `curl` + * `gd` (for image processing) + * `mbstring` + * `json` + +## 2. Database Setup + +1. **Create a Database:** Create a new MySQL/MariaDB database (e.g., `pos_system`). +2. **Configure Connection:** Rename `db/config.php.example` to `db/config.php` (if not already present) and update the database credentials: + ```php + define('DB_HOST', 'localhost'); + define('DB_NAME', 'your_database_name'); + define('DB_USER', 'your_username'); + define('DB_PASS', 'your_password'); + ``` +3. **Import Schema:** Import the base schema from `db/schema.sql` into your database. +4. **Run Migrations:** Import all SQL files located in `db/migrations/` in sequential order (001, 002, etc.). +5. **Initialize Data:** Run the initialization script by visiting `http://your-domain.com/db/init.php` in your browser. This will seed categories, products, and outlets. + +## 3. Creating a Super Admin + +Since the initial setup does not include a default user for security reasons, you must create the first Administrator account. + +### Option A: Using the Setup Script (Recommended) +Create a temporary file named `setup_admin.php` in the root directory with the following content: + +```php +prepare("SELECT id FROM user_groups WHERE name = 'Administrator' LIMIT 1"); +$stmt->execute(); +$group_id = $stmt->fetchColumn(); + +if (!$group_id) { + $pdo->exec("INSERT INTO user_groups (name, permissions) VALUES ('Administrator', 'all')"); + $group_id = $pdo->lastInsertId(); +} + +// Create the user +try { + $stmt = $pdo->prepare("INSERT INTO users (group_id, username, password, full_name, email, is_active) VALUES (?, ?, ?, ?, ?, 1)"); + $stmt->execute([$group_id, $username, $password, $full_name, $email]); + echo "Super Admin created successfully!
Username: admin
Password: admin123
Please delete this file immediately!"; +} catch (Exception $e) { + echo "Error: " . $e->getMessage(); +} +``` + +Visit `http://your-domain.com/setup_admin.php` and then **delete the file**. + +### Option B: Manual SQL +If you prefer SQL, run the following (replace the password hash with one generated via `password_hash()` in PHP): +```sql +INSERT INTO users (group_id, username, password, full_name, email, is_active) +VALUES (1, 'admin', 'REPLACE_WITH_HASH', 'Super Admin', 'admin@example.com', 1); +``` + +## 4. Final Steps + +1. **File Permissions:** Ensure the `assets/images/` directory is writable by the web server for uploading product and ad images. +2. **Login:** Go to `http://your-domain.com/login.php` and log in with your new credentials. +3. **Company Settings:** Navigate to **Admin -> Company Settings** to configure your restaurant name, address, and currency. + +--- +**Security Note:** Always ensure your `db/config.php` and `.env` files are not accessible from the public web. diff --git a/admin/includes/header.php b/admin/includes/header.php index 24cdbb7..b8c3b0f 100644 --- a/admin/includes/header.php +++ b/admin/includes/header.php @@ -457,7 +457,7 @@ function can_view($module) { @@ -488,6 +488,11 @@ function can_view($module) { Attendance + @@ -578,4 +583,4 @@ function can_view($module) { - \ No newline at end of file + diff --git a/admin/rating.php b/admin/rating.php new file mode 100644 index 0000000..bc4f3e7 --- /dev/null +++ b/admin/rating.php @@ -0,0 +1,3 @@ +query(" + SELECT u.id, u.full_name, u.username, u.profile_pic, + AVG(r.rating) as avg_rating, COUNT(r.id) as total_ratings + FROM users u + JOIN staff_ratings r ON u.id = r.user_id + GROUP BY u.id + ORDER BY avg_rating DESC +"); +$summaries = $summaryStmt->fetchAll(PDO::FETCH_ASSOC); + +// Fetch Service summary stats +$serviceSummaryStmt = $pdo->query(" + SELECT AVG(rating) as avg_rating, COUNT(id) as total_ratings FROM service_ratings +"); +$serviceSummary = $serviceSummaryStmt->fetch(PDO::FETCH_ASSOC); + +if ($tab === 'service') { + $query = "SELECT * FROM service_ratings ORDER BY created_at DESC"; +} else { + $query = " + SELECT r.*, u.full_name, u.username, u.profile_pic + FROM staff_ratings r + JOIN users u ON r.user_id = u.id + ORDER BY r.created_at DESC + "; +} + +$pagination = paginate_query($pdo, $query); +$ratings = $pagination['data']; +?> + +
+

Ratings & Feedback

+
+ + + Open Public Rating Page + +
+
+ + + + + + +
+ +

No staff members have been rated yet.

+
+ +
+ +
+
+
+ + Staff + +
+ +
+ +
+ +
+
+ ' : ''; + } + ?> + () +
+

total ratings

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

Overall Service

+
+ 0): ?> + / 5.0 + + N/A + +
+
+ Based on customer reviews +
+
+
+
+
+ + + +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
DateStaff MemberRatingComment
No ratings found yet.
+ + +
+ + + + +
+
+
+ ' : ''; + } + ?> +
+
+ +
+
+ +
+ + + + + + + \ No newline at end of file diff --git a/admin/user_edit.php b/admin/user_edit.php index ebffd8b..b34961a 100644 --- a/admin/user_edit.php +++ b/admin/user_edit.php @@ -26,6 +26,7 @@ if ($id) { 'group_id' => '', 'employee_id' => '', 'is_active' => 1, + 'is_ratable' => 0, 'profile_pic' => '', 'created_at' => date('Y-m-d H:i:s') ]; @@ -40,6 +41,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $group_id = $_POST['group_id']; $employee_id = $_POST['employee_id'] ?? null; $is_active = isset($_POST['is_active']) ? 1 : 0; + $is_ratable = isset($_POST['is_ratable']) ? 1 : 0; $assigned_outlets = $_POST['outlets'] ?? []; $password = $_POST['password'] ?? ''; @@ -60,8 +62,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { try { if ($id) { // Update - $sql = "UPDATE users SET full_name = ?, username = ?, email = ?, group_id = ?, is_active = ?, employee_id = ? WHERE id = ?"; - $params = [$full_name, $username, $email, $group_id, $is_active, $employee_id, $id]; + $sql = "UPDATE users SET full_name = ?, username = ?, email = ?, group_id = ?, is_active = ?, is_ratable = ?, employee_id = ? WHERE id = ?"; + $params = [$full_name, $username, $email, $group_id, $is_active, $is_ratable, $employee_id, $id]; $stmt = $pdo->prepare($sql); $stmt->execute($params); @@ -73,8 +75,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } else { // Insert $hashed_password = password_hash($password, PASSWORD_DEFAULT); - $sql = "INSERT INTO users (full_name, username, email, group_id, is_active, employee_id, password) VALUES (?, ?, ?, ?, ?, ?, ?)"; - $params = [$full_name, $username, $email, $group_id, $is_active, $employee_id, $hashed_password]; + $sql = "INSERT INTO users (full_name, username, email, group_id, is_active, is_ratable, employee_id, password) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; + $params = [$full_name, $username, $email, $group_id, $is_active, $is_ratable, $employee_id, $hashed_password]; $stmt = $pdo->prepare($sql); $stmt->execute($params); $user_id = $pdo->lastInsertId(); @@ -237,10 +239,19 @@ include 'includes/header.php';
Assign one or more outlets to this user.
-
-
- > - +
+
+
+ > + +
+
+
+
+ > + +
+
Enable this to allow customers to rate this staff member in the public rating page.
diff --git a/admin/users.php b/admin/users.php index f269c15..3501600 100644 --- a/admin/users.php +++ b/admin/users.php @@ -74,8 +74,9 @@ include 'includes/header.php'; User Role / Group - Employee ID + Emp. ID Email + Ratable Status Joined Actions @@ -104,7 +105,15 @@ include 'includes/header.php'; + + + + Yes + + No + + Active diff --git a/db/migrations/020_staff_ratings.sql b/db/migrations/020_staff_ratings.sql new file mode 100644 index 0000000..a73cc14 --- /dev/null +++ b/db/migrations/020_staff_ratings.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS staff_ratings ( + id INT AUTO_INCREMENT PRIMARY KEY, + user_id INT NOT NULL, + rating INT NOT NULL CHECK (rating >= 1 AND rating <= 5), + comment TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE +); diff --git a/db/migrations/021_add_is_ratable_to_users.sql b/db/migrations/021_add_is_ratable_to_users.sql new file mode 100644 index 0000000..0cbec43 --- /dev/null +++ b/db/migrations/021_add_is_ratable_to_users.sql @@ -0,0 +1,5 @@ +-- Migration: Add is_ratable to users table +-- Description: Allows choosing specific staff members to be rated by customers. +-- Date: 2026-02-23 + +ALTER TABLE users ADD COLUMN is_ratable TINYINT(1) DEFAULT 0; diff --git a/db/migrations/022_service_ratings.sql b/db/migrations/022_service_ratings.sql new file mode 100644 index 0000000..b13e69e --- /dev/null +++ b/db/migrations/022_service_ratings.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS service_ratings ( + id INT AUTO_INCREMENT PRIMARY KEY, + rating INT NOT NULL CHECK (rating >= 1 AND rating <= 5), + comment TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); diff --git a/includes/functions.php b/includes/functions.php index 338c5f6..70110bd 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -288,4 +288,20 @@ function require_permission($permission) { echo "Access Denied: You don't have permission to access this page."; exit; } -} \ No newline at end of file +} + +/** + * Get the base URL of the application. + * + * @return string The base URL. + */ +function get_base_url() { + $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; + $domainName = $_SERVER['HTTP_HOST']; + // Remove admin/ if we are in it + $script_dir = dirname($_SERVER['SCRIPT_NAME']); + $script_dir = str_replace(['/admin', '/api'], '', $script_dir); + if ($script_dir === '/') $script_dir = ''; + + return $protocol . $domainName . $script_dir . '/'; +} diff --git a/index.php b/index.php index 3fa41e5..5c5861c 100644 --- a/index.php +++ b/index.php @@ -9,6 +9,7 @@ $settings = get_company_settings(); <?= htmlspecialchars($settings['company_name']) ?> - Welcome + @@ -17,128 +18,226 @@ $settings = get_company_settings(); - -
-
-
-
- - - - -
- -
- - -

-

Welcome! How would you like to order?

- - - - +
+
+
+
+ + + + +
+
+ - +

+

Your all-in-one business management solution.

+ + + +
+

+ Authorized staff access only. +

+
+
+ + \ No newline at end of file diff --git a/pos.php b/pos.php index 08c4510..457a407 100644 --- a/pos.php +++ b/pos.php @@ -110,7 +110,7 @@ if (!$loyalty_settings) { -
+
Kitchen View @@ -125,8 +125,12 @@ if (!$loyalty_settings) { Current Orders + +
- -
- - -
- -
- > - - - > - - - > - + +
+
+
Current Order
+ 0 items +
+ + +
+
+ + + +
+
+ + +
+
- -
-
- - - -
-
- - -
- +
+
- - - -
-
-
- Loyalty Points - 0 -
- -
-
-
-
-
- - -
-
- -

Cart is empty

-
-
- - -
-
- Subtotal - -
- - -
- Discount -
- - - -
-
- -
- Total - -
- - -
- - -
- -
- View Only Mode -
- - -
- Powered By Abidarcafe @2026 -
-
- +
@@ -449,14 +411,45 @@ if (!$loyalty_settings) {
+ + + - \ No newline at end of file + diff --git a/rate.php b/rate.php new file mode 100644 index 0000000..3d52460 --- /dev/null +++ b/rate.php @@ -0,0 +1,375 @@ +prepare("INSERT INTO service_ratings (rating, comment) VALUES (?, ?)"); + $stmt->execute([$rating, $comment]); + $success = true; + } else if ($userId) { + $stmt = $pdo->prepare("INSERT INTO staff_ratings (user_id, rating, comment) VALUES (?, ?, ?)"); + $stmt->execute([$userId, $rating, $comment]); + $success = true; + } else { + $error = "Please select a staff member."; + } + } catch (Exception $e) { + $error = "Error saving rating: " . $e->getMessage(); + } + } else { + $error = "Please provide a rating."; + } +} + +// Fetch active and ratable users with pictures +$pdo = db(); +$stmt = $pdo->query("SELECT id, full_name, username, profile_pic FROM users WHERE is_active = 1 AND is_ratable = 1 ORDER BY full_name ASC"); +$users = $stmt->fetchAll(PDO::FETCH_ASSOC); +?> + + + + + + Rate Our Service - <?= htmlspecialchars($companyName) ?> + + + + + + + +
+
+ +
+
+ + + +

+ +

We value your feedback! What would you like to rate?

+
+ + +
+
+ +

Thank You!

+

Your rating has been submitted successfully.

+ Back to Home +
+
+ + + + + +
+ +
+
+
+ +
+
Rate Our Services
+

How was your overall experience with us?

+
+
+ +
+
OR RATE OUR STAFF
+
+ + +
+

No staff members are currently available for rating.

+
+ + +
+
+ + <?= htmlspecialchars($user['full_name']) ?> + +
+ +
+ +
+
+
+ + +
+ +
+ + + +
+

Rate

+

+ +
+ + + + + +
+
+ +
+ + +
+ +
+
+ +
+
+ +
+
+
+ +
+ + + + + \ No newline at end of file