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… -
-

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
-
- + + +
+
+
+

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.

+
+
+
+ + + + - + \ 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