by Guest » 20 Jan 2025, 17:43
Ich versuche, einige Daten, die ich aus der Datenbank abgerufen habe, in der Benutzeroberfläche anzuzeigen. Allerdings wird nur ein Teil der zurückgegebenen Daten angezeigt, obwohl Routenhandler so eingerichtet sind, dass sie alle gespeicherten Daten zurückgeben.
Das unten ist eine Kopie meines route.js-Codes:
Code: Select all
import { NextResponse } from 'next/server';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export async function POST(req) {
let script = null;
let user = null;
try {
const body = await req.json();
script = body.script;
user = body.user;
// Validate input
if (!script || !user) {
throw new Error("Invalid request payload: 'script' and 'user' are required.");
}
if (!script.id) {
throw new Error("Script ID is required.");
}
if (!Array.isArray(script.scenes)) {
throw new Error("Scenes must be an array.");
}
const appwriteId = user?.$id;
if (!appwriteId) {
throw new Error("User ID is required.");
}
// Ensure the user exists in the database
const foundUser = await prisma.user.upsert({
where: { appwriteId },
update: {},
create: {
appwriteId,
email: user.email,
name: user.name,
},
});
// Upsert the script
const savedScript = await prisma.script.upsert({
where: { id: script.id },
update: {
title: script.title || '',
type: script.type || 'feature',
genre: script.genre || '',
},
create: {
title: script.title || '',
type: script.type || 'feature',
genre: script.genre || '',
userId: foundUser.id,
},
});
if (!savedScript || !savedScript.id) {
throw new Error('Failed to upsert script.');
}
// Delete related entities before deleting scenes
const existingSceneIds = (
await prisma.scene.findMany({
where: { scriptId: savedScript.id },
select: { id: true },
})
).map((scene) => scene.id);
if (existingSceneIds.length > 0) {
// Delete lines related to sceneCharacters
await prisma.line.deleteMany({
where: { sceneCharacter: { sceneId: { in: existingSceneIds } } },
});
// Delete sceneCharacters related to scenes
await prisma.sceneCharacter.deleteMany({
where: { sceneId: { in: existingSceneIds } },
});
// Delete the scenes themselves
await prisma.scene.deleteMany({
where: { id: { in: existingSceneIds } },
});
}
// Recreate scenes
const scenesWithScriptId = script.scenes.map((scene, index) => ({
title: scene.title || '',
location: scene.location || '',
description: scene.description || '',
shot: scene.shot || '',
order: index,
scriptId: savedScript.id,
}));
if (scenesWithScriptId.length > 0) {
await prisma.scene.createMany({
data: scenesWithScriptId,
});
}
// Fetch the saved script with ordered scenes
const fetchedScript = await prisma.script.findUnique({
where: { id: savedScript.id },
include: {
scenes: {
orderBy: { order: 'asc' },
},
},
});
return NextResponse.json(fetchedScript);
} catch (error) {
console.error('Error while saving script:', {
message: error.message,
stack: error.stack,
script,
user,
});
return NextResponse.json(
{ error: "An error occurred while saving the script." },
{ status: 500 }
);
}
}
export async function GET() {
try {
const scripts = await prisma.script.findMany({
include: {
scenes: {
include: {
sceneCharacters: {
include: {
character: true,
lines: true,
},
},
},
},
},
});
console.log("SCRIPT FROM DB", scripts);
return NextResponse.json(scripts);
} catch (error) {
console.error('Error while fetching scripts:', error.message);
return NextResponse.json(
{ error: "An error occurred while fetching the scripts." },
{ status: 500 }
);
}
}
und das Folgende ist der UI-Code, der die Daten abruft und anzeigt:
Code: Select all
import React, { useState, useEffect } from "react";
import {
Modal,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
} from "@nextui-org/react";
const EditScript = ({
isOpen,
onClose,
editScripts = [],
selectedScriptId,
user,
}) => {
const [editableScript, setEditableScript] = useState(null);
const [isEditing, setIsEditing] = useState(false);
useEffect(() => {
if (!isOpen) return;
const currentScript = editScripts.find(
(script) => script.id === selectedScriptId
);
if (currentScript) {
console.log("Fetched script:", JSON.stringify(currentScript, null, 2));
setEditableScript(currentScript);
} else {
console.error(`Script with ID ${selectedScriptId} not found.`);
}
}, [isOpen, editScripts, selectedScriptId]);
//Saving the data 👇🏾
const saveEdit = async () => {
if (!editableScript || !editableScript.id) {
console.error("No script or ID to save.");
return;
}
try {
const response = await fetch("/api/scripts/editScriptV2", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
script: {
...editableScript,
scenes: editableScript.scenes.map((scene) => ({
id: scene.id || null,
title: scene.title || "",
location: scene.location || "",
description: scene.description || "",
shot: scene.shot || "",
order: scene.order,
})),
},
scriptType: editableScript?.type,
user,
}),
});
if (!response.ok) {
throw new Error(`Failed to save script: ${response.statusText}`);
}
console.log("Script saved successfully:", editableScript);
onClose();
} catch (error) {
console.error("Error saving script:", error);
}
};
const handleSceneChange = (index, field, value) => {
setEditableScript((prev) => ({
...prev,
scenes: prev.scenes.map((scene, i) =>
i === index ? { ...scene, [field]: value } : scene
),
}));
};
const handleDownload = () => {
if (!editableScript) return;
const blob = new Blob([JSON.stringify(editableScript, null, 2)], {
type: "application/json",
});
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = `${editableScript.title || "script"}.json`;
link.click();
URL.revokeObjectURL(url);
};
const renderScenes = () => {
if (!editableScript || !editableScript.scenes) {
return
No scenes available.
;
}
return editableScript.scenes.map((scene, index) => (
{isEditing ? (
handleSceneChange(index, "title", e.target.value)
}
className="border p-1 w-full"
/>
) : (
scene.title || `Scene ${index + 1}`
)}
[b]Location:[/b]{" "}
{isEditing ? (
handleSceneChange(index, "location", e.target.value)
}
className="border p-1 w-full"
/>
) : (
scene.location || "N/A"
)}
[b]Description:[/b]{" "}
{isEditing ? (
handleSceneChange(index, "description", e.target.value)
}
className="border p-1 w-full"
/>
) : (
scene.description || "N/A"
)}
[b]Shot:[/b]{" "}
{isEditing ? (
handleSceneChange(index, "shot", e.target.value)}
className="border p-1 w-full"
/>
) : (
scene.shot || "N/A"
)}
[b]Order:[/b]{" "}
{isEditing ? (
handleSceneChange(index, "order", e.target.value)
}
className="border p-1 w-full"
/>
) : (
scene.order || "N/A"
)}
[h4]Characters & Dialogue:[/h4]
{scene.sceneCharacters && scene.sceneCharacters.length > 0 ? (
scene.sceneCharacters.map((character, charIndex) => (
{isEditing ? (
handleSceneChange(index, "sceneCharacters", [
...scene.sceneCharacters.slice(0, charIndex),
{
...character,
character: {
...character.character,
name: e.target.value,
},
},
...scene.sceneCharacters.slice(charIndex + 1),
])
}
className="border p-1"
/>
) : (
character.character.name?.toUpperCase() ||
"Unnamed Character"
)}
{scene.Dialogue &&
scene.Dialogue.filter(
(dialogue) =>
dialogue.character === character.character.name
).map((dialogue, dialogueIndex) => (
{dialogue.lines.map((line, lineIndex) => (
{isEditing ? (
handleSceneChange(index, "Dialogue", [
...scene.Dialogue.slice(0, dialogueIndex),
{
...dialogue,
lines: dialogue.lines.map((l, li) =>
li === lineIndex
? { ...l, content: e.target.value }
: l
),
},
...scene.Dialogue.slice(dialogueIndex + 1),
])
}
className="border p-1 w-full"
/>
) : (
line.content
)}
))}
))}
))
) : (
No characters or dialogue available.
)}
));
};
const renderSegments = () => {
return (
Video
Audio
{editableScript.scenes?.length > 0 ? (
editableScript.scenes.map((scene, index) => (
{isEditing ? (
handleSceneChange(index, "title", e.target.value)
}
className="border p-1 w-full"
/>
) : (
scene.title
)}
{isEditing ? (
handleSceneChange(index, "description", e.target.value)
}
className="border p-1 w-full"
/>
) : (
scene.description
)}
))
) : (
No scenes available.
)}
);
};
if (!editableScript) {
return (
No Script Selected
Please select a script to edit.
Close
);
}
return (
{editableScript.title || "Edit Script"}
{editableScript.type === "feature" ||
editableScript.type === "series" ? (
renderScenes()
) : editableScript.type === "short" ||
editableScript.type === "commercial" ? (
renderSegments()
) : (
Script type not supported.
)}
Close
Download Script
{isEditing ? (
saveEdit()}
>
Save Changes
setIsEditing(false)}
>
Cancel Changes
) : (
setIsEditing(true)}
disabled={
!["feature", "series", "short", "commercial"].includes(
editableScript?.type
)
}
>
Edit
)}
);
};
export default EditScript;
Zuletzt finden Sie unten eine Kopie meines schema.prisma:
Code: Select all
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
enum MembershipStatus {
Free
Paid
}
enum NumberType {
Voice
SMS
Both
}
enum ContentType {
MOVIE
TRAILER
SHORT
SERIES
}
enum Role {
USER
ADMIN
}
model User {
id String @id @default(uuid())
name String?
email String @unique
appwriteId String @unique
membershipStatus MembershipStatus @default(Free)
stripeCustomerId String? @unique
provider String @default("")
providerId String?
role Role @default(USER)
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
Post Post[]
Profile Profile?
Movie Movie[]
Stream Stream[]
Trailer Trailer[]
Scene Scene[]
Character Character[]
Content Content[]
phoneNumber Number[]
scripts Script[]
}
model Genre {
id Int @id @default(autoincrement())
name String @unique
}
model Content {
id Int @id @default(autoincrement())
title String
url String
genres String
subGenre String?
contentType ContentType
movieId String?
trailerId Int?
scenes Scene[]
user_id String
user User @relation(fields: [user_id], references: [id])
Trailer Trailer?
@@unique([title, url, user_id])
}
model Script {
id Int @id @default(autoincrement())
title String
genre String?
type String?
userId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
scenes Scene[]
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
// @@unique([userId, title])
}
model AdShortScript {
id String @id @default(uuid()) // Primary key is a UUID
title String @unique
hook String
segments Segment[]
callToAction String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Segment {
id String @id @default(uuid()) // Primary key is a UUID
video String
audio String
order Int?
scriptId String
script AdShortScript @relation(fields: [scriptId], references: [id])
}
model Scene {
id Int @id @default(autoincrement())
title String
location String?
description String?
shot String // Required
order Int // Required
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
scriptId Int
script Script @relation(fields: [scriptId], references: [id], onDelete: Cascade)
sceneCharacters SceneCharacter[] @relation("SceneToCharacters")
userId String?
user User? @relation(fields: [userId], references: [id])
Trailer Trailer? @relation(fields: [trailerId], references: [id])
trailerId Int?
Content Content? @relation(fields: [contentId], references: [id])
contentId Int?
Character Character[]
Dialogue Dialogue[]
@@map("scenes")
}
model SceneCharacter {
id Int @id @default(autoincrement())
scene Scene @relation("SceneToCharacters", fields: [sceneId], references: [id], onDelete: Cascade)
sceneId Int
character Character @relation(fields: [characterId], references: [id])
characterId Int
lines Line[]
// @@map("scene_characters")
}
model Line {
id Int @id @default(autoincrement())
content String
sentiment String?
sceneCharacter SceneCharacter @relation(fields: [sceneCharacterId], references: [id])
sceneCharacterId Int
Character Character? @relation(fields: [characterId], references: [id])
characterId Int?
Dialogue Dialogue? @relation(fields: [dialogueId], references: [id])
dialogueId Int?
// @@map("lines")
}
model Character {
id Int @id @default(autoincrement())
name String?
description String?
attributes String?
url String?
characterRefImage String?
emotionalImpact String?
scenes SceneCharacter[]
lines Line[]
user User? @relation(fields: [userId], references: [id])
userId String?
Scene Scene? @relation(fields: [sceneId], references: [id])
sceneId Int?
@@unique([name, userId])
}
model Dialogue {
id Int @id @default(autoincrement())
sceneId Int
scene Scene @relation(fields: [sceneId], references: [id])
character String
lines Line[]
order Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Category {
id Int @id @default(autoincrement())
name String
streams Stream[]
}
model Stamp {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Das erwartete Verhalten besteht darin, die Daten anzuzeigen, genauer gesagt die Szenen einschließlich der Zeichen und Zeilen. Bitte helfen Sie herauszufinden, warum die Zeichen und Zeilen nicht wie erwartet angezeigt werden. Hier ist eine Kopie der Antwort, als der Code ausgeführt wurde:
Code: Select all
[
{
"id": 130,
"title": "ENCHANTED REALM\n\n By\n\n Screenplay Author",
"genre": "Screenplay Author",
"type": "feature",
"userId": "5fa953db-9875-4b14-bd23-8d24c6cc6a99",
"createdAt": "2025-01-20T03:08:49.097Z",
"updatedAt": "2025-01-20T16:11:38.767Z",
"scenes": [
{
"id": 659,
"title": "INT. MYSTIC SHOP - DAY",
"location": "INT. MYSTIC SHOP - DAY",
"description": "The room is filled with strange and exotic items, shelves upon shelves of magical artifacts and dusty tomes. We see ESON, a young woman in her early twenties, with a curious expression, browsing through the shelves. She is being helped by the shop owner, ZEPSOR, an eccentric old man with a wild look in his eye.",
"shot": "The room is filled with strange and exotic items, shelves upon shelves of magical artifacts and dusty tomes. We see EMILY WILSON, a young woman in her early twenties, with a curious expression, browsing through the shelves. She is being helped by the shop owner, ZEPHYR WINDSOR, an eccentric old man with a wild look in his eye. ",
"order": 0,
"createdAt": "2025-01-20T16:11:39.287Z",
"updatedAt": "2025-01-20T16:11:39.287Z",
"scriptId": 130,
"userId": null,
"trailerId": null,
"contentId": null,
"sceneCharacters": []
},
{
"id": 660,
"title": "EXT. MYSOP - DAY",
"location": "EXT. MYSTIC SHOP - DAY",
"description": "The camera pans out, showing the small town of Willowdale. The streets are lined with old buildings, and the air is filled with the smell of magic. We see EMILY and ZEPHYR standing outside the shop, looking up at the sky.",
"shot": "The camera pans out, showing the small town of Willowdale. The streets are lined with old buildings, and the air is filled with the smell of magic. We see EMILY and ZEPHYR standing outside the shop, looking up at the sky. ",
"order": 1,
"createdAt": "2025-01-20T16:11:39.287Z",
"updatedAt": "2025-01-20T16:11:39.287Z",
"scriptId": 130,
"userId": null,
"trailerId": null,
"contentId": null,
"sceneCharacters": []
},
{
"id": 661,
"title": "INT. TOWN HALL - NIGHT",
"location": "INT. TOWN HALL - NIGHT",
"description": "The room is filled with townspeople, all gathered to discuss the strange occurrences that have been happening in Willowdale. We see EY and ZEYR standing at the front of the room, facing the crowd. ",
"shot": "The room is filled with townspeople, all gathered to discuss the strange occurrences that have been happening in Willowdale. We see EMILY and ZEPHYR standing at the front of the room, facing the crowd. ",
"order": 2,
"createdAt": "2025-01-20T16:11:39.287Z",
"updatedAt": "2025-01-20T16:11:39.287Z",
"scriptId": 130,
"userId": null,
"trailerId": null,
"contentId": null,
"sceneCharacters": []
}
]
}
]
Ich versuche, einige Daten, die ich aus der Datenbank abgerufen habe, in der Benutzeroberfläche anzuzeigen. Allerdings wird nur ein Teil der zurückgegebenen Daten angezeigt, obwohl Routenhandler so eingerichtet sind, dass sie alle gespeicherten Daten zurückgeben.
Das unten ist eine Kopie meines route.js-Codes:
[code]import { NextResponse } from 'next/server';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export async function POST(req) {
let script = null;
let user = null;
try {
const body = await req.json();
script = body.script;
user = body.user;
// Validate input
if (!script || !user) {
throw new Error("Invalid request payload: 'script' and 'user' are required.");
}
if (!script.id) {
throw new Error("Script ID is required.");
}
if (!Array.isArray(script.scenes)) {
throw new Error("Scenes must be an array.");
}
const appwriteId = user?.$id;
if (!appwriteId) {
throw new Error("User ID is required.");
}
// Ensure the user exists in the database
const foundUser = await prisma.user.upsert({
where: { appwriteId },
update: {},
create: {
appwriteId,
email: user.email,
name: user.name,
},
});
// Upsert the script
const savedScript = await prisma.script.upsert({
where: { id: script.id },
update: {
title: script.title || '',
type: script.type || 'feature',
genre: script.genre || '',
},
create: {
title: script.title || '',
type: script.type || 'feature',
genre: script.genre || '',
userId: foundUser.id,
},
});
if (!savedScript || !savedScript.id) {
throw new Error('Failed to upsert script.');
}
// Delete related entities before deleting scenes
const existingSceneIds = (
await prisma.scene.findMany({
where: { scriptId: savedScript.id },
select: { id: true },
})
).map((scene) => scene.id);
if (existingSceneIds.length > 0) {
// Delete lines related to sceneCharacters
await prisma.line.deleteMany({
where: { sceneCharacter: { sceneId: { in: existingSceneIds } } },
});
// Delete sceneCharacters related to scenes
await prisma.sceneCharacter.deleteMany({
where: { sceneId: { in: existingSceneIds } },
});
// Delete the scenes themselves
await prisma.scene.deleteMany({
where: { id: { in: existingSceneIds } },
});
}
// Recreate scenes
const scenesWithScriptId = script.scenes.map((scene, index) => ({
title: scene.title || '',
location: scene.location || '',
description: scene.description || '',
shot: scene.shot || '',
order: index,
scriptId: savedScript.id,
}));
if (scenesWithScriptId.length > 0) {
await prisma.scene.createMany({
data: scenesWithScriptId,
});
}
// Fetch the saved script with ordered scenes
const fetchedScript = await prisma.script.findUnique({
where: { id: savedScript.id },
include: {
scenes: {
orderBy: { order: 'asc' },
},
},
});
return NextResponse.json(fetchedScript);
} catch (error) {
console.error('Error while saving script:', {
message: error.message,
stack: error.stack,
script,
user,
});
return NextResponse.json(
{ error: "An error occurred while saving the script." },
{ status: 500 }
);
}
}
export async function GET() {
try {
const scripts = await prisma.script.findMany({
include: {
scenes: {
include: {
sceneCharacters: {
include: {
character: true,
lines: true,
},
},
},
},
},
});
console.log("SCRIPT FROM DB", scripts);
return NextResponse.json(scripts);
} catch (error) {
console.error('Error while fetching scripts:', error.message);
return NextResponse.json(
{ error: "An error occurred while fetching the scripts." },
{ status: 500 }
);
}
}
[/code]
und das Folgende ist der UI-Code, der die Daten abruft und anzeigt:
[code]import React, { useState, useEffect } from "react";
import {
Modal,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
} from "@nextui-org/react";
const EditScript = ({
isOpen,
onClose,
editScripts = [],
selectedScriptId,
user,
}) => {
const [editableScript, setEditableScript] = useState(null);
const [isEditing, setIsEditing] = useState(false);
useEffect(() => {
if (!isOpen) return;
const currentScript = editScripts.find(
(script) => script.id === selectedScriptId
);
if (currentScript) {
console.log("Fetched script:", JSON.stringify(currentScript, null, 2));
setEditableScript(currentScript);
} else {
console.error(`Script with ID ${selectedScriptId} not found.`);
}
}, [isOpen, editScripts, selectedScriptId]);
//Saving the data 👇🏾
const saveEdit = async () => {
if (!editableScript || !editableScript.id) {
console.error("No script or ID to save.");
return;
}
try {
const response = await fetch("/api/scripts/editScriptV2", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
script: {
...editableScript,
scenes: editableScript.scenes.map((scene) => ({
id: scene.id || null,
title: scene.title || "",
location: scene.location || "",
description: scene.description || "",
shot: scene.shot || "",
order: scene.order,
})),
},
scriptType: editableScript?.type,
user,
}),
});
if (!response.ok) {
throw new Error(`Failed to save script: ${response.statusText}`);
}
console.log("Script saved successfully:", editableScript);
onClose();
} catch (error) {
console.error("Error saving script:", error);
}
};
const handleSceneChange = (index, field, value) => {
setEditableScript((prev) => ({
...prev,
scenes: prev.scenes.map((scene, i) =>
i === index ? { ...scene, [field]: value } : scene
),
}));
};
const handleDownload = () => {
if (!editableScript) return;
const blob = new Blob([JSON.stringify(editableScript, null, 2)], {
type: "application/json",
});
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = `${editableScript.title || "script"}.json`;
link.click();
URL.revokeObjectURL(url);
};
const renderScenes = () => {
if (!editableScript || !editableScript.scenes) {
return
No scenes available.
;
}
return editableScript.scenes.map((scene, index) => (
{isEditing ? (
handleSceneChange(index, "title", e.target.value)
}
className="border p-1 w-full"
/>
) : (
scene.title || `Scene ${index + 1}`
)}
[b]Location:[/b]{" "}
{isEditing ? (
handleSceneChange(index, "location", e.target.value)
}
className="border p-1 w-full"
/>
) : (
scene.location || "N/A"
)}
[b]Description:[/b]{" "}
{isEditing ? (
handleSceneChange(index, "description", e.target.value)
}
className="border p-1 w-full"
/>
) : (
scene.description || "N/A"
)}
[b]Shot:[/b]{" "}
{isEditing ? (
handleSceneChange(index, "shot", e.target.value)}
className="border p-1 w-full"
/>
) : (
scene.shot || "N/A"
)}
[b]Order:[/b]{" "}
{isEditing ? (
handleSceneChange(index, "order", e.target.value)
}
className="border p-1 w-full"
/>
) : (
scene.order || "N/A"
)}
[h4]Characters & Dialogue:[/h4]
{scene.sceneCharacters && scene.sceneCharacters.length > 0 ? (
scene.sceneCharacters.map((character, charIndex) => (
{isEditing ? (
handleSceneChange(index, "sceneCharacters", [
...scene.sceneCharacters.slice(0, charIndex),
{
...character,
character: {
...character.character,
name: e.target.value,
},
},
...scene.sceneCharacters.slice(charIndex + 1),
])
}
className="border p-1"
/>
) : (
character.character.name?.toUpperCase() ||
"Unnamed Character"
)}
{scene.Dialogue &&
scene.Dialogue.filter(
(dialogue) =>
dialogue.character === character.character.name
).map((dialogue, dialogueIndex) => (
{dialogue.lines.map((line, lineIndex) => (
{isEditing ? (
handleSceneChange(index, "Dialogue", [
...scene.Dialogue.slice(0, dialogueIndex),
{
...dialogue,
lines: dialogue.lines.map((l, li) =>
li === lineIndex
? { ...l, content: e.target.value }
: l
),
},
...scene.Dialogue.slice(dialogueIndex + 1),
])
}
className="border p-1 w-full"
/>
) : (
line.content
)}
))}
))}
))
) : (
No characters or dialogue available.
)}
));
};
const renderSegments = () => {
return (
Video
Audio
{editableScript.scenes?.length > 0 ? (
editableScript.scenes.map((scene, index) => (
{isEditing ? (
handleSceneChange(index, "title", e.target.value)
}
className="border p-1 w-full"
/>
) : (
scene.title
)}
{isEditing ? (
handleSceneChange(index, "description", e.target.value)
}
className="border p-1 w-full"
/>
) : (
scene.description
)}
))
) : (
No scenes available.
)}
);
};
if (!editableScript) {
return (
No Script Selected
Please select a script to edit.
Close
);
}
return (
{editableScript.title || "Edit Script"}
{editableScript.type === "feature" ||
editableScript.type === "series" ? (
renderScenes()
) : editableScript.type === "short" ||
editableScript.type === "commercial" ? (
renderSegments()
) : (
Script type not supported.
)}
Close
Download Script
{isEditing ? (
saveEdit()}
>
Save Changes
setIsEditing(false)}
>
Cancel Changes
) : (
setIsEditing(true)}
disabled={
!["feature", "series", "short", "commercial"].includes(
editableScript?.type
)
}
>
Edit
)}
);
};
export default EditScript;
[/code]
Zuletzt finden Sie unten eine Kopie meines schema.prisma:
[code]generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
enum MembershipStatus {
Free
Paid
}
enum NumberType {
Voice
SMS
Both
}
enum ContentType {
MOVIE
TRAILER
SHORT
SERIES
}
enum Role {
USER
ADMIN
}
model User {
id String @id @default(uuid())
name String?
email String @unique
appwriteId String @unique
membershipStatus MembershipStatus @default(Free)
stripeCustomerId String? @unique
provider String @default("")
providerId String?
role Role @default(USER)
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
Post Post[]
Profile Profile?
Movie Movie[]
Stream Stream[]
Trailer Trailer[]
Scene Scene[]
Character Character[]
Content Content[]
phoneNumber Number[]
scripts Script[]
}
model Genre {
id Int @id @default(autoincrement())
name String @unique
}
model Content {
id Int @id @default(autoincrement())
title String
url String
genres String
subGenre String?
contentType ContentType
movieId String?
trailerId Int?
scenes Scene[]
user_id String
user User @relation(fields: [user_id], references: [id])
Trailer Trailer?
@@unique([title, url, user_id])
}
model Script {
id Int @id @default(autoincrement())
title String
genre String?
type String?
userId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
scenes Scene[]
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
// @@unique([userId, title])
}
model AdShortScript {
id String @id @default(uuid()) // Primary key is a UUID
title String @unique
hook String
segments Segment[]
callToAction String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Segment {
id String @id @default(uuid()) // Primary key is a UUID
video String
audio String
order Int?
scriptId String
script AdShortScript @relation(fields: [scriptId], references: [id])
}
model Scene {
id Int @id @default(autoincrement())
title String
location String?
description String?
shot String // Required
order Int // Required
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
scriptId Int
script Script @relation(fields: [scriptId], references: [id], onDelete: Cascade)
sceneCharacters SceneCharacter[] @relation("SceneToCharacters")
userId String?
user User? @relation(fields: [userId], references: [id])
Trailer Trailer? @relation(fields: [trailerId], references: [id])
trailerId Int?
Content Content? @relation(fields: [contentId], references: [id])
contentId Int?
Character Character[]
Dialogue Dialogue[]
@@map("scenes")
}
model SceneCharacter {
id Int @id @default(autoincrement())
scene Scene @relation("SceneToCharacters", fields: [sceneId], references: [id], onDelete: Cascade)
sceneId Int
character Character @relation(fields: [characterId], references: [id])
characterId Int
lines Line[]
// @@map("scene_characters")
}
model Line {
id Int @id @default(autoincrement())
content String
sentiment String?
sceneCharacter SceneCharacter @relation(fields: [sceneCharacterId], references: [id])
sceneCharacterId Int
Character Character? @relation(fields: [characterId], references: [id])
characterId Int?
Dialogue Dialogue? @relation(fields: [dialogueId], references: [id])
dialogueId Int?
// @@map("lines")
}
model Character {
id Int @id @default(autoincrement())
name String?
description String?
attributes String?
url String?
characterRefImage String?
emotionalImpact String?
scenes SceneCharacter[]
lines Line[]
user User? @relation(fields: [userId], references: [id])
userId String?
Scene Scene? @relation(fields: [sceneId], references: [id])
sceneId Int?
@@unique([name, userId])
}
model Dialogue {
id Int @id @default(autoincrement())
sceneId Int
scene Scene @relation(fields: [sceneId], references: [id])
character String
lines Line[]
order Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Category {
id Int @id @default(autoincrement())
name String
streams Stream[]
}
model Stamp {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
[/code]
Das erwartete Verhalten besteht darin, die Daten anzuzeigen, genauer gesagt die Szenen einschließlich der Zeichen und Zeilen. Bitte helfen Sie herauszufinden, warum die Zeichen und Zeilen nicht wie erwartet angezeigt werden. Hier ist eine Kopie der Antwort, als der Code ausgeführt wurde:
[code][
{
"id": 130,
"title": "ENCHANTED REALM\n\n By\n\n Screenplay Author",
"genre": "Screenplay Author",
"type": "feature",
"userId": "5fa953db-9875-4b14-bd23-8d24c6cc6a99",
"createdAt": "2025-01-20T03:08:49.097Z",
"updatedAt": "2025-01-20T16:11:38.767Z",
"scenes": [
{
"id": 659,
"title": "INT. MYSTIC SHOP - DAY",
"location": "INT. MYSTIC SHOP - DAY",
"description": "The room is filled with strange and exotic items, shelves upon shelves of magical artifacts and dusty tomes. We see ESON, a young woman in her early twenties, with a curious expression, browsing through the shelves. She is being helped by the shop owner, ZEPSOR, an eccentric old man with a wild look in his eye.",
"shot": "The room is filled with strange and exotic items, shelves upon shelves of magical artifacts and dusty tomes. We see EMILY WILSON, a young woman in her early twenties, with a curious expression, browsing through the shelves. She is being helped by the shop owner, ZEPHYR WINDSOR, an eccentric old man with a wild look in his eye. ",
"order": 0,
"createdAt": "2025-01-20T16:11:39.287Z",
"updatedAt": "2025-01-20T16:11:39.287Z",
"scriptId": 130,
"userId": null,
"trailerId": null,
"contentId": null,
"sceneCharacters": []
},
{
"id": 660,
"title": "EXT. MYSOP - DAY",
"location": "EXT. MYSTIC SHOP - DAY",
"description": "The camera pans out, showing the small town of Willowdale. The streets are lined with old buildings, and the air is filled with the smell of magic. We see EMILY and ZEPHYR standing outside the shop, looking up at the sky.",
"shot": "The camera pans out, showing the small town of Willowdale. The streets are lined with old buildings, and the air is filled with the smell of magic. We see EMILY and ZEPHYR standing outside the shop, looking up at the sky. ",
"order": 1,
"createdAt": "2025-01-20T16:11:39.287Z",
"updatedAt": "2025-01-20T16:11:39.287Z",
"scriptId": 130,
"userId": null,
"trailerId": null,
"contentId": null,
"sceneCharacters": []
},
{
"id": 661,
"title": "INT. TOWN HALL - NIGHT",
"location": "INT. TOWN HALL - NIGHT",
"description": "The room is filled with townspeople, all gathered to discuss the strange occurrences that have been happening in Willowdale. We see EY and ZEYR standing at the front of the room, facing the crowd. ",
"shot": "The room is filled with townspeople, all gathered to discuss the strange occurrences that have been happening in Willowdale. We see EMILY and ZEPHYR standing at the front of the room, facing the crowd. ",
"order": 2,
"createdAt": "2025-01-20T16:11:39.287Z",
"updatedAt": "2025-01-20T16:11:39.287Z",
"scriptId": 130,
"userId": null,
"trailerId": null,
"contentId": null,
"sceneCharacters": []
}
]
}
]
[/code]