<?php
// Start the session
session_start();
// Include database configuration
require_once 'database/db_config.php';
// Check if user is logged in and is an admin
if (!isset($_SESSION['user_id']) || !isset($_SESSION['role']) || ($_SESSION['role'] != 'admin' && $_SESSION['role'] != 'director')) {
header('Location: login.php');
exit;
}
// Process form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Get form data
$title = $conn->real_escape_string($_POST['title']);
$short_description = $conn->real_escape_string($_POST['short_description']);
$description = $conn->real_escape_string($_POST['description']);
$category = $conn->real_escape_string($_POST['category']); // Primary category
$categories = isset($_POST['categories']) ? $_POST['categories'] : array(); // Multiple categories
$price = (float) $_POST['price'];
$discount_price = !empty($_POST['discount_price']) ? (float) $_POST['discount_price'] : NULL;
$status = $conn->real_escape_string($_POST['status']);
$level = $conn->real_escape_string($_POST['level']);
$language = $conn->real_escape_string($_POST['language']);
$lessons_count = (int) $_POST['lessons_count'];
$certificate = isset($_POST['certificate']) ? 1 : 0;
$duration = $conn->real_escape_string($_POST['duration']); // Store numeric value
$duration_unit = $conn->real_escape_string($_POST['duration_unit']); // Store unit (days, weeks, months)
$duration_formatted = $duration . ' ' . $duration_unit; // Combined for display
$is_featured = isset($_POST['is_featured']) ? 1 : 0;
$tags = $conn->real_escape_string($_POST['tags']);
$course_code = $conn->real_escape_string($_POST['course_code']);
// Handle image upload
$image_path = '';
if (isset($_FILES['image']) && $_FILES['image']['error'] == 0) {
$upload_dir = '../assets/img/courses/';
// Create directory if it doesn't exist
if (!file_exists($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
$file_name = time() . '_' . basename($_FILES['image']['name']);
$target_file = $upload_dir . $file_name;
$image_path = 'assets/img/courses/' . $file_name;
// Check if file is an actual image
$check = getimagesize($_FILES['image']['tmp_name']);
if ($check === false) {
$_SESSION['error_message'] = "File is not an image.";
header('Location: course-add.php');
exit;
}
// Check file size (max 5MB)
if ($_FILES['image']['size'] > 5000000) {
$_SESSION['error_message'] = "Sorry, your file is too large. Max size is 5MB.";
header('Location: course-add.php');
exit;
}
// Allow certain file formats
$imageFileType = strtolower(pathinfo($target_file, PATHINFO_EXTENSION));
if ($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg" && $imageFileType != "gif" && $imageFileType != "webp") {
$_SESSION['error_message'] = "Sorry, only JPG, JPEG, PNG, GIF & WebP files are allowed.";
header('Location: course-add.php');
exit;
}
// Upload the file
if (!move_uploaded_file($_FILES['image']['tmp_name'], $target_file)) {
$_SESSION['error_message'] = "Sorry, there was an error uploading your file.";
header('Location: course-add.php');
exit;
}
} else {
// Use default image path if no image uploaded
$image_path = 'assets/img/defaults/default-course-image.jpg';
}
// Prepare the SQL query
$sql = "INSERT INTO courses (title, short_description, description, category, price, discount_price, image, status, level, language, lessons_count, certificate, duration, is_featured, tags, course_code, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())";
$stmt = $conn->prepare($sql);
$stmt->bind_param("sssiidssssiisss", $title, $short_description, $description, $category, $price, $discount_price, $image_path, $status, $level, $language, $lessons_count, $certificate, $duration_formatted, $is_featured, $tags, $course_code);
if ($stmt->execute()) {
// Get the new course ID
$course_id = $conn->insert_id;
// Add primary category to the junction table
$insert_cat = "INSERT INTO course_categories (course_id, category_id) VALUES (?, ?)";
$insert_stmt = $conn->prepare($insert_cat);
$insert_stmt->bind_param("ii", $course_id, $cat_id);
$cat_id = $category;
$insert_stmt->execute();
// Add additional categories
if (!empty($categories)) {
foreach ($categories as $cat_id) {
if ($cat_id != $category) { // Skip primary category to avoid duplicates
$insert_stmt->execute();
}
}
}
$_SESSION['success_message'] = "Course added successfully!";
header('Location: courses.php');
exit;
} else {
$_SESSION['error_message'] = "Error adding course: " . $conn->error;
header('Location: course-add.php');
exit;
}
}
// Get all active instructors
$instructors_query = "SELECT id, first_name, last_name FROM users WHERE (role = 'instructor' OR role = 'director' OR role = 'developer') AND status = 'active' ORDER BY first_name";
$instructors_result = $conn->query($instructors_query);
// Get all categories
$categories_query = "SELECT id, name FROM categories ORDER BY name";
$categories_result = $conn->query($categories_query);
// Include header
include 'includes/header.php';
?>
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Add New Course</h1>
<a href="courses.php" class="d-none d-sm-inline-block btn btn-sm btn-secondary shadow-sm">
<i class="fas fa-arrow-left fa-sm text-white-50"></i> Back to Courses
</a>
</div>
<?php if (isset($_SESSION['error_message'])): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<?php
echo $_SESSION['error_message'];
unset($_SESSION['error_message']);
?>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<?php endif; ?>
<!-- Course Add Form -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Course Information</h6>
</div>
<div class="card-body">
<form action="course-add.php" method="POST" enctype="multipart/form-data">
<div class="row">
<div class="col-md-8">
<div class="form-group">
<label for="title">Course Title*</label>
<input type="text" class="form-control" id="title" name="title" required>
</div>
<div class="form-group">
<label for="short_description">Short Description*</label>
<textarea class="form-control" id="short_description" name="short_description" rows="3" required></textarea>
<small class="form-text text-muted">A brief summary of the course (max 255 characters)</small>
</div>
<div class="form-group">
<label for="description">Full Description*</label>
<textarea class="form-control" id="description" name="description" rows="8" required></textarea>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="image">Course Image</label>
<div class="custom-file">
<input type="file" class="custom-file-input" id="image" name="image" accept="image/*">
<label class="custom-file-label" for="image">Choose file...</label>
</div>
<small class="form-text text-muted">Recommended size: 1200x800 pixels (16:9)</small>
<div class="mt-2">
<img id="imagePreview" src="../assets/img/defaults/default-course-image.jpg" class="img-fluid img-thumbnail" style="max-height: 200px;">
</div>
</div>
<div class="form-group">
<label for="category">Primary Category*</label>
<select class="form-control" id="category" name="category" required>
<option value="">Select Primary Category</option>
<?php
if ($categories_result && $categories_result->num_rows > 0) {
while ($category = $categories_result->fetch_assoc()) {
echo '<option value="' . $category['id'] . '">' . htmlspecialchars($category['name']) . '</option>';
}
}
?>
</select>
</div>
<div class="form-group">
<label for="categories">Additional Categories</label>
<select class="form-control" id="categories" name="categories[]" multiple size="5">
<?php
if ($categories_result && $categories_result->num_rows > 0) {
// Reset result pointer
$categories_result->data_seek(0);
while ($category = $categories_result->fetch_assoc()) {
echo '<option value="' . $category['id'] . '">' . htmlspecialchars($category['name']) . '</option>';
}
}
?>
</select>
<small class="form-text text-muted">Hold Ctrl (Cmd on Mac) to select multiple categories</small>
</div>
<div class="form-group">
<label for="course_code">Course Code</label>
<input type="text" class="form-control" id="course_code" name="course_code" maxlength="20" placeholder="e.g., CS101">
<small class="form-text text-muted">Unique code used for enrollment numbers</small>
</div>
<div class="form-group">
<label for="level">Level*</label>
<select class="form-control" id="level" name="level" required>
<option value="beginner">Beginner</option>
<option value="intermediate">Intermediate</option>
<option value="advanced">Advanced</option>
<option value="all-levels">All Levels</option>
</select>
</div>
<div class="form-group">
<label for="language">Language*</label>
<select class="form-control" id="language" name="language" required>
<option value="English">English</option>
<option value="Hindi">Hindi</option>
<option value="Marathi">Marathi</option>
<option value="Tamil">Tamil</option>
<option value="Telugu">Telugu</option>
<option value="Kannada">Kannada</option>
<option value="Malayalam">Malayalam</option>
<option value="Gujarati">Gujarati</option>
<option value="Bengali">Bengali</option>
</select>
</div>
<div class="form-group">
<label for="lessons_count">Number of Lessons</label>
<input type="number" class="form-control" id="lessons_count" name="lessons_count" min="0" value="0">
<small class="form-text text-muted">Enter the total number of lessons in this course</small>
</div>
<div class="form-group">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="certificate" name="certificate" value="1">
<label class="custom-control-label" for="certificate">Certificate Available</label>
</div>
</div>
<div class="form-group">
<label for="duration">Course Duration*</label>
<div class="input-group">
<input type="number" class="form-control" id="duration" name="duration" required min="1" value="1">
<div class="input-group-append">
<select class="form-control" id="duration_unit" name="duration_unit">
<option value="days">Days</option>
<option value="weeks">Weeks</option>
<option value="months" selected>Months</option>
</select>
</div>
</div>
<small class="form-text text-muted">The expected duration of the course. This will be used to calculate expected completion dates.</small>
</div>
<div class="form-group">
<label for="tags">Course Tags (SEO)</label>
<input type="text" class="form-control" id="tags" name="tags">
<small class="form-text text-muted">Enter comma-separated tags for SEO</small>
</div>
</div>
</div>
<hr>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="price">Price (INR)*</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">₹</span>
</div>
<input type="number" class="form-control" id="price" name="price" min="0" step="0.01" value="0.00" required>
</div>
<small class="form-text text-muted">Set to 0 for free courses</small>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="discount_price">Discount Price (INR)</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">₹</span>
</div>
<input type="number" class="form-control" id="discount_price" name="discount_price" min="0" step="0.01">
</div>
<small class="form-text text-muted">Leave empty for no discount</small>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="status">Status*</label>
<select class="form-control" id="status" name="status" required>
<option value="draft">Draft</option>
<option value="active">Published</option>
<option value="inactive">Inactive</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="form-group mt-4">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="is_featured" name="is_featured">
<label class="custom-control-label" for="is_featured">Feature this course on homepage</label>
</div>
</div>
</div>
</div>
<div class="form-group text-center mt-4">
<button type="submit" class="btn btn-primary btn-lg px-5">Add Course</button>
</div>
</form>
</div>
</div>
</div>
<!-- /.container-fluid -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// Initialize CKEditor for rich text editing
if (typeof ClassicEditor !== 'undefined') {
ClassicEditor
.create(document.querySelector('#description'))
.catch(error => {
console.error(error);
});
}
// File input preview
document.getElementById('image').addEventListener('change', function(e) {
if (e.target.files && e.target.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
document.getElementById('imagePreview').src = e.target.result;
}
reader.readAsDataURL(e.target.files[0]);
// Update file input label
var fileName = e.target.files[0].name;
var label = document.querySelector('.custom-file-label');
label.textContent = fileName;
}
});
});
</script>
<?php
// Include footer
include 'includes/footer.php';
?>