Update app.py
Browse files
app.py
CHANGED
@@ -1226,55 +1226,266 @@ def init_theme_state():
|
|
1226 |
|
1227 |
# Theme Selection UI
|
1228 |
def show_theme_selection():
|
1229 |
-
|
1230 |
-
|
1231 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1232 |
|
|
|
1233 |
st.markdown("""
|
1234 |
<div class="theme-header">
|
1235 |
-
<
|
|
|
1236 |
</div>
|
1237 |
""", unsafe_allow_html=True)
|
1238 |
-
|
1239 |
-
#
|
1240 |
-
available_themes =
|
1241 |
-
|
1242 |
-
|
|
|
|
|
|
|
1243 |
for i in range(0, len(available_themes), 4):
|
1244 |
-
row_themes = available_themes[i:i+4]
|
1245 |
cols = st.columns(4)
|
|
|
1246 |
|
1247 |
for col, theme in zip(cols, row_themes):
|
1248 |
with col:
|
1249 |
-
#
|
1250 |
-
st.
|
1251 |
-
|
1252 |
-
|
1253 |
-
|
1254 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1255 |
|
1256 |
-
# Theme
|
1257 |
if st.button(
|
1258 |
-
f"
|
1259 |
-
key=
|
1260 |
use_container_width=True,
|
|
|
1261 |
):
|
1262 |
-
|
1263 |
-
|
1264 |
-
|
1265 |
-
|
1266 |
-
|
1267 |
-
|
1268 |
-
|
1269 |
-
|
1270 |
-
|
1271 |
-
|
1272 |
-
|
1273 |
-
|
1274 |
-
|
1275 |
-
|
1276 |
-
|
1277 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1278 |
|
1279 |
# Add theme-specific CSS
|
1280 |
def add_theme_css():
|
@@ -1945,12 +2156,16 @@ if st.session_state.should_reset:
|
|
1945 |
reset_story()
|
1946 |
|
1947 |
# Main UI Layout
|
1948 |
-
|
|
|
|
|
1949 |
init_theme_state()
|
1950 |
add_theme_css()
|
|
|
|
|
1951 |
st.markdown("# 📖 JoyStory")
|
1952 |
show_welcome_section()
|
1953 |
-
show_parent_guide()
|
1954 |
|
1955 |
# After showing the welcome section and before the main story area
|
1956 |
if not st.session_state.current_theme:
|
@@ -2011,147 +2226,156 @@ with st.sidebar:
|
|
2011 |
|
2012 |
|
2013 |
# Main content area
|
2014 |
-
|
2015 |
-
|
2016 |
-
|
2017 |
-
|
2018 |
-
|
2019 |
-
|
2020 |
-
<div class="thai">📖 เรื่องราวของคุณ</div>
|
2021 |
-
<div class="eng">Your Story</div>
|
2022 |
-
</div>
|
2023 |
-
""", unsafe_allow_html=True)
|
2024 |
-
|
2025 |
-
# Theme Selection หรือ Change Theme
|
2026 |
-
if not st.session_state.current_theme:
|
2027 |
-
show_theme_selection()
|
2028 |
-
else:
|
2029 |
-
# Show current theme and option to change - เพิ่ม key ให้ปุ่ม
|
2030 |
-
if st.button("🔄 Change Theme", key="change_theme_button"):
|
2031 |
-
st.session_state.current_theme = None
|
2032 |
-
st.session_state.theme_story_starter = None
|
2033 |
-
st.session_state.story = []
|
2034 |
-
st.rerun()
|
2035 |
-
|
2036 |
-
# แสดงเนื้อเรื่อง
|
2037 |
-
show_story()
|
2038 |
|
2039 |
-
|
|
|
2040 |
st.markdown("""
|
2041 |
<div class="thai-eng">
|
2042 |
-
<div class="thai"
|
2043 |
-
<div class="eng">Your
|
2044 |
</div>
|
2045 |
""", unsafe_allow_html=True)
|
2046 |
-
|
2047 |
-
#
|
2048 |
-
st.
|
2049 |
-
|
2050 |
-
|
2051 |
-
key
|
2052 |
-
|
2053 |
-
|
2054 |
-
|
2055 |
-
|
2056 |
-
|
2057 |
-
|
2058 |
-
|
2059 |
-
|
2060 |
-
|
2061 |
-
|
2062 |
-
|
2063 |
<div class="thai-eng">
|
2064 |
-
<div class="thai"
|
2065 |
-
<div class="eng">
|
2066 |
-
</div>
|
2067 |
-
</div>
|
2068 |
-
""", unsafe_allow_html=True)
|
2069 |
-
|
2070 |
-
feedback_data = st.session_state.feedback
|
2071 |
-
if isinstance(feedback_data, dict) and feedback_data.get('has_errors'):
|
2072 |
-
st.markdown(f"""
|
2073 |
-
<div style='background-color: #f0f2f6;
|
2074 |
-
padding: 15px;
|
2075 |
-
border-radius: 8px;
|
2076 |
-
border-left: 4px solid #FF9800;
|
2077 |
-
margin: 5px 0;
|
2078 |
-
font-family: "Sarabun", sans-serif;'>
|
2079 |
-
<p style='color: #1e88e5; margin-bottom: 10px;'>
|
2080 |
-
{feedback_data['feedback']}
|
2081 |
-
</p>
|
2082 |
-
<p style='color: #666; font-size: 0.9em;'>
|
2083 |
-
ประโยคที่ถูกต้อง:<br/>
|
2084 |
-
<span style='color: #4CAF50; font-weight: bold;'>
|
2085 |
-
{feedback_data['corrected']}
|
2086 |
-
</span>
|
2087 |
-
</p>
|
2088 |
</div>
|
2089 |
""", unsafe_allow_html=True)
|
2090 |
|
2091 |
-
#
|
2092 |
-
|
2093 |
-
|
2094 |
-
|
2095 |
-
|
2096 |
-
|
2097 |
-
|
2098 |
-
|
2099 |
-
|
2100 |
-
|
2101 |
-
|
2102 |
-
|
2103 |
-
|
2104 |
-
|
2105 |
-
st.markdown(
|
2106 |
-
<div
|
2107 |
-
|
2108 |
-
|
2109 |
-
|
2110 |
-
|
2111 |
-
font-family: "Sarabun", sans-serif;'>
|
2112 |
-
<p style='color: #1e88e5;'>
|
2113 |
-
{feedback_data.get('feedback', '✨ เขียนได้ถูกต้องแล้วค่ะ!')}
|
2114 |
-
</p>
|
2115 |
-
</div>
|
2116 |
-
""", unsafe_allow_html=True)
|
2117 |
-
|
2118 |
-
# 2. Writing Tools (Expandable)
|
2119 |
-
with st.expander("✨ เครื่องมือช่วยเขียน | Writing Tools"):
|
2120 |
-
if st.button("🎯 ขอคำใบ้"):
|
2121 |
-
prompt = get_creative_prompt()
|
2122 |
-
st.markdown(f"""
|
2123 |
-
<div class="thai-eng">
|
2124 |
-
<div class="thai">💭 {prompt['thai']}</div>
|
2125 |
-
<div class="eng">💭 {prompt['eng']}</div>
|
2126 |
</div>
|
2127 |
""", unsafe_allow_html=True)
|
2128 |
-
|
2129 |
-
|
2130 |
-
|
2131 |
-
|
2132 |
-
|
2133 |
-
|
2134 |
-
|
2135 |
-
|
2136 |
-
|
2137 |
-
|
2138 |
-
|
2139 |
-
|
2140 |
-
|
2141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2142 |
st.markdown("### 💾 บันทึกเรื่องราว")
|
2143 |
-
|
2144 |
-
|
2145 |
-
|
2146 |
-
|
2147 |
-
|
2148 |
-
|
2149 |
-
|
2150 |
-
|
2151 |
-
|
2152 |
-
|
2153 |
-
|
2154 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
2155 |
# Add new CSS for improved layout
|
2156 |
st.markdown("""
|
2157 |
<style>
|
|
|
1226 |
|
1227 |
# Theme Selection UI
|
1228 |
def show_theme_selection():
|
1229 |
+
"""แสดงหน้าเลือกธีมพร้อม animations และ interactive elements"""
|
1230 |
+
|
1231 |
+
# Add custom CSS
|
1232 |
+
st.markdown("""
|
1233 |
+
<style>
|
1234 |
+
/* Custom Fonts */
|
1235 |
+
@import url('https://fonts.googleapis.com/css2?family=Sarabun:wght@400;600&display=swap');
|
1236 |
+
|
1237 |
+
/* Container Styles */
|
1238 |
+
.theme-container {
|
1239 |
+
padding: 2rem 1rem;
|
1240 |
+
max-width: 1200px;
|
1241 |
+
margin: 0 auto;
|
1242 |
+
}
|
1243 |
+
|
1244 |
+
/* Header Styles */
|
1245 |
+
.theme-header {
|
1246 |
+
text-align: center;
|
1247 |
+
margin-bottom: 2.5rem;
|
1248 |
+
}
|
1249 |
+
|
1250 |
+
.theme-header h2 {
|
1251 |
+
color: #1E88E5;
|
1252 |
+
font-family: 'Sarabun', sans-serif;
|
1253 |
+
font-size: 2rem;
|
1254 |
+
font-weight: 600;
|
1255 |
+
margin-bottom: 0.5rem;
|
1256 |
+
}
|
1257 |
+
|
1258 |
+
.theme-header p {
|
1259 |
+
color: #666;
|
1260 |
+
font-size: 1.1rem;
|
1261 |
+
max-width: 600px;
|
1262 |
+
margin: 0 auto;
|
1263 |
+
}
|
1264 |
+
|
1265 |
+
/* Theme Card Animation */
|
1266 |
+
@keyframes float {
|
1267 |
+
0% { transform: translateY(0px); }
|
1268 |
+
50% { transform: translateY(-5px); }
|
1269 |
+
100% { transform: translateY(0px); }
|
1270 |
+
}
|
1271 |
+
|
1272 |
+
/* Theme Card Styles */
|
1273 |
+
.theme-card {
|
1274 |
+
background: white;
|
1275 |
+
border-radius: 15px;
|
1276 |
+
padding: 1.5rem;
|
1277 |
+
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
1278 |
+
transition: all 0.3s ease;
|
1279 |
+
position: relative;
|
1280 |
+
overflow: hidden;
|
1281 |
+
height: 100%;
|
1282 |
+
animation: float 3s ease-in-out infinite;
|
1283 |
+
cursor: pointer;
|
1284 |
+
}
|
1285 |
+
|
1286 |
+
.theme-card:hover {
|
1287 |
+
transform: translateY(-8px);
|
1288 |
+
box-shadow: 0 8px 15px rgba(0,0,0,0.15);
|
1289 |
+
}
|
1290 |
+
|
1291 |
+
.theme-card:hover .theme-hover-content {
|
1292 |
+
opacity: 1;
|
1293 |
+
}
|
1294 |
+
|
1295 |
+
/* Theme Card Content */
|
1296 |
+
.theme-icon {
|
1297 |
+
font-size: 2.5rem;
|
1298 |
+
margin-bottom: 1rem;
|
1299 |
+
display: block;
|
1300 |
+
}
|
1301 |
+
|
1302 |
+
.theme-title {
|
1303 |
+
font-size: 1.2rem;
|
1304 |
+
font-weight: 600;
|
1305 |
+
margin-bottom: 0.5rem;
|
1306 |
+
color: #1E88E5;
|
1307 |
+
font-family: 'Sarabun', sans-serif;
|
1308 |
+
}
|
1309 |
+
|
1310 |
+
.theme-description {
|
1311 |
+
font-size: 0.9rem;
|
1312 |
+
color: #666;
|
1313 |
+
line-height: 1.4;
|
1314 |
+
margin-bottom: 1rem;
|
1315 |
+
}
|
1316 |
+
|
1317 |
+
/* Level Badge */
|
1318 |
+
.level-badge {
|
1319 |
+
position: absolute;
|
1320 |
+
top: 1rem;
|
1321 |
+
right: 1rem;
|
1322 |
+
padding: 0.25rem 0.75rem;
|
1323 |
+
border-radius: 999px;
|
1324 |
+
font-size: 0.8rem;
|
1325 |
+
background: #E3F2FD;
|
1326 |
+
color: #1E88E5;
|
1327 |
+
font-weight: 500;
|
1328 |
+
}
|
1329 |
+
|
1330 |
+
/* Hover Content */
|
1331 |
+
.theme-hover-content {
|
1332 |
+
position: absolute;
|
1333 |
+
bottom: 0;
|
1334 |
+
left: 0;
|
1335 |
+
right: 0;
|
1336 |
+
background: rgba(255,255,255,0.95);
|
1337 |
+
padding: 1rem;
|
1338 |
+
opacity: 0;
|
1339 |
+
transition: opacity 0.3s ease;
|
1340 |
+
}
|
1341 |
+
|
1342 |
+
/* Theme Button */
|
1343 |
+
.theme-button {
|
1344 |
+
width: 100%;
|
1345 |
+
padding: 0.5rem;
|
1346 |
+
background: #1E88E5;
|
1347 |
+
color: white;
|
1348 |
+
border: none;
|
1349 |
+
border-radius: 8px;
|
1350 |
+
font-size: 1rem;
|
1351 |
+
font-weight: 500;
|
1352 |
+
cursor: pointer;
|
1353 |
+
transition: background 0.3s ease;
|
1354 |
+
}
|
1355 |
+
|
1356 |
+
.theme-button:hover {
|
1357 |
+
background: #1565C0;
|
1358 |
+
}
|
1359 |
+
|
1360 |
+
/* Responsive Grid */
|
1361 |
+
.theme-grid {
|
1362 |
+
display: grid;
|
1363 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
1364 |
+
gap: 1.5rem;
|
1365 |
+
padding: 1rem;
|
1366 |
+
}
|
1367 |
+
|
1368 |
+
/* Loading Animation */
|
1369 |
+
@keyframes pulse {
|
1370 |
+
0% { opacity: 0.6; }
|
1371 |
+
50% { opacity: 1; }
|
1372 |
+
100% { opacity: 0.6; }
|
1373 |
+
}
|
1374 |
+
|
1375 |
+
.loading {
|
1376 |
+
animation: pulse 1.5s infinite;
|
1377 |
+
}
|
1378 |
+
|
1379 |
+
/* Tooltip */
|
1380 |
+
.theme-tooltip {
|
1381 |
+
position: relative;
|
1382 |
+
display: inline-block;
|
1383 |
+
}
|
1384 |
+
|
1385 |
+
.theme-tooltip .tooltip-text {
|
1386 |
+
visibility: hidden;
|
1387 |
+
width: 200px;
|
1388 |
+
background-color: #333;
|
1389 |
+
color: white;
|
1390 |
+
text-align: center;
|
1391 |
+
border-radius: 6px;
|
1392 |
+
padding: 5px;
|
1393 |
+
position: absolute;
|
1394 |
+
z-index: 1;
|
1395 |
+
bottom: 125%;
|
1396 |
+
left: 50%;
|
1397 |
+
transform: translateX(-50%);
|
1398 |
+
opacity: 0;
|
1399 |
+
transition: opacity 0.3s;
|
1400 |
+
}
|
1401 |
+
|
1402 |
+
.theme-tooltip:hover .tooltip-text {
|
1403 |
+
visibility: visible;
|
1404 |
+
opacity: 1;
|
1405 |
+
}
|
1406 |
+
</style>
|
1407 |
+
""", unsafe_allow_html=True)
|
1408 |
|
1409 |
+
# Header
|
1410 |
st.markdown("""
|
1411 |
<div class="theme-header">
|
1412 |
+
<h2>🎨 เลือกธีมเรื่องราว | Choose Story Theme</h2>
|
1413 |
+
<p>เลือกโลกแห่งจินตนาการที่คุณต้องการผจญภัย และเริ่มต้นเขียนเรื่องราวของคุณ</p>
|
1414 |
</div>
|
1415 |
""", unsafe_allow_html=True)
|
1416 |
+
|
1417 |
+
# Filter themes based on current level
|
1418 |
+
available_themes = [
|
1419 |
+
theme for theme in story_themes.values()
|
1420 |
+
if st.session_state.level in theme['level_range']
|
1421 |
+
]
|
1422 |
+
|
1423 |
+
# Create rows of 4 themes each
|
1424 |
for i in range(0, len(available_themes), 4):
|
|
|
1425 |
cols = st.columns(4)
|
1426 |
+
row_themes = available_themes[i:i+4]
|
1427 |
|
1428 |
for col, theme in zip(cols, row_themes):
|
1429 |
with col:
|
1430 |
+
# Theme Card Container
|
1431 |
+
st.markdown(f"""
|
1432 |
+
<div class="theme-card" style="background-color: {theme['background_color']}">
|
1433 |
+
<div class="level-badge">{st.session_state.level}</div>
|
1434 |
+
<div class="theme-icon">{theme['icon']}</div>
|
1435 |
+
<div class="theme-title">{theme['name_th']}</div>
|
1436 |
+
<div class="theme-description">{theme['description_th']}</div>
|
1437 |
+
|
1438 |
+
<div class="theme-hover-content">
|
1439 |
+
<p style="font-size: 0.8rem; margin-bottom: 0.5rem;">
|
1440 |
+
🎯 ตัวอย่างคำศัพท์:<br/>
|
1441 |
+
{', '.join(theme['vocabulary'][st.session_state.level][:3])}...
|
1442 |
+
</p>
|
1443 |
+
</div>
|
1444 |
+
</div>
|
1445 |
+
""", unsafe_allow_html=True)
|
1446 |
|
1447 |
+
# Theme Selection Button
|
1448 |
if st.button(
|
1449 |
+
f"เลือกธีม {theme['name_th']}",
|
1450 |
+
key=f"theme_{theme['id']}",
|
1451 |
use_container_width=True,
|
1452 |
+
help=f"คลิกเพื่อเริ่มเขียนเรื่องราวในธีม {theme['name_th']}"
|
1453 |
):
|
1454 |
+
try:
|
1455 |
+
with st.spinner("กำลังเตรียมเรื่องราว..."):
|
1456 |
+
st.session_state.current_theme = theme['id']
|
1457 |
+
starter = generate_dynamic_story_starter(
|
1458 |
+
theme['id'],
|
1459 |
+
st.session_state.level
|
1460 |
+
)
|
1461 |
+
st.session_state.story = [{
|
1462 |
+
"role": "AI",
|
1463 |
+
"content": starter['en'],
|
1464 |
+
"thai_content": starter['th'],
|
1465 |
+
"is_starter": True
|
1466 |
+
}]
|
1467 |
+
st.success(f"เลือกธีม {theme['name_th']} เรียบร้อยแล้ว!")
|
1468 |
+
st.rerun()
|
1469 |
+
except Exception as e:
|
1470 |
+
st.error(f"เกิดข้อผิดพลาดในการเลือกธีม: {str(e)}")
|
1471 |
+
logging.error(f"Theme selection error: {str(e)}")
|
1472 |
+
|
1473 |
+
# Help Text
|
1474 |
+
st.markdown("""
|
1475 |
+
<div style="text-align: center; margin-top: 2rem; padding: 1rem; background: #F5F5F5; border-radius: 8px;">
|
1476 |
+
<p style="color: #666; margin-bottom: 0.5rem;">💡 เคล็ดลับ: เลือกธีมที่คุณสนใจและอยากเขียนถึงที่สุด</p>
|
1477 |
+
<p style="color: #666; font-size: 0.9rem;">
|
1478 |
+
แต่ละธีมมีคำศัพท์และแนวเรื่องที่แตกต่างกัน เหมาะสำหรับการฝึกเขียนในบริบทต่างๆ
|
1479 |
+
</p>
|
1480 |
+
</div>
|
1481 |
+
""", unsafe_allow_html=True)
|
1482 |
+
|
1483 |
+
# Error Handling
|
1484 |
+
if not available_themes:
|
1485 |
+
st.warning("""
|
1486 |
+
⚠️ ไม่พบธีมที่เหมาะสมกับระดับปัจจุบัน
|
1487 |
+
กรุณาเลือกระดับการเรียนรู้ใหม่หรือติดต่อผู้ดูแลระบบ
|
1488 |
+
""")
|
1489 |
|
1490 |
# Add theme-specific CSS
|
1491 |
def add_theme_css():
|
|
|
2156 |
reset_story()
|
2157 |
|
2158 |
# Main UI Layout
|
2159 |
+
|
2160 |
+
# Initialize session state
|
2161 |
+
init_session_state()
|
2162 |
init_theme_state()
|
2163 |
add_theme_css()
|
2164 |
+
|
2165 |
+
# Main UI Layout
|
2166 |
st.markdown("# 📖 JoyStory")
|
2167 |
show_welcome_section()
|
2168 |
+
show_parent_guide()
|
2169 |
|
2170 |
# After showing the welcome section and before the main story area
|
2171 |
if not st.session_state.current_theme:
|
|
|
2226 |
|
2227 |
|
2228 |
# Main content area
|
2229 |
+
if not st.session_state.current_theme:
|
2230 |
+
# Show theme selection if no theme is selected
|
2231 |
+
show_theme_selection()
|
2232 |
+
else:
|
2233 |
+
# Show main story interface
|
2234 |
+
col1, col2 = st.columns([3, 1])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2235 |
|
2236 |
+
with col1:
|
2237 |
+
# Story Display Box
|
2238 |
st.markdown("""
|
2239 |
<div class="thai-eng">
|
2240 |
+
<div class="thai">📖 เรื่องราวของคุณ</div>
|
2241 |
+
<div class="eng">Your Story</div>
|
2242 |
</div>
|
2243 |
""", unsafe_allow_html=True)
|
2244 |
+
|
2245 |
+
# Theme Selection หรือ Change Theme
|
2246 |
+
if not st.session_state.current_theme:
|
2247 |
+
show_theme_selection()
|
2248 |
+
else:
|
2249 |
+
# Show current theme and option to change - เพิ่ม key ให้ปุ่ม
|
2250 |
+
if st.button("🔄 Change Theme", key="change_theme_button"):
|
2251 |
+
st.session_state.current_theme = None
|
2252 |
+
st.session_state.theme_story_starter = None
|
2253 |
+
st.session_state.story = []
|
2254 |
+
st.rerun()
|
2255 |
+
|
2256 |
+
# แสดงเนื้อเรื่อง
|
2257 |
+
show_story()
|
2258 |
+
|
2259 |
+
# Text input area
|
2260 |
+
st.markdown("""
|
2261 |
<div class="thai-eng">
|
2262 |
+
<div class="thai">✏️ ถึงตาคุณแล้ว</div>
|
2263 |
+
<div class="eng">Your Turn</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2264 |
</div>
|
2265 |
""", unsafe_allow_html=True)
|
2266 |
|
2267 |
+
# เพิ่ม key ให้ input area
|
2268 |
+
st.text_area(
|
2269 |
+
"เขียนต่อจากเรื่องราว | Continue the story:",
|
2270 |
+
height=100,
|
2271 |
+
key="story_input_area",
|
2272 |
+
label_visibility="collapsed"
|
2273 |
+
)
|
2274 |
+
|
2275 |
+
# เพิ่ม key ให้ปุ่ม Submit
|
2276 |
+
st.button("ส่งคำตอบ | Submit", key="submit_story_button", on_click=submit_story)
|
2277 |
+
|
2278 |
+
with col2:
|
2279 |
+
# 1. Feedback Section (Most Important)
|
2280 |
+
if st.session_state.feedback:
|
2281 |
+
st.markdown("""
|
2282 |
+
<div class="feedback-box">
|
2283 |
+
<div class="thai-eng">
|
2284 |
+
<div class="thai">📝 คำแนะนำจากครู</div>
|
2285 |
+
<div class="eng">Writing Feedback</div>
|
2286 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2287 |
</div>
|
2288 |
""", unsafe_allow_html=True)
|
2289 |
+
|
2290 |
+
feedback_data = st.session_state.feedback
|
2291 |
+
if isinstance(feedback_data, dict) and feedback_data.get('has_errors'):
|
2292 |
+
st.markdown(f"""
|
2293 |
+
<div style='background-color: #f0f2f6;
|
2294 |
+
padding: 15px;
|
2295 |
+
border-radius: 8px;
|
2296 |
+
border-left: 4px solid #FF9800;
|
2297 |
+
margin: 5px 0;
|
2298 |
+
font-family: "Sarabun", sans-serif;'>
|
2299 |
+
<p style='color: #1e88e5; margin-bottom: 10px;'>
|
2300 |
+
{feedback_data['feedback']}
|
2301 |
+
</p>
|
2302 |
+
<p style='color: #666; font-size: 0.9em;'>
|
2303 |
+
ประโยคที่ถูกต้อง:<br/>
|
2304 |
+
<span style='color: #4CAF50; font-weight: bold;'>
|
2305 |
+
{feedback_data['corrected']}
|
2306 |
+
</span>
|
2307 |
+
</p>
|
2308 |
+
</div>
|
2309 |
+
""", unsafe_allow_html=True)
|
2310 |
+
|
2311 |
+
# แสดงปุ่มแก้ไข
|
2312 |
+
if st.button("✍️ แก้ไขประโยคให้ถูกต้อง", key="correct_button"):
|
2313 |
+
last_user_entry_idx = next(
|
2314 |
+
(i for i, entry in reversed(list(enumerate(st.session_state.story)))
|
2315 |
+
if entry['role'] == 'You'),
|
2316 |
+
None
|
2317 |
+
)
|
2318 |
+
if last_user_entry_idx is not None:
|
2319 |
+
apply_correction(
|
2320 |
+
last_user_entry_idx,
|
2321 |
+
feedback_data['corrected']
|
2322 |
+
)
|
2323 |
+
st.rerun()
|
2324 |
+
else:
|
2325 |
+
st.markdown(f"""
|
2326 |
+
<div style='background-color: #f0f2f6;
|
2327 |
+
padding: 15px;
|
2328 |
+
border-radius: 8px;
|
2329 |
+
border-left: 4px solid #4CAF50;
|
2330 |
+
margin: 5px 0;
|
2331 |
+
font-family: "Sarabun", sans-serif;'>
|
2332 |
+
<p style='color: #1e88e5;'>
|
2333 |
+
{feedback_data.get('feedback', '✨ เขียนได้ถูกต้องแล้วค่ะ!')}
|
2334 |
+
</p>
|
2335 |
+
</div>
|
2336 |
+
""", unsafe_allow_html=True)
|
2337 |
+
|
2338 |
+
# 2. Writing Tools (Expandable)
|
2339 |
+
with st.expander("✨ เครื่องมือช่วยเขียน | Writing Tools"):
|
2340 |
+
if st.button("🎯 ขอคำใบ้"):
|
2341 |
+
prompt = get_creative_prompt()
|
2342 |
+
st.markdown(f"""
|
2343 |
+
<div class="thai-eng">
|
2344 |
+
<div class="thai">💭 {prompt['thai']}</div>
|
2345 |
+
<div class="eng">💭 {prompt['eng']}</div>
|
2346 |
+
</div>
|
2347 |
+
""", unsafe_allow_html=True)
|
2348 |
+
|
2349 |
+
if st.button("📚 คำศัพท์แนะนำ"):
|
2350 |
+
vocab_suggestions = get_vocabulary_suggestions()
|
2351 |
+
st.markdown("#### 📚 คำศัพท์น่ารู้")
|
2352 |
+
for word in vocab_suggestions:
|
2353 |
+
st.markdown(f"• {word}")
|
2354 |
+
|
2355 |
+
# 3. Achievements (Expandable)
|
2356 |
+
with st.expander("🏆 ความสำเร็จ | Achievements"):
|
2357 |
+
show_achievements()
|
2358 |
+
|
2359 |
+
# 4. Save Options (At the bottom)
|
2360 |
st.markdown("### 💾 บันทึกเรื่องราว")
|
2361 |
+
if st.session_state.story:
|
2362 |
+
st.markdown("### 💾 บันทึกเรื่องราว")
|
2363 |
+
col1, col2 = st.columns(2)
|
2364 |
+
with col1:
|
2365 |
+
pdf = create_story_pdf()
|
2366 |
+
st.download_button("📑 PDF", data=pdf, file_name="story.pdf", mime="application/pdf")
|
2367 |
+
with col2:
|
2368 |
+
story_data = {
|
2369 |
+
'level': st.session_state.level,
|
2370 |
+
'story': st.session_state.story,
|
2371 |
+
'achievements': st.session_state.achievements
|
2372 |
+
}
|
2373 |
+
st.download_button("💾 Save", data=json.dumps(story_data), file_name="story.json", mime="application/json")
|
2374 |
+
|
2375 |
+
# Handle story reset if needed
|
2376 |
+
if st.session_state.should_reset:
|
2377 |
+
reset_story()
|
2378 |
+
|
2379 |
# Add new CSS for improved layout
|
2380 |
st.markdown("""
|
2381 |
<style>
|