diff --git a/add_scene.php b/add_scene.php
new file mode 100644
index 0000000..c1b2a46
--- /dev/null
+++ b/add_scene.php
@@ -0,0 +1,71 @@
+ 'User not authenticated']);
+ exit;
+}
+
+require_once 'db/config.php';
+
+$request_body = file_get_contents('php://input');
+$data = json_decode($request_body, true);
+
+if ($_SERVER['REQUEST_METHOD'] !== 'POST' || json_last_error() !== JSON_ERROR_NONE) {
+ http_response_code(400);
+ echo json_encode(['error' => 'Invalid request']);
+ exit;
+}
+
+$project_id = filter_var($data['project_id'] ?? null, FILTER_VALIDATE_INT);
+$description = trim($data['description'] ?? '');
+$duration = filter_var($data['duration'] ?? null, FILTER_VALIDATE_INT);
+$shot_type = trim($data['shot_type'] ?? '');
+
+if (!$project_id || empty($description) || !$duration || empty($shot_type)) {
+ http_response_code(400);
+ echo json_encode(['error' => 'Invalid input. Required fields: project_id, description, duration, shot_type']);
+ exit;
+}
+
+try {
+ $pdo = db();
+
+ // Verify project ownership and status
+ $stmt = $pdo->prepare("SELECT status FROM projects WHERE id = ? AND user_id = ?");
+ $stmt->execute([$project_id, $_SESSION['user_id']]);
+ $project = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (!$project) {
+ http_response_code(404);
+ echo json_encode(['error' => 'Project not found or you do not have permission to access it.']);
+ exit;
+ }
+
+ if ($project['status'] !== 'draft') {
+ http_response_code(403);
+ echo json_encode(['error' => 'Project is not in draft status, scenes cannot be added.']);
+ exit;
+ }
+
+ // Insert new scene
+ $stmt = $pdo->prepare("INSERT INTO scenes (project_id, user_id, description, duration, shot_type) VALUES (?, ?, ?, ?, ?)");
+ $stmt->execute([$project_id, $_SESSION['user_id'], $description, $duration, $shot_type]);
+
+ $new_scene_id = $pdo->lastInsertId();
+
+ // Fetch the newly created scene
+ $stmt = $pdo->prepare("SELECT * FROM scenes WHERE id = ?");
+ $stmt->execute([$new_scene_id]);
+ $scene = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ http_response_code(201);
+ echo json_encode($scene);
+
+} catch (PDOException $e) {
+ http_response_code(500);
+ // error_log("Database error: " . $e->getMessage()); // It's good practice to log the actual error
+ echo json_encode(['error' => 'Database error.']);
+}
\ No newline at end of file
diff --git a/assets/css/custom.css b/assets/css/custom.css
new file mode 100644
index 0000000..7f9cbd2
--- /dev/null
+++ b/assets/css/custom.css
@@ -0,0 +1,39 @@
+:root {
+ --primary-color: #4F46E5;
+ --light-gray: #f8f9fa;
+ --white: #ffffff;
+}
+
+body {
+ background-color: var(--light-gray);
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+}
+
+.card {
+ border: none;
+ border-radius: .75rem;
+ box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
+}
+
+.card-header {
+ background-color: var(--white);
+ border-bottom: none;
+ padding: 1.5rem;
+ font-weight: 700;
+}
+
+.btn-primary {
+ background-color: var(--primary-color);
+ border-color: var(--primary-color);
+ padding: .75rem 1.5rem;
+}
+
+.btn-primary:hover {
+ background-color: #4338CA;
+ border-color: #4338CA;
+}
+
+.form-control:focus {
+ border-color: var(--primary-color);
+ box-shadow: 0 0 0 0.25rem rgba(79, 70, 229, 0.25);
+}
diff --git a/assets/pasted-20260101-095324-285a9cb6.png b/assets/pasted-20260101-095324-285a9cb6.png
new file mode 100644
index 0000000..89f6df1
Binary files /dev/null and b/assets/pasted-20260101-095324-285a9cb6.png differ
diff --git a/assets/pasted-20260101-095442-40a3627d.png b/assets/pasted-20260101-095442-40a3627d.png
new file mode 100644
index 0000000..e652412
Binary files /dev/null and b/assets/pasted-20260101-095442-40a3627d.png differ
diff --git a/create_project.php b/create_project.php
new file mode 100644
index 0000000..a877c85
--- /dev/null
+++ b/create_project.php
@@ -0,0 +1,52 @@
+ 'Authentication required.']);
+ exit;
+}
+
+require_once 'db/config.php';
+
+if ($_SERVER["REQUEST_METHOD"] !== "POST") {
+ http_response_code(405);
+ echo json_encode(['error' => 'Method Not Allowed']);
+ exit;
+}
+
+$input = json_decode(file_get_contents('php://input'), true);
+
+$title = $input['title'] ?? null;
+$story_text = $input['story_text'] ?? null;
+$style = $input['style'] ?? null;
+$target_duration = isset($input['target_duration']) ? filter_var($input['target_duration'], FILTER_VALIDATE_INT) : null;
+
+if (empty($title)) {
+ http_response_code(400);
+ echo json_encode(['error' => 'Title is a required field.']);
+ exit;
+}
+
+try {
+ $pdo = db();
+ $stmt = $pdo->prepare(
+ "INSERT INTO projects (user_id, title, story_text, style, target_duration, status) VALUES (?, ?, ?, ?, ?, 'draft')"
+ );
+ $stmt->execute([$_SESSION['user_id'], $title, $story_text, $style, $target_duration]);
+
+ $projectId = $pdo->lastInsertId();
+
+ $stmt = $pdo->prepare("SELECT * FROM projects WHERE id = ? AND user_id = ?");
+ $stmt->execute([$projectId, $_SESSION['user_id']]);
+ $project = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ http_response_code(201);
+ echo json_encode($project);
+
+} catch (PDOException $e) {
+ http_response_code(500);
+ error_log('Project creation failed: ' . $e->getMessage());
+ echo json_encode(['error' => 'An internal server error occurred while creating the project.']);
+}
\ No newline at end of file
diff --git a/db/migrate.php b/db/migrate.php
new file mode 100644
index 0000000..2a90eb2
--- /dev/null
+++ b/db/migrate.php
@@ -0,0 +1,58 @@
+exec($sql);
+
+ $sql = "
+ CREATE TABLE IF NOT EXISTS `projects` (
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
+ `user_id` INT NOT NULL,
+ `title` VARCHAR(255) NOT NULL,
+ `story_text` TEXT,
+ `style` VARCHAR(100),
+ `target_duration` INT,
+ `status` ENUM('draft', 'scripted', 'rendering', 'completed', 'failed') DEFAULT 'draft',
+ `final_video_url` VARCHAR(255) NULL,
+ `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
+ );
+ ";
+ $pdo->exec($sql);
+
+ $sql = "
+ CREATE TABLE IF NOT EXISTS `scenes` (
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
+ `project_id` INT NOT NULL,
+ `user_id` INT NOT NULL,
+ `scene_number` INT NULL,
+ `description` TEXT,
+ `duration` INT,
+ `shot_type` VARCHAR(100),
+ `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
+ );
+ ";
+ $pdo->exec($sql);
+
+ echo "Database migration completed successfully." . PHP_EOL;
+} catch (PDOException $e) {
+ die("Database migration failed: " . $e->getMessage());
+}
diff --git a/delete_project.php b/delete_project.php
new file mode 100644
index 0000000..9097ecb
--- /dev/null
+++ b/delete_project.php
@@ -0,0 +1,68 @@
+ 'User not authenticated']);
+ exit;
+}
+
+require_once 'db/config.php';
+
+$project_id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
+if (!$project_id) {
+ http_response_code(400);
+ echo json_encode(['error' => 'Project ID is required.']);
+ exit;
+}
+
+if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
+ http_response_code(405);
+ echo json_encode(['error' => 'POST method required.']);
+ exit;
+}
+
+try {
+ $pdo = db();
+
+ // Begin a transaction
+ $pdo->beginTransaction();
+
+ // Verify project ownership
+ $stmt = $pdo->prepare("SELECT id FROM projects WHERE id = ? AND user_id = ?");
+ $stmt->execute([$project_id, $_SESSION['user_id']]);
+ $project = $stmt->fetch();
+
+ if (!$project) {
+ http_response_code(404);
+ $pdo->rollBack();
+ echo json_encode(['error' => 'Project not found or permission denied.']);
+ exit;
+ }
+
+ // Delete associated scenes first to maintain integrity
+ $stmt = $pdo->prepare("DELETE FROM scenes WHERE project_id = ?");
+ $stmt->execute([$project_id]);
+
+ // Now, delete the project
+ $stmt = $pdo->prepare("DELETE FROM projects WHERE id = ?");
+ $stmt->execute([$project_id]);
+
+ if ($stmt->rowCount() > 0) {
+ $pdo->commit();
+ echo json_encode(['success' => 'Project and all its scenes were deleted successfully.']);
+ } else {
+ $pdo->rollBack();
+ http_response_code(500); // Should not happen if ownership check passed
+ echo json_encode(['error' => 'Failed to delete project.']);
+ }
+
+} catch (PDOException $e) {
+ if ($pdo->inTransaction()) {
+ $pdo->rollBack();
+ }
+ http_response_code(500);
+ // error_log("Database error: " . $e->getMessage());
+ echo json_encode(['error' => 'Database error during project deletion.']);
+}
\ No newline at end of file
diff --git a/delete_scene.php b/delete_scene.php
new file mode 100644
index 0000000..0fa4a89
--- /dev/null
+++ b/delete_scene.php
@@ -0,0 +1,66 @@
+ 'User not authenticated']);
+ exit;
+}
+
+require_once 'db/config.php';
+
+$scene_id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
+if (!$scene_id) {
+ http_response_code(400);
+ echo json_encode(['error' => 'Scene ID is required.']);
+ exit;
+}
+
+if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
+ http_response_code(405);
+ echo json_encode(['error' => 'POST method required.']);
+ exit;
+}
+
+try {
+ $pdo = db();
+
+ // Fetch scene info to get project_id and verify ownership/status
+ $stmt = $pdo->prepare("
+ SELECT s.project_id, p.status as project_status
+ FROM scenes s
+ JOIN projects p ON s.project_id = p.id
+ WHERE s.id = ? AND s.user_id = ?
+ ");
+ $stmt->execute([$scene_id, $_SESSION['user_id']]);
+ $scene = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (!$scene) {
+ http_response_code(404);
+ echo json_encode(['error' => 'Scene not found or permission denied.']);
+ exit;
+ }
+
+ if ($scene['project_status'] !== 'draft') {
+ http_response_code(403);
+ echo json_encode(['error' => 'Project is not in draft status; scene cannot be deleted.']);
+ exit;
+ }
+
+ // Delete the scene
+ $stmt = $pdo->prepare("DELETE FROM scenes WHERE id = ?");
+ $stmt->execute([$scene_id]);
+
+ if ($stmt->rowCount() > 0) {
+ echo json_encode(['success' => 'Scene deleted successfully.']);
+ } else {
+ http_response_code(500); // This case might indicate an issue if the check passed but delete failed
+ echo json_encode(['error' => 'Failed to delete scene.']);
+ }
+
+} catch (PDOException $e) {
+ http_response_code(500);
+ // error_log("Database error: " . $e->getMessage());
+ echo json_encode(['error' => 'Database error.']);
+}
\ No newline at end of file
diff --git a/edit_project.php b/edit_project.php
new file mode 100644
index 0000000..a07537f
--- /dev/null
+++ b/edit_project.php
@@ -0,0 +1,81 @@
+ 'User not authenticated']);
+ exit;
+}
+
+require_once 'db/config.php';
+
+$project_id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
+if (!$project_id) {
+ http_response_code(400);
+ echo json_encode(['error' => 'Project ID is required.']);
+ exit;
+}
+
+if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
+ http_response_code(405);
+ echo json_encode(['error' => 'POST method required.']);
+ exit;
+}
+
+$request_body = file_get_contents('php://input');
+$data = json_decode($request_body, true);
+if (json_last_error() !== JSON_ERROR_NONE) {
+ http_response_code(400);
+ echo json_encode(['error' => 'Invalid JSON input.']);
+ exit;
+}
+
+try {
+ $pdo = db();
+
+ // Verify project ownership and status
+ $stmt = $pdo->prepare("SELECT status FROM projects WHERE id = ? AND user_id = ?");
+ $stmt->execute([$project_id, $_SESSION['user_id']]);
+ $project = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (!$project) {
+ http_response_code(404);
+ echo json_encode(['error' => 'Project not found or permission denied.']);
+ exit;
+ }
+
+ if ($project['status'] !== 'draft') {
+ http_response_code(403);
+ echo json_encode(['error' => 'Project is not in draft status and cannot be edited.']);
+ exit;
+ }
+
+ // Get new data from request body
+ $title = trim($data['title'] ?? '');
+ $story_text = trim($data['story_text'] ?? '');
+ $style = trim($data['style'] ?? '');
+ $target_duration = filter_var($data['target_duration'] ?? null, FILTER_VALIDATE_INT, ['options' => ['default' => 0]]);
+
+ if (empty($title)) {
+ http_response_code(400);
+ echo json_encode(['error' => 'Title is required.']);
+ exit;
+ }
+
+ // Update the project
+ $stmt = $pdo->prepare("UPDATE projects SET title = ?, story_text = ?, style = ?, target_duration = ? WHERE id = ?");
+ $stmt->execute([$title, $story_text, $style, $target_duration, $project_id]);
+
+ // Fetch and return the updated project
+ $stmt = $pdo->prepare("SELECT * FROM projects WHERE id = ?");
+ $stmt->execute([$project_id]);
+ $updated_project = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ echo json_encode($updated_project);
+
+} catch (PDOException $e) {
+ http_response_code(500);
+ // error_log("Database error: " . $e->getMessage());
+ echo json_encode(['error' => 'Database error.']);
+}
\ No newline at end of file
diff --git a/edit_scene.php b/edit_scene.php
new file mode 100644
index 0000000..bef2c66
--- /dev/null
+++ b/edit_scene.php
@@ -0,0 +1,87 @@
+ 'User not authenticated']);
+ exit;
+}
+
+require_once 'db/config.php';
+
+// The scene ID must be passed as a URL parameter
+$scene_id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
+if (!$scene_id) {
+ http_response_code(400);
+ echo json_encode(['error' => 'Scene ID is required.']);
+ exit;
+}
+
+if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
+ http_response_code(405); // Method Not Allowed
+ echo json_encode(['error' => 'POST method required.']);
+ exit;
+}
+
+$request_body = file_get_contents('php://input');
+$data = json_decode($request_body, true);
+if (json_last_error() !== JSON_ERROR_NONE) {
+ http_response_code(400);
+ echo json_encode(['error' => 'Invalid JSON input.']);
+ exit;
+}
+
+try {
+ $pdo = db();
+
+ // Fetch scene and project status to verify ownership and draft status
+ $stmt = $pdo->prepare("
+ SELECT s.project_id, p.status as project_status
+ FROM scenes s
+ JOIN projects p ON s.project_id = p.id
+ WHERE s.id = ? AND s.user_id = ?
+ ");
+ $stmt->execute([$scene_id, $_SESSION['user_id']]);
+ $scene_check = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (!$scene_check) {
+ http_response_code(404);
+ echo json_encode(['error' => 'Scene not found or permission denied.']);
+ exit;
+ }
+
+ if ($scene_check['project_status'] !== 'draft') {
+ http_response_code(403);
+ echo json_encode(['error' => 'Project is not in draft status; scene cannot be edited.']);
+ exit;
+ }
+
+ // Get new data from request body
+ $description = trim($data['description'] ?? '');
+ $duration = filter_var($data['duration'] ?? null, FILTER_VALIDATE_INT);
+ $shot_type = trim($data['shot_type'] ?? '');
+
+ // Basic validation
+ if (empty($description) || !$duration || empty($shot_type)) {
+ http_response_code(400);
+ echo json_encode(['error' => 'Invalid input. All fields are required: description, duration, shot_type']);
+ exit;
+ }
+
+ // Update the scene
+ $stmt = $pdo->prepare("UPDATE scenes SET description = ?, duration = ?, shot_type = ? WHERE id = ?");
+ $stmt->execute([$description, $duration, $shot_type, $scene_id]);
+
+ // Fetch and return the updated scene
+ $stmt = $pdo->prepare("SELECT * FROM scenes WHERE id = ?");
+ $stmt->execute([$scene_id]);
+ $updated_scene = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ echo json_encode($updated_scene);
+
+} catch (PDOException $e) {
+ http_response_code(500);
+ // error_log("Database error: " . $e->getMessage());
+ echo json_encode(['error' => 'Database error.']);
+}
\ No newline at end of file
diff --git a/index.php b/index.php
index 7205f3d..c824f5c 100644
--- a/index.php
+++ b/index.php
@@ -1,150 +1,68 @@
-
+
-
-
- New Style
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ Welcome to AI Cinema Engine
+
+
+
-
-
-
Analyzing your requirements and generating your website…
-
- Loading…
-
-
= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.
-
This page will update automatically as the plan is implemented.
-
Runtime: PHP = htmlspecialchars($phpVersion) ?> — UTC = htmlspecialchars($now) ?>
+
+
+
+
AI Cinema Engine
+
= htmlspecialchars($projectDescription) ?>
+
Get Started
+
Login
-
-
+
+
+
+
+
+
Feature 1
+
Describe a core feature of your service here.
+
+
+
Feature 2
+
Describe another great benefit of using your application.
+
+
+
Feature 3
+
Highlight a unique selling proposition or technology.
+
+
+
+
+
+
+
-
+