From 39839fb76f5f2b841de41914839d8127dfe317b9 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Thu, 1 Jan 2026 15:13:16 +0000 Subject: [PATCH] mstg --- add_scene.php | 71 ++++++++ assets/css/custom.css | 39 ++++ assets/pasted-20260101-095324-285a9cb6.png | Bin 0 -> 37183 bytes assets/pasted-20260101-095442-40a3627d.png | Bin 0 -> 14268 bytes create_project.php | 52 ++++++ db/migrate.php | 58 ++++++ delete_project.php | 68 +++++++ delete_scene.php | 66 +++++++ edit_project.php | 81 +++++++++ edit_scene.php | 87 +++++++++ index.php | 200 ++++++--------------- login.php | 93 ++++++++++ logout.php | 6 + register.php | 114 ++++++++++++ view_project.php | 40 +++++ 15 files changed, 834 insertions(+), 141 deletions(-) create mode 100644 add_scene.php create mode 100644 assets/css/custom.css create mode 100644 assets/pasted-20260101-095324-285a9cb6.png create mode 100644 assets/pasted-20260101-095442-40a3627d.png create mode 100644 create_project.php create mode 100644 db/migrate.php create mode 100644 delete_project.php create mode 100644 delete_scene.php create mode 100644 edit_project.php create mode 100644 edit_scene.php create mode 100644 login.php create mode 100644 logout.php create mode 100644 register.php create mode 100644 view_project.php 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 0000000000000000000000000000000000000000..89f6df1b2ed5366ec318e01e237de3a941b9c1aa GIT binary patch literal 37183 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 i4g9kP&X0uYvDBYwL5;Qs*B '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… -
-

AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

+ +
+
+

AI Cinema Engine

+

+ Get Started + Login
-
-
- Page updated: (UTC) -
+ + +
+
+
+

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.

+
+
+
+ +
+

© AI Cinema Engine. All Rights Reserved.

+
+ + - + \ No newline at end of file diff --git a/login.php b/login.php new file mode 100644 index 0000000..e74f3f3 --- /dev/null +++ b/login.php @@ -0,0 +1,93 @@ +prepare('SELECT * FROM users WHERE email = ?'); + $stmt->execute([$email]); + $user = $stmt->fetch(); + + if ($user && password_verify($password, $user['password'])) { + $_SESSION['user_id'] = $user['id']; + $_SESSION['user_email'] = $user['email']; + header('Location: dashboard.php'); + exit; + } else { + $errors[] = 'Invalid email or password.'; + } + } catch (PDOException $e) { + $errors[] = "Database error: " . $e->getMessage(); + } + } +} +?> + + + + + + Login - AI Cinema Engine + + + + + +
+
+
+
+
+

Login

+
+
+ +
+ +

+ +
+ +
+
+ + +
+
+ + +
+ +
+
+ +
+
+
+
+ + + + diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..7e7a48f --- /dev/null +++ b/logout.php @@ -0,0 +1,6 @@ +prepare('SELECT id FROM users WHERE email = ?'); + $stmt->execute([$email]); + if ($stmt->fetch()) { + $errors[] = 'Email already registered.'; + } else { + $hashed_password = password_hash($password, PASSWORD_DEFAULT); + $stmt = $pdo->prepare('INSERT INTO users (email, password) VALUES (?, ?)'); + if ($stmt->execute([$email, $hashed_password])) { + $success = 'Registration successful! You can now login.'; + } else { + $errors[] = 'Failed to register user. Please try again.'; + } + } + } catch (PDOException $e) { + $errors[] = "Database error: " . $e->getMessage(); + } + } +} +?> + + + + + + Register - AI Cinema Engine + + + + + +
+
+
+
+
+

Register

+
+
+ +
+ +

+ +
+ + +
+

+
+ +
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+ +
+
+
+
+ + + + diff --git a/view_project.php b/view_project.php new file mode 100644 index 0000000..8e47f04 --- /dev/null +++ b/view_project.php @@ -0,0 +1,40 @@ + 'Unauthorized']); + 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' => 'Invalid project ID']); + exit; +} + +$pdo = db(); +$stmt = $pdo->prepare("SELECT * 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']); + exit; +} + +$scene_stmt = $pdo->prepare("SELECT * FROM scenes WHERE project_id = ? ORDER BY scene_number ASC"); +$scene_stmt->execute([$project_id]); +$scenes = $scene_stmt->fetchAll(PDO::FETCH_ASSOC); + +$project['scenes'] = $scenes; + +echo json_encode($project); +exit; +?> \ No newline at end of file