-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Javid Momeni
committed
Dec 7, 2024
1 parent
af6902c
commit 3ceb69a
Showing
29 changed files
with
1,137 additions
and
1,118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { fetchStories } from '@/lib/api'; | ||
import { StoryDetail } from '@/components/library/story-detail'; | ||
import { notFound } from 'next/navigation'; | ||
|
||
export async function generateStaticParams() { | ||
const stories = await fetchStories(); | ||
return stories.map((story) => ({ | ||
id: story.id, | ||
})); | ||
} | ||
|
||
export default async function StoryPage({ params }: { params: { id: string } }) { | ||
const stories = await fetchStories(); | ||
const story = stories.find((s) => s.id === params.id); | ||
|
||
if (!story) { | ||
notFound(); | ||
} | ||
|
||
return <StoryDetail story={story} />; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
import { fetchStories } from '@/lib/api'; | ||
import { StoryLibrary } from '@/components/library/story-library'; | ||
|
||
export default function LibraryPage() { | ||
return <StoryLibrary />; | ||
export default async function LibraryPage() { | ||
const stories = await fetchStories(); | ||
|
||
return <StoryLibrary initialStories={stories} />; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,239 +1,48 @@ | ||
"use client"; | ||
|
||
import { useState } from "react"; | ||
import { Button } from "@/components/ui/button"; | ||
import { Card, CardHeader, CardTitle } from "@/components/ui/card"; | ||
import { Input } from "@/components/ui/input"; | ||
import { Label } from "@/components/ui/label"; | ||
import { Textarea } from "@/components/ui/textarea"; | ||
import { Slider } from "@/components/ui/slider"; | ||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; | ||
import { StoryForm } from "@/lib/types"; | ||
import { StoryPreview } from "@/components/create/story-preview"; | ||
|
||
const environmentalTopicsMap: Record<string, string> = { | ||
"حفاظت از حیوانات": "Animal Protection", | ||
"کاهش زباله": "Waste Reduction", | ||
"صرفهجویی در آب": "Water Conservation", | ||
"حفاظت از درختان": "Tree Preservation", | ||
"کاهش آلودگی هوا": "Air Pollution Reduction", | ||
}; | ||
|
||
const livingEnvironmentsMap: Record<string, string> = { | ||
شهر: "City", | ||
روستا: "Village", | ||
"حومه شهر": "Suburbs", | ||
ساحل: "Coast", | ||
کوهستان: "Mountainous Area", | ||
}; | ||
|
||
const transformFormData = (formData: StoryForm) => { | ||
return { | ||
title: formData.title, | ||
sex: formData.sex, | ||
ageRange: formData.ageRange[0], | ||
theme: formData.theme, | ||
characters: formData.characters, | ||
additionalNotes: formData.additionalNotes, | ||
environmentalTopic: | ||
environmentalTopicsMap[formData.environmentalTopic] || "", | ||
livingEnvironment: livingEnvironmentsMap[formData.livingEnvironment] || "", | ||
}; | ||
}; | ||
import { useState } from 'react'; | ||
import { Button } from '@/components/ui/button'; | ||
import { Card } from '@/components/ui/card'; | ||
import { StoryForm } from '@/lib/types'; | ||
import { StoryPreview } from '@/components/create/story-preview'; | ||
import { StoryFormFields } from '@/components/create/story-form-fields'; | ||
|
||
export function StoryCreator() { | ||
const [apiResponse, setApiResponse] = useState<{ | ||
aiResponse: string; | ||
approach: string[]; | ||
git: string | null; | ||
success: boolean; | ||
} | null>(null); | ||
const [showPreview, setShowPreview] = useState(true); | ||
|
||
const [form, setForm] = useState<StoryForm>({ | ||
title: "", | ||
sex: "male", | ||
title: '', | ||
ageRange: [6], | ||
theme: "", | ||
characters: "", | ||
additionalNotes: "", | ||
environmentalTopic: "", | ||
livingEnvironment: "", | ||
theme: '', | ||
characters: '', | ||
additionalNotes: '', | ||
childGender: 'boy', | ||
academicApproaches: [], | ||
topic: '', | ||
livingArea: '', | ||
}); | ||
const [isGenerating, setIsGenerating] = useState(false); | ||
const [response, setResponse] = useState<string | null>(null); | ||
|
||
const handleInputChange = ( | ||
field: keyof StoryForm, | ||
value: string | number[] | string | ||
) => { | ||
setForm((prevForm) => ({ | ||
...prevForm, | ||
[field]: value, | ||
})); | ||
}; | ||
const [isGenerating, setIsGenerating] = useState(false); | ||
|
||
const handleSubmit = async (e: React.FormEvent) => { | ||
e.preventDefault(); | ||
const transformedValues = transformFormData(form); | ||
setIsGenerating(true); | ||
|
||
try { | ||
const response = await fetch( | ||
"https://aibots.kharcoin.info/ai-story/build", | ||
{ | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify(transformedValues), | ||
} | ||
); | ||
|
||
const data = await response.json(); | ||
setApiResponse(data); | ||
setShowPreview(false); | ||
setResponse(data); | ||
setForm({ | ||
title: "", | ||
sex: "male", | ||
ageRange: [6], | ||
theme: "", | ||
characters: "", | ||
additionalNotes: "", | ||
environmentalTopic: "", | ||
livingEnvironment: "", | ||
}); | ||
console.log(data); | ||
} catch (error) { | ||
console.error("Error:", error); | ||
setResponse("متاسفانه در ارسال فرم خطایی رخ داد"); | ||
} finally { | ||
setIsGenerating(false); | ||
} | ||
// TODO: Implement story generation logic | ||
setTimeout(() => setIsGenerating(false), 2000); | ||
}; | ||
|
||
return ( | ||
<div className="container mx-auto px-4 py-8"> | ||
<h1 className="mb-8 text-3xl font-bold">قصهتان را بسازید</h1> | ||
<h1 className="mb-8 text-3xl font-bold">Create Your Story</h1> | ||
<div className="grid gap-8 md:grid-cols-2"> | ||
<Card className="p-6"> | ||
<form onSubmit={handleSubmit} className="space-y-6"> | ||
<div className="space-y-2"> | ||
<Label htmlFor="title">قصه</Label> | ||
<Input | ||
id="title" | ||
value={form.title} | ||
onChange={(e) => handleInputChange("title", e.target.value)} | ||
placeholder="قصه شما چه اسمی داشته باشد؟" | ||
/> | ||
</div> | ||
<div className="space-y-2"> | ||
<Label htmlFor="characters">شخصیت اصلی</Label> | ||
<Input | ||
id="characters" | ||
value={form.characters} | ||
onChange={(e) => | ||
handleInputChange("characters", e.target.value) | ||
} | ||
placeholder="Describe your characters" | ||
/> | ||
</div> | ||
<div className="space-y-2"> | ||
<RadioGroup | ||
label="جنسیت" | ||
value={form.sex} | ||
onValueChange={(value) => handleInputChange("sex", value)} | ||
> | ||
<RadioGroupItem value="male">پسر</RadioGroupItem> | ||
<RadioGroupItem value="female">دختر</RadioGroupItem> | ||
</RadioGroup> | ||
</div> | ||
|
||
<div className="space-y-2"> | ||
<Label htmlFor="age-range">سن: {form.ageRange[0]} ساله</Label> | ||
<Slider | ||
id="age-range" | ||
value={form.ageRange} | ||
onValueChange={(value) => handleInputChange("ageRange", value)} | ||
min={3} | ||
max={11} | ||
step={1} | ||
/> | ||
</div> | ||
<div className="grid grid-cols-2 gap-4"> | ||
<div className="space-y-2"> | ||
<Label htmlFor="environmental-topic">موضوع زیست محیطی</Label> | ||
<select | ||
id="environmental-topic" | ||
value={form.environmentalTopic} | ||
onChange={(e) => | ||
handleInputChange("environmentalTopic", e.target.value) | ||
} | ||
className="rounded-md border border-gray-300 px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500" | ||
> | ||
<option value="">انتخاب کنید</option> | ||
{Object.keys(environmentalTopicsMap).map((topic) => ( | ||
<option key={topic} value={topic}> | ||
{topic} | ||
</option> | ||
))} | ||
</select> | ||
</div> | ||
<div className="space-y-2"> | ||
<Label htmlFor="living-environment">محیط زندگی</Label> | ||
<select | ||
id="living-environment" | ||
value={form.livingEnvironment} | ||
onChange={(e) => | ||
handleInputChange("livingEnvironment", e.target.value) | ||
} | ||
className="rounded-md border border-gray-300 px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500" | ||
> | ||
<option value="">انتخاب کنید</option> | ||
{Object.keys(livingEnvironmentsMap).map((environment) => ( | ||
<option key={environment} value={environment}> | ||
{environment} | ||
</option> | ||
))} | ||
</select> | ||
</div> | ||
</div> | ||
|
||
<div className="space-y-2"> | ||
<Label htmlFor="additional-notes">نکات تکمیلی</Label> | ||
<Textarea | ||
id="additional-notes" | ||
value={form.additionalNotes} | ||
onChange={(e) => | ||
handleInputChange("additionalNotes", e.target.value) | ||
} | ||
placeholder="Any special requests or additional details" | ||
/> | ||
</div> | ||
<Button type="submit" className="w-full" disabled={isGenerating}> | ||
{isGenerating ? "در حال ارسال..." : "شروع به قصه گویی"} | ||
<form onSubmit={handleSubmit}> | ||
<StoryFormFields form={form} setForm={setForm} /> | ||
<Button type="submit" className="w-full mt-6" disabled={isGenerating}> | ||
{isGenerating ? 'Creating Story...' : 'Generate Story'} | ||
</Button> | ||
</form> | ||
</Card> | ||
{showPreview ? ( | ||
<StoryPreview | ||
form={form} | ||
environmentalTopicsMap={environmentalTopicsMap} | ||
livingEnvironmentsMap={livingEnvironmentsMap} | ||
/> | ||
) : ( | ||
<Card className="p-6"> | ||
<CardHeader> | ||
</CardHeader> | ||
{apiResponse && apiResponse.aiResponse ? ( | ||
<div className="space-y-4">{apiResponse.aiResponse}</div> | ||
) : ( | ||
<div className="space-y-4">No response available</div> | ||
)} | ||
</Card> | ||
)} | ||
</div> | ||
<StoryPreview form={form} /> | ||
</div> | ||
</div> | ||
); | ||
} | ||
} |
Oops, something went wrong.