banao-tech commited on
Commit
6a8ccf5
Β·
verified Β·
1 Parent(s): 3661a96

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +249 -121
app.py CHANGED
@@ -25,6 +25,10 @@ DEFAULT_USER_ID = int(os.getenv("DEFAULT_USER_ID", "30"))
25
  DEFAULT_PERSONALIZATION_ID = int(os.getenv("DEFAULT_PERSONALIZATION_ID", "100"))
26
  API_TIMEOUT = int(os.getenv("API_TIMEOUT", "30"))
27
 
 
 
 
 
28
  # Set page configuration
29
  st.set_page_config(
30
  page_title="Base Course Personalization",
@@ -50,6 +54,9 @@ st.markdown("""
50
  --border-color: #444444;
51
  --header-color: #4F97FF;
52
  --subheader-color: #FFFFFF;
 
 
 
53
  }
54
 
55
  /* Main container styling */
@@ -65,6 +72,7 @@ st.markdown("""
65
  color: var(--header-color);
66
  margin-bottom: 1rem;
67
  text-align: center;
 
68
  }
69
 
70
  .section-header {
@@ -74,31 +82,50 @@ st.markdown("""
74
  margin-top: 2rem;
75
  margin-bottom: 1rem;
76
  padding-bottom: 0.5rem;
77
- border-bottom: 1px solid var(--border-color);
 
 
 
78
  }
79
 
80
  /* Form container */
81
  div[data-testid="stForm"] {
82
  background-color: var(--card-background);
83
- padding: 1.5rem;
84
- border-radius: 8px;
85
- box-shadow: 0 4px 6px rgba(0,0,0,0.3);
 
 
86
  }
87
 
88
  /* Button styling */
89
  .stButton>button {
90
- background-color: var(--accent-color);
91
  color: white;
92
- border-radius: 4px;
93
- padding: 0.5rem 2rem;
94
- font-weight: 500;
95
  border: none;
 
 
 
 
 
 
 
96
  }
97
 
98
- /* Input fields */
99
  div[data-baseweb="select"] > div {
100
  background-color: var(--background-color);
101
- border-color: var(--border-color);
 
 
 
 
 
 
 
102
  }
103
 
104
  .stTextInput > div > div > input,
@@ -106,64 +133,123 @@ st.markdown("""
106
  .stTextArea > div > div > textarea {
107
  background-color: var(--background-color);
108
  color: var(--text-color);
109
- border-color: var(--border-color);
 
 
 
110
  }
111
 
112
- /* Radio buttons - Fix visibility */
113
- .stRadio > div {
114
- background-color: transparent;
 
 
115
  }
116
 
117
- .stRadio > div > label > div {
118
- color: var(--text-color) !important;
 
 
 
 
 
 
119
  }
120
 
121
- /* Select box labels */
122
- .stSelectbox > label {
123
- color: var(--text-color) !important;
 
 
 
 
124
  }
125
 
126
- /* All form labels */
127
- div[data-testid="stForm"] label {
 
 
 
 
 
128
  color: var(--text-color) !important;
 
129
  }
130
 
131
- /* Radio button text */
132
- .stRadio label {
 
 
 
 
133
  color: var(--text-color) !important;
 
 
134
  }
135
 
136
- /* Fix for all input labels */
137
- .st-emotion-cache-1gulkj5,
138
- .st-emotion-cache-1aumxhf,
139
- .st-emotion-cache-16txtl3 {
140
  color: var(--text-color) !important;
 
141
  }
142
 
143
  /* Spacing */
144
  div.block-container {
145
  padding-top: 2rem;
 
146
  }
147
 
148
  hr {
149
- margin-top: 1rem;
150
- margin-bottom: 1rem;
151
- border-color: var(--border-color);
152
  }
153
 
154
  /* API Response Container */
155
  .api-response {
156
  background-color: #1A1A1A;
157
- border-radius: 8px;
158
- padding: 1rem;
159
  border-left: 4px solid var(--accent-color);
 
160
  }
161
 
162
  .session-info {
163
  background-color: var(--card-background);
164
- padding: 1rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  border-radius: 8px;
 
166
  margin: 1rem 0;
 
 
 
 
 
 
 
 
167
  border: 1px solid var(--border-color);
168
  }
169
  </style>
@@ -177,54 +263,54 @@ if 'session_ids' not in st.session_state:
177
  if 'authenticated' not in st.session_state:
178
  st.session_state.authenticated = False
179
 
180
- # Hardcoded credentials (you can change these)
181
- VALID_USERNAME = "admin"
182
- VALID_PASSWORD = "techlearn2024"
183
-
184
  # Authentication check
185
  if not st.session_state.authenticated:
186
  st.markdown('<h1 class="main-header">πŸ” Login to Course Personalization</h1>', unsafe_allow_html=True)
187
 
188
- with st.form("login_form"):
189
- st.markdown('<div class="section-header">πŸ”‘ Authentication Required</div>', unsafe_allow_html=True)
190
-
191
- col1, col2, col3 = st.columns([1, 2, 1])
192
- with col2:
193
- username = st.text_input("Username", placeholder="Enter username")
194
- password = st.text_input("Password", placeholder="Enter password", type="password")
195
 
196
- login_submitted = st.form_submit_button("πŸš€ Login", use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
- if login_submitted:
199
- if username == VALID_USERNAME and password == VALID_PASSWORD:
200
- st.session_state.authenticated = True
201
- st.success("Login successful! Redirecting...")
202
- time.sleep(1)
203
- st.rerun()
204
- else:
205
- st.error(" Invalid username or password")
206
 
207
  st.markdown("---")
208
- st.markdown("""
209
  <div style="text-align: center; color: #888888;">
210
- <small>Demo Credentials: admin / techlearn2024</small>
211
  </div>
212
  """, unsafe_allow_html=True)
213
  st.stop()
214
 
215
- # Main app (only shown after authentication)
216
- # App Header
217
- col1, col2, col3 = st.columns([1, 2, 1])
218
- with col2:
219
- st.markdown('<h1 class="main-header">πŸ“š Base Course Personalization</h1>', unsafe_allow_html=True)
220
  with col3:
221
- if st.button(" Logout"):
222
  st.session_state.authenticated = False
223
  st.session_state.topics_list = [{"topic_title": "What is Flask", "chapter_title": "Introduction to Flask"}]
224
  st.session_state.session_ids = []
225
  st.rerun()
226
 
227
-
228
  # Main Form
229
  with st.form("personalization_form", clear_on_submit=False):
230
  # Topics Section
@@ -232,30 +318,59 @@ with st.form("personalization_form", clear_on_submit=False):
232
 
233
  # Option to choose single or multiple topics
234
  topic_mode = st.radio(
235
- "Topic Mode",
236
  ["Single Topic", "Multiple Topics"],
237
  horizontal=True,
238
  help="Choose whether to process one topic or multiple topics"
239
  )
240
 
241
  if topic_mode == "Single Topic":
242
- st.subheader("Single Topic Details")
243
- single_topic_title = st.text_input("Topic Title", value="What is Flask", help="Enter the topic title")
 
 
 
 
 
 
 
 
244
 
245
  else:
246
- st.subheader("Multiple Topics")
247
 
248
- # Display existing topics
249
  for i, topic in enumerate(st.session_state.topics_list):
250
- col1, col2 = st.columns([4, 1])
 
 
 
251
  with col1:
252
- topic_title = st.text_input(f"Topic {i+1}", value=topic["topic_title"], key=f"topic_{i}")
 
 
 
 
 
253
  st.session_state.topics_list[i]["topic_title"] = topic_title
 
254
  with col2:
 
 
 
 
 
 
 
 
 
255
  if len(st.session_state.topics_list) > 1:
256
- if st.button("πŸ—‘οΈ", key=f"remove_{i}", help="Remove topic"):
 
257
  st.session_state.topics_list.pop(i)
258
  st.rerun()
 
 
259
 
260
  # Language & Voice Settings Section
261
  st.markdown('<div class="section-header">πŸ—£οΈ Language & Voice Settings</div>', unsafe_allow_html=True)
@@ -264,9 +379,10 @@ with st.form("personalization_form", clear_on_submit=False):
264
  with col1:
265
  target_language = st.selectbox(
266
  "Target Language",
267
- ["english", "hindi", "telugu", "tamil", "other"],
268
  index=0,
269
- format_func=lambda x: x.capitalize()
 
270
  )
271
 
272
  with col2:
@@ -274,15 +390,17 @@ with st.form("personalization_form", clear_on_submit=False):
274
  "Voice Gender",
275
  ["male", "female"],
276
  index=0,
277
- format_func=lambda x: x.capitalize()
 
278
  )
279
 
280
  with col3:
281
  tts_voice = st.selectbox(
282
  "Voice Style",
283
  ["onyx", "echo", "soprano", "alto", "robotic"],
284
- index=0, # Default to "onyx"
285
- format_func=lambda x: x.capitalize()
 
286
  )
287
 
288
  # Technical Settings Section
@@ -294,40 +412,59 @@ with st.form("personalization_form", clear_on_submit=False):
294
  "Programming Language",
295
  ["python", "java", "javascript", "c++", "go"],
296
  index=0,
297
- format_func=lambda x: x.capitalize()
 
298
  )
299
  with col2:
300
- toggle_hinglish = st.toggle("Enable Hinglish", value=True, help="Mix of Hindi and English")
 
301
 
302
  # Submit button
303
  st.markdown("<br>", unsafe_allow_html=True)
304
  col1, col2, col3 = st.columns([1, 2, 1])
305
  with col2:
306
- submitted = st.form_submit_button("Generate Personalized Course", use_container_width=True)
307
 
308
  # Add/Remove topic buttons outside the form (for multiple topics)
309
  if topic_mode == "Multiple Topics":
310
- col1, col2, col3 = st.columns([1, 1, 2])
 
311
  with col1:
312
- if st.button(" Add More Topic"):
313
- st.session_state.topics_list.append({"topic_title": f"Topic {len(st.session_state.topics_list) + 1}"})
 
 
 
314
  st.rerun()
315
  with col2:
316
- if st.button(" Reset Topics"):
317
- st.session_state.topics_list = [{"topic_title": "What is Flask"}]
318
  st.rerun()
 
319
 
320
  # Handle submission
321
  if submitted:
 
 
 
 
 
 
322
  # Validate inputs
323
- valid_topics = [topic for topic in st.session_state.topics_list if topic["topic_title"].strip() and topic["chapter_title"].strip()]
 
 
 
324
 
325
  if not valid_topics:
326
- st.error("Please enter at least one topic with both topic title and chapter title")
327
  else:
328
- # Show loading state
329
- with st.spinner("Generating your personalized course..."):
330
- time.sleep(1.5) # Simulating API call delay
 
 
 
331
 
332
  # Hardcoded values
333
  course_id = DEFAULT_COURSE_ID
@@ -405,53 +542,44 @@ if submitted:
405
  response_data = response.json()
406
  session_ids = response_data.get("session_ids", [])
407
 
408
- st.success(f"Course personalization started successfully!")
409
 
410
  # Store session IDs in session state
411
  st.session_state.session_ids.extend(session_ids)
412
 
413
  # Display results in a clean format
414
- st.markdown("### πŸŽ‰ Your personalized course generation has started!")
415
- st.markdown(f"""
416
- **Course ID**: {course_id}
417
- **Programming Language**: {programming_language.capitalize()}
418
- **Target Language**: {target_language.capitalize()}
419
- **Voice**: {tts_voice.capitalize()} ({tts_gender.capitalize()})
420
- **Topics**: {len(valid_topics)}
421
- """)
 
 
 
 
 
 
 
422
 
423
- # Display session IDs
424
- if session_ids:
425
- st.markdown("### πŸ” Session IDs for Tracking")
426
- for i, session_id in enumerate(session_ids, 1):
427
- st.markdown(f'<div class="session-info"><strong>Session {i}:</strong> <code>{session_id}</code></div>', unsafe_allow_html=True)
428
 
429
- # Display API response
430
- st.markdown('<div class="section-header">πŸ“Š API Response</div>', unsafe_allow_html=True)
431
- st.markdown('<div class="api-response">', unsafe_allow_html=True)
432
- st.json(response_data)
433
- st.markdown('</div>', unsafe_allow_html=True)
434
 
435
- # Information about tracking
436
- st.info(f"""
437
- πŸ’‘ **Tracking Information**
438
- You can track the progress of your video generation using the session IDs above.
439
- The processing status will be updated in DynamoDB table: `{SESSION_TABLE}`
440
- Region: `{DYNAMODB_REGION}`
441
- """)
442
 
443
  else:
444
- st.error(f"API Error: {response.status_code}")
445
  if response.text:
446
- st.error(f"Error Details: {response.text}")
447
 
448
  except requests.exceptions.Timeout:
449
- st.error("Request timed out. Please try again later.")
450
  except requests.exceptions.ConnectionError:
451
- st.error("Connection error. Please check your internet connection.")
452
  except Exception as e:
453
- st.error(f"API call failed: {str(e)}")
454
 
455
  # Show payload for debugging
456
- st.warning("Request payload for debugging:")
457
- st.json(payload)
 
 
25
  DEFAULT_PERSONALIZATION_ID = int(os.getenv("DEFAULT_PERSONALIZATION_ID", "100"))
26
  API_TIMEOUT = int(os.getenv("API_TIMEOUT", "30"))
27
 
28
+ # Authentication credentials from environment variables
29
+ VALID_USERNAME = os.getenv("APP_USERNAME")
30
+ VALID_PASSWORD = os.getenv("APP_PASSWORD")
31
+
32
  # Set page configuration
33
  st.set_page_config(
34
  page_title="Base Course Personalization",
 
54
  --border-color: #444444;
55
  --header-color: #4F97FF;
56
  --subheader-color: #FFFFFF;
57
+ --success-color: #10B981;
58
+ --warning-color: #F59E0B;
59
+ --error-color: #EF4444;
60
  }
61
 
62
  /* Main container styling */
 
72
  color: var(--header-color);
73
  margin-bottom: 1rem;
74
  text-align: center;
75
+ text-shadow: 0 2px 4px rgba(79, 151, 255, 0.3);
76
  }
77
 
78
  .section-header {
 
82
  margin-top: 2rem;
83
  margin-bottom: 1rem;
84
  padding-bottom: 0.5rem;
85
+ border-bottom: 2px solid var(--border-color);
86
+ display: flex;
87
+ align-items: center;
88
+ gap: 0.5rem;
89
  }
90
 
91
  /* Form container */
92
  div[data-testid="stForm"] {
93
  background-color: var(--card-background);
94
+ padding: 2rem;
95
+ border-radius: 12px;
96
+ box-shadow: 0 8px 25px rgba(0,0,0,0.4);
97
+ border: 1px solid var(--border-color);
98
+ margin-bottom: 1rem;
99
  }
100
 
101
  /* Button styling */
102
  .stButton>button {
103
+ background: linear-gradient(135deg, var(--accent-color) 0%, #3B82F6 100%);
104
  color: white;
105
+ border-radius: 8px;
106
+ padding: 0.75rem 2rem;
107
+ font-weight: 600;
108
  border: none;
109
+ transition: all 0.3s ease;
110
+ box-shadow: 0 4px 15px rgba(79, 151, 255, 0.3);
111
+ }
112
+
113
+ .stButton>button:hover {
114
+ transform: translateY(-2px);
115
+ box-shadow: 0 6px 20px rgba(79, 151, 255, 0.4);
116
  }
117
 
118
+ /* Input fields styling */
119
  div[data-baseweb="select"] > div {
120
  background-color: var(--background-color);
121
+ border: 2px solid var(--border-color);
122
+ border-radius: 8px;
123
+ transition: border-color 0.3s ease;
124
+ }
125
+
126
+ div[data-baseweb="select"] > div:focus-within {
127
+ border-color: var(--accent-color);
128
+ box-shadow: 0 0 0 3px rgba(79, 151, 255, 0.1);
129
  }
130
 
131
  .stTextInput > div > div > input,
 
133
  .stTextArea > div > div > textarea {
134
  background-color: var(--background-color);
135
  color: var(--text-color);
136
+ border: 2px solid var(--border-color);
137
+ border-radius: 8px;
138
+ padding: 0.75rem;
139
+ transition: border-color 0.3s ease;
140
  }
141
 
142
+ .stTextInput > div > div > input:focus,
143
+ .stNumberInput > div > div > input:focus,
144
+ .stTextArea > div > div > textarea:focus {
145
+ border-color: var(--accent-color);
146
+ box-shadow: 0 0 0 3px rgba(79, 151, 255, 0.1);
147
  }
148
 
149
+ /* Topic container styling */
150
+ .topic-container {
151
+ background-color: var(--card-background);
152
+ padding: 1.5rem;
153
+ border-radius: 10px;
154
+ margin-bottom: 1rem;
155
+ border: 1px solid var(--border-color);
156
+ position: relative;
157
  }
158
 
159
+ .topic-header {
160
+ display: flex;
161
+ align-items: center;
162
+ gap: 0.5rem;
163
+ margin-bottom: 1rem;
164
+ font-weight: 600;
165
+ color: var(--accent-color);
166
  }
167
 
168
+ /* Radio buttons */
169
+ .stRadio > div {
170
+ background-color: transparent;
171
+ gap: 1rem;
172
+ }
173
+
174
+ .stRadio > div > label > div {
175
  color: var(--text-color) !important;
176
+ font-weight: 500;
177
  }
178
 
179
+ /* Labels */
180
+ .stSelectbox > label,
181
+ .stTextInput > label,
182
+ .stNumberInput > label,
183
+ .stTextArea > label,
184
+ .stRadio > label {
185
  color: var(--text-color) !important;
186
+ font-weight: 500;
187
+ margin-bottom: 0.5rem;
188
  }
189
 
190
+ /* Toggle switch */
191
+ .stToggle > label {
 
 
192
  color: var(--text-color) !important;
193
+ font-weight: 500;
194
  }
195
 
196
  /* Spacing */
197
  div.block-container {
198
  padding-top: 2rem;
199
+ max-width: 1200px;
200
  }
201
 
202
  hr {
203
+ margin: 2rem 0;
204
+ border: none;
205
+ border-top: 1px solid var(--border-color);
206
  }
207
 
208
  /* API Response Container */
209
  .api-response {
210
  background-color: #1A1A1A;
211
+ border-radius: 10px;
212
+ padding: 1.5rem;
213
  border-left: 4px solid var(--accent-color);
214
+ margin: 1rem 0;
215
  }
216
 
217
  .session-info {
218
  background-color: var(--card-background);
219
+ padding: 1.5rem;
220
+ border-radius: 10px;
221
+ margin: 1rem 0;
222
+ border: 1px solid var(--border-color);
223
+ box-shadow: 0 4px 12px rgba(0,0,0,0.2);
224
+ }
225
+
226
+ /* Action buttons container */
227
+ .action-buttons {
228
+ display: flex;
229
+ gap: 1rem;
230
+ margin: 1rem 0;
231
+ justify-content: flex-start;
232
+ }
233
+
234
+ /* Small action buttons */
235
+ .small-button {
236
+ padding: 0.5rem 1rem;
237
+ font-size: 0.875rem;
238
+ }
239
+
240
+ /* Success/Error styling */
241
+ .stSuccess, .stError, .stWarning, .stInfo {
242
  border-radius: 8px;
243
+ padding: 1rem;
244
  margin: 1rem 0;
245
+ }
246
+
247
+ /* Login container */
248
+ .login-container {
249
+ background-color: var(--card-background);
250
+ padding: 3rem;
251
+ border-radius: 15px;
252
+ box-shadow: 0 10px 30px rgba(0,0,0,0.5);
253
  border: 1px solid var(--border-color);
254
  }
255
  </style>
 
263
  if 'authenticated' not in st.session_state:
264
  st.session_state.authenticated = False
265
 
 
 
 
 
266
  # Authentication check
267
  if not st.session_state.authenticated:
268
  st.markdown('<h1 class="main-header">πŸ” Login to Course Personalization</h1>', unsafe_allow_html=True)
269
 
270
+ col1, col2, col3 = st.columns([1, 2, 1])
271
+ with col2:
272
+ with st.container():
273
+ st.markdown('<div class="login-container">', unsafe_allow_html=True)
 
 
 
274
 
275
+ with st.form("login_form"):
276
+ st.markdown('<div class="section-header">πŸ”‘ Authentication Required</div>', unsafe_allow_html=True)
277
+
278
+ username = st.text_input("Username", placeholder="Enter username", key="login_username")
279
+ password = st.text_input("Password", placeholder="Enter password", type="password", key="login_password")
280
+
281
+ login_submitted = st.form_submit_button("πŸš€ Login", use_container_width=True)
282
+
283
+ if login_submitted:
284
+ if username == VALID_USERNAME and password == VALID_PASSWORD:
285
+ st.session_state.authenticated = True
286
+ st.success("Login successful! Redirecting...")
287
+ time.sleep(1)
288
+ st.rerun()
289
+ else:
290
+ st.error("❌ Invalid username or password")
291
 
292
+ st.markdown('</div>', unsafe_allow_html=True)
 
 
 
 
 
 
 
293
 
294
  st.markdown("---")
295
+ st.markdown(f"""
296
  <div style="text-align: center; color: #888888;">
297
+ <small>Demo Credentials: {VALID_USERNAME} / {VALID_PASSWORD if len(VALID_PASSWORD) <= 10 else VALID_PASSWORD[:3] + '...'}</small>
298
  </div>
299
  """, unsafe_allow_html=True)
300
  st.stop()
301
 
302
+ # Main app header
303
+ st.markdown('<h1 class="main-header">πŸ“š Base Course Personalization</h1>', unsafe_allow_html=True)
304
+
305
+ # Logout button in top right
306
+ col1, col2, col3 = st.columns([2, 1, 1])
307
  with col3:
308
+ if st.button("πŸ”“ Logout", key="logout_btn"):
309
  st.session_state.authenticated = False
310
  st.session_state.topics_list = [{"topic_title": "What is Flask", "chapter_title": "Introduction to Flask"}]
311
  st.session_state.session_ids = []
312
  st.rerun()
313
 
 
314
  # Main Form
315
  with st.form("personalization_form", clear_on_submit=False):
316
  # Topics Section
 
318
 
319
  # Option to choose single or multiple topics
320
  topic_mode = st.radio(
321
+ "Select Topic Mode",
322
  ["Single Topic", "Multiple Topics"],
323
  horizontal=True,
324
  help="Choose whether to process one topic or multiple topics"
325
  )
326
 
327
  if topic_mode == "Single Topic":
328
+ st.markdown('<div class="topic-container">', unsafe_allow_html=True)
329
+ st.markdown('<div class="topic-header">πŸ“ Single Topic Configuration</div>', unsafe_allow_html=True)
330
+
331
+ col1, col2 = st.columns(2)
332
+ with col1:
333
+ single_topic_title = st.text_input("Topic Title", value="What is Flask", help="Enter the topic title", key="single_topic")
334
+ with col2:
335
+ single_chapter_title = st.text_input("Chapter Title", value="Introduction to Flask", help="Enter the chapter title", key="single_chapter")
336
+
337
+ st.markdown('</div>', unsafe_allow_html=True)
338
 
339
  else:
340
+ st.markdown("### πŸ“š Multiple Topics Configuration")
341
 
342
+ # Display existing topics with better styling
343
  for i, topic in enumerate(st.session_state.topics_list):
344
+ st.markdown(f'<div class="topic-container">', unsafe_allow_html=True)
345
+ st.markdown(f'<div class="topic-header">πŸ“– Topic {i+1}</div>', unsafe_allow_html=True)
346
+
347
+ col1, col2, col3 = st.columns([3, 3, 1])
348
  with col1:
349
+ topic_title = st.text_input(
350
+ "Topic Title",
351
+ value=topic["topic_title"],
352
+ key=f"topic_title_{i}",
353
+ help="Enter the topic title"
354
+ )
355
  st.session_state.topics_list[i]["topic_title"] = topic_title
356
+
357
  with col2:
358
+ chapter_title = st.text_input(
359
+ "Chapter Title",
360
+ value=topic["chapter_title"],
361
+ key=f"chapter_title_{i}",
362
+ help="Enter the chapter title"
363
+ )
364
+ st.session_state.topics_list[i]["chapter_title"] = chapter_title
365
+
366
+ with col3:
367
  if len(st.session_state.topics_list) > 1:
368
+ st.markdown("<br>", unsafe_allow_html=True) # Add spacing
369
+ if st.button("πŸ—‘οΈ", key=f"remove_{i}", help="Remove this topic"):
370
  st.session_state.topics_list.pop(i)
371
  st.rerun()
372
+
373
+ st.markdown('</div>', unsafe_allow_html=True)
374
 
375
  # Language & Voice Settings Section
376
  st.markdown('<div class="section-header">πŸ—£οΈ Language & Voice Settings</div>', unsafe_allow_html=True)
 
379
  with col1:
380
  target_language = st.selectbox(
381
  "Target Language",
382
+ ["english", "hindi", "marathi", "kannada", "punjabi","gujarati"],
383
  index=0,
384
+ format_func=lambda x: x.capitalize(),
385
+ help="Select the target language for content generation"
386
  )
387
 
388
  with col2:
 
390
  "Voice Gender",
391
  ["male", "female"],
392
  index=0,
393
+ format_func=lambda x: x.capitalize(),
394
+ help="Select the voice gender for text-to-speech"
395
  )
396
 
397
  with col3:
398
  tts_voice = st.selectbox(
399
  "Voice Style",
400
  ["onyx", "echo", "soprano", "alto", "robotic"],
401
+ index=0,
402
+ format_func=lambda x: x.capitalize(),
403
+ help="Select the voice style for text-to-speech"
404
  )
405
 
406
  # Technical Settings Section
 
412
  "Programming Language",
413
  ["python", "java", "javascript", "c++", "go"],
414
  index=0,
415
+ format_func=lambda x: x.capitalize(),
416
+ help="Select the primary programming language for examples"
417
  )
418
  with col2:
419
+ st.markdown("<br>", unsafe_allow_html=True) # Add spacing
420
+ toggle_hinglish = st.toggle("Enable Hinglish", value=True, help="Enable mixing of Hindi and English")
421
 
422
  # Submit button
423
  st.markdown("<br>", unsafe_allow_html=True)
424
  col1, col2, col3 = st.columns([1, 2, 1])
425
  with col2:
426
+ submitted = st.form_submit_button("πŸš€ Generate Base Course", use_container_width=True)
427
 
428
  # Add/Remove topic buttons outside the form (for multiple topics)
429
  if topic_mode == "Multiple Topics":
430
+ st.markdown('<div class="action-buttons">', unsafe_allow_html=True)
431
+ col1, col2, col3, col4 = st.columns([2, 2, 2, 4])
432
  with col1:
433
+ if st.button(" Add Topic", key="add_topic", help="Add a new topic"):
434
+ st.session_state.topics_list.append({
435
+ "topic_title": f"Topic {len(st.session_state.topics_list) + 1}",
436
+ "chapter_title": f"Chapter {len(st.session_state.topics_list) + 1}"
437
+ })
438
  st.rerun()
439
  with col2:
440
+ if st.button(" Reset All", key="reset_topics", help="Reset to default topics"):
441
+ st.session_state.topics_list = [{"topic_title": "What is Flask", "chapter_title": "Introduction to Flask"}]
442
  st.rerun()
443
+ st.markdown('</div>', unsafe_allow_html=True)
444
 
445
  # Handle submission
446
  if submitted:
447
+ # Determine which topics to use based on mode
448
+ if topic_mode == "Single Topic":
449
+ topics_to_process = [{"topic_title": single_topic_title, "chapter_title": single_chapter_title}]
450
+ else:
451
+ topics_to_process = st.session_state.topics_list
452
+
453
  # Validate inputs
454
+ valid_topics = []
455
+ for topic in topics_to_process:
456
+ if topic["topic_title"].strip() and topic["chapter_title"].strip():
457
+ valid_topics.append(topic)
458
 
459
  if not valid_topics:
460
+ st.error("❌ Please enter at least one topic with both topic title and chapter title")
461
  else:
462
+ # Show loading state with better animation
463
+ with st.spinner("🎬 Generating your personalized course... This may take a few moments."):
464
+ progress_bar = st.progress(0)
465
+ for i in range(100):
466
+ time.sleep(0.02) # Simulating progress
467
+ progress_bar.progress(i + 1)
468
 
469
  # Hardcoded values
470
  course_id = DEFAULT_COURSE_ID
 
542
  response_data = response.json()
543
  session_ids = response_data.get("session_ids", [])
544
 
545
+ st.success(" Base Course started successfully!")
546
 
547
  # Store session IDs in session state
548
  st.session_state.session_ids.extend(session_ids)
549
 
550
  # Display results in a clean format
551
+ st.markdown("### Generation Summary")
552
+
553
+ col1, col2 = st.columns(2)
554
+ with col1:
555
+ st.markdown(f"""
556
+ **Course ID**: `{course_id}`
557
+ **Programming Language**: {programming_language.capitalize()}
558
+ **Target Language**: {target_language.capitalize()}
559
+ """)
560
+ with col2:
561
+ st.markdown(f"""
562
+ **Voice**: {tts_voice.capitalize()} ({tts_gender.capitalize()})
563
+ **Topics Count**: {len(valid_topics)}
564
+ **Hinglish**: {"Enabled" if toggle_hinglish else "Disabled"}
565
+ """)
566
 
 
 
 
 
 
567
 
 
 
 
 
 
568
 
 
 
 
 
 
 
 
569
 
570
  else:
571
+ st.error(f" API Error: {response.status_code}")
572
  if response.text:
573
+ st.error(f"**Error Details**: {response.text}")
574
 
575
  except requests.exceptions.Timeout:
576
+ st.error(" Request timed out. Please try again later.")
577
  except requests.exceptions.ConnectionError:
578
+ st.error("🌐 Connection error. Please check your internet connection.")
579
  except Exception as e:
580
+ st.error(f" API call failed: {str(e)}")
581
 
582
  # Show payload for debugging
583
+ with st.expander("πŸ› Debug Information", expanded=False):
584
+ st.warning("Request payload for debugging:")
585
+ st.json(payload)