Maryam Ilka commited on
Commit
9015f8c
·
verified ·
1 Parent(s): 6baf2ce

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +479 -8
app.py CHANGED
@@ -17,17 +17,249 @@ SHEET_ID = "1mmdWAyOCYq4yXMgP53Duq712AnlqZWLkfIo76JqM7wM"
17
  SHEET_NAME = "Condition1"
18
 
19
  # ========== استایل‌های سفارشی یکپارچه ==========
20
- # (استایل‌ها مانند قبل باقی می‌مانند)
21
- # ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
  # ========== توابع اصلی ==========
24
  def create_ride_map():
25
  """ایجاد نقشه سفر با Folium"""
26
- # (کد مانند قبل)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
  def show_explanation(exp_type):
29
  """نمایش توضیحات قیمت"""
30
- # (کد مانند قبل)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
  def create_likert_question(question, key, scale_type="5point"):
33
  """سوال لیکرت با دکمه‌ها"""
@@ -74,7 +306,24 @@ def create_likert_question(question, key, scale_type="5point"):
74
  # ========== توابع مدیریت داده‌ها ==========
75
  def get_credentials():
76
  """دریافت اعتبارنامه از Secrets"""
77
- # (کد مانند قبل)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
  def save_to_sheet(data):
80
  try:
@@ -133,10 +382,149 @@ def save_to_sheet(data):
133
 
134
  except Exception as e:
135
  st.error(f"خطا در ذخیره‌سازی: {str(e)}")
136
- return False
137
 
138
  # ========== بخش‌های فرم ==========
139
- # (صفحات welcome, contact, demographic, scenario_explanation, map_view مانند قبل)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
  def attention_check1():
142
  """سوال توجه اول (رادیویی ساده)"""
@@ -218,8 +606,91 @@ def random_likert_questions():
218
  else:
219
  st.session_state.current_page = "attention_check2"
220
  st.rerun()
 
 
 
 
 
 
 
 
 
 
 
 
221
 
222
- # (صفحات explanation_questions و thank_you مانند قبل)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
  # ========== مدیریت وضعیت و صفحه‌بندی ==========
225
  def main():
 
17
  SHEET_NAME = "Condition1"
18
 
19
  # ========== استایل‌های سفارشی یکپارچه ==========
20
+ st.markdown("""
21
+ <style>
22
+ @font-face {
23
+ font-family: 'Vazir';
24
+ src: url('https://cdn.jsdelivr.net/gh/rastikerdar/vazir-font@v30.1.0/dist/Vazir.woff') format('woff');
25
+ }
26
+
27
+ :root {
28
+ --primary: #6a0dad;
29
+ --text: #333333;
30
+ --background: #ffffff;
31
+ --border: #dddddd;
32
+ --input-bg: #ffffff;
33
+ --secondary-bg: #f8f9fa;
34
+ --green: #f0ff0;
35
+ }
36
+
37
+ * {
38
+ font-family: 'Vazir', sans-serif !important;
39
+ text-align: right !important;
40
+ direction: rtl !important;
41
+ }
42
+
43
+ /* تنظیمات اصلی */
44
+ body, .stApp, [data-testid="stAppViewContainer"] {
45
+ background-color: var(--background) !important;
46
+ color: var(--text) !important;
47
+ }
48
+
49
+ /* هدر راهیار */
50
+ .rahyar-title {
51
+ color: var(--primary) !important;
52
+ margin: 0 !important;
53
+ }
54
+
55
+ .rahyar-subtitle {
56
+ color: var(--primary) !important;
57
+ margin: 0 !important;
58
+ font-size: 14px !important;
59
+ }
60
+
61
+ /* باکس‌های ورودی */
62
+ .stTextInput input,
63
+ .stNumberInput input,
64
+ .stSelectbox select,
65
+ .stTextArea textarea,
66
+ .stDateInput input,
67
+ .stTimeInput input,
68
+ .stMultiSelect div[role="combobox"],
69
+ div[data-testid="stVerticalBlock"] > div[data-testid="stHorizontalBlock"] > div > div > div > div > input,
70
+ /* لیست dropdown */
71
+ .st-bq, .st-br, .st-bs, .st-bt, .st-bu, .st-bv, .st-bw, .st-bx, .st-by, .st-bz {
72
+ color: var(--text) !important;
73
+ background-color: var(--input-bg) !important;
74
+ }
75
+
76
+ /* استایل برای متن بالای باکس‌های دموگرافیک */
77
+ .stTextInput > label,
78
+ .stNumberInput > label,
79
+ .stSelectbox > label,
80
+ .stRadio > label,
81
+ .stSlider > label {
82
+ color: black !important;
83
+ font-weight: bold !important;
84
+ }
85
+
86
+ /* Placeholder */
87
+ ::placeholder {
88
+ color: var(--text) !important;
89
+ opacity: 0.7 !important;
90
+ }
91
+
92
+ /* دکمه اصلی (بنفش با متن سفید) */
93
+ .stButton>button,
94
+ [data-testid="baseButton-primary"],
95
+ .accept-btn,
96
+ div[data-testid="stVerticalBlock"] > div[data-testid="stHorizontalBlock"] > div > div > button {
97
+ background-color: var(--primary) !important;
98
+ color: white !important;
99
+ border: none !important;
100
+ border-radius: 8px !important;
101
+ padding: 10px 20px !important;
102
+ font-weight: bold !important;
103
+ }
104
+
105
+ /* دکمه ثانویه (سفید با حاشیه بنفش) */
106
+ .stFormSubmitButton>button,
107
+ [data-testid="baseButton-secondary"],
108
+ .reject-btn {
109
+ background-color: var(--primary) !important;
110
+ color: var(--input-bg) !important;
111
+ border: 1px solid var(--primary) !important;
112
+ border-radius: 8px !important;
113
+ padding: 10px 20px !important;
114
+ font-weight: bold !important;
115
+ }
116
+
117
+
118
+ /* کامپوننت‌های سفارشی */
119
+ .rahyar-header {
120
+ background-color: var(--primary) !important;
121
+ color: white !important;
122
+ padding: 15px !important;
123
+ border-radius: 10px !important;
124
+ margin-bottom: 20px !important;
125
+ text-align: center !important;
126
+ }
127
+
128
+ .price-container {
129
+ background-color: var(--secondary-bg) !important;
130
+ border-radius: 10px !important;
131
+ padding: 15px !important;
132
+ margin: 15px 0 !important;
133
+ border-right: 5px solid var(--primary) !important;
134
+ }
135
+
136
+ .rahyar-price {
137
+ color: var(--primary) !important;
138
+ font-size: 28px !important;
139
+ font-weight: bold !important;
140
+ }
141
+
142
+ /* فرم دموگرافیک */
143
+ .stSelectbox > div > div {
144
+ background-color: white !important;
145
+ color: var(--text) !important;
146
+ }
147
+
148
+ .stSelectbox option {
149
+ background-color: white !important;
150
+ color: var(--text) !important;
151
+ }
152
+
153
+ /* توضیحات */
154
+ .explanation-title {
155
+ color: var(--primary) !important;
156
+ font-weight: bold !important;
157
+ margin: 20px 0 10px 0 !important;
158
+ font-size: 18px !important;
159
+ }
160
+
161
+ .explanation-item {
162
+ background-color: var(--secondary-bg) !important;
163
+ border-radius: 8px !important;
164
+ padding: 12px 15px !important;
165
+ margin: 8px 0 !important;
166
+ border-right: 3px solid var(--primary) !important;
167
+ }
168
+
169
+ /* استایل برای سوالات رادیویی و گزینه‌ها */
170
+ .stRadio > label,
171
+ .stRadio > div > label,
172
+ .stRadio > div > div > label,
173
+ .stRadio > div > div > div > label,
174
+ .stRadio span {
175
+ color: black !important;
176
+ }
177
+
178
+ /* استایل برای متن سوالات */
179
+ .stMarkdown h3,
180
+ .stMarkdown p {
181
+ color: black !important;
182
+ }
183
+
184
+ /* استایل برای دکمه ثبت */
185
+ .stButton > button {
186
+ color: white !important;
187
+ }
188
+
189
+ /* پیام موفقیت */
190
+ .stAlert .stSuccess {
191
+ color: var(--text) !important;
192
+ background-color: #f0fff0 !important;
193
+ }
194
+
195
+
196
+ /* تنظیمات مخصوص دسکتاپ */
197
+ @media (min-width: 769px) {
198
+ .folium-map {
199
+ height: 500px !important;
200
+ }
201
+ }
202
+
203
+ /* تنظیمات مخصوص موبایل */
204
+ @media (max-width: 768px) {
205
+ .folium-map {
206
+ height: 300px !important;
207
+ }
208
+
209
+ .stSelectbox > div > div {
210
+ padding: 8px !important;
211
+ }
212
+ }
213
+ </style>
214
+ """, unsafe_allow_html=True)
215
 
216
  # ========== توابع اصلی ==========
217
  def create_ride_map():
218
  """ایجاد نقشه سفر با Folium"""
219
+ start_point = [35.7698, 51.4116] # میدان ونک
220
+ end_point = [35.8044, 51.4258] # میدان تجریش
221
+
222
+ m = folium.Map(location=[35.7871, 51.4187], zoom_start=13)
223
+
224
+ folium.Marker(
225
+ start_point,
226
+ popup="<b>مبدأ:</b> میدان ونک",
227
+ icon=folium.Icon(color="green", icon="flag", prefix="fa")
228
+ ).add_to(m)
229
+
230
+ folium.Marker(
231
+ end_point,
232
+ popup="<b>مقصد:</b> میدان تجریش",
233
+ icon=folium.Icon(color="red", icon="flag", prefix="fa")
234
+ ).add_to(m)
235
+
236
+ folium.PolyLine(
237
+ [start_point, end_point],
238
+ color="#6a0dad",
239
+ weight=3,
240
+ opacity=1
241
+ ).add_to(m)
242
+
243
+ return m
244
 
245
  def show_explanation(exp_type):
246
  """نمایش توضیحات قیمت"""
247
+ explanations = {
248
+ "input": [
249
+ "سطح تقاضا در منطقه: زیاد",
250
+ "تعداد رانندگان فعال: کم",
251
+ "زمان روز: ساعت اوج ترافیک",
252
+ "شرایط جوی: هوای بارانی"
253
+ ],
254
+ "counterfactual": [
255
+ "اگر این سفر را ۳۰ دقیقه دیرتر درخواست می‌کردید، به دلیل سطح تقاضای کمتر، رانندگان فعال بیش‌تر، زمان بهتر روز و شرایط جوی بهتر، ممکن بود قیمت ۱۵٪ کمتر باشد.",
256
+ ]
257
+ }
258
+
259
+ if exp_type != "control":
260
+ st.markdown("<p class='explanation-title'>علت قیمت گذاری:</p>", unsafe_allow_html=True)
261
+ for item in explanations.get(exp_type, []):
262
+ st.markdown(f"<p class='explanation-item'>• {item}</p>", unsafe_allow_html=True)
263
 
264
  def create_likert_question(question, key, scale_type="5point"):
265
  """سوال لیکرت با دکمه‌ها"""
 
306
  # ========== توابع مدیریت داده‌ها ==========
307
  def get_credentials():
308
  """دریافت اعتبارنامه از Secrets"""
309
+ try:
310
+ service_account_json = os.environ.get('GCP_SERVICE_ACCOUNT')
311
+ if not service_account_json:
312
+ st.error("مقدار GCP_SERVICE_ACCOUNT در محیط یافت نشد")
313
+ return None
314
+
315
+ service_account_info = json.loads(service_account_json)
316
+ creds = Credentials.from_service_account_info(
317
+ service_account_info,
318
+ scopes=[
319
+ "https://www.googleapis.com/auth/spreadsheets",
320
+ "https://www.googleapis.com/auth/drive.file"
321
+ ]
322
+ )
323
+ return creds
324
+ except Exception as e:
325
+ st.error(f"خطا در دریافت اعتبارنامه: {str(e)}")
326
+ return None
327
 
328
  def save_to_sheet(data):
329
  try:
 
382
 
383
  except Exception as e:
384
  st.error(f"خطا در ذخیره‌سازی: {str(e)}")
385
+ return False
386
 
387
  # ========== بخش‌های فرم ==========
388
+
389
+ def welcome_page():
390
+ """صفحه خوشامدگویی"""
391
+ st.markdown("""
392
+ <div style="text-align: center; margin-bottom: 30px;">
393
+ <h2> 🚖 قیمت‌گذاری در پلتفرم‌های درخواست تاکسی اینترنتی</h2>
394
+ <p>👋با سلام و درود</p>
395
+ <p>پیشاپیش بابت زمانی که برای پاسخ به سوالات این پرسشنامه و پیش‌برد اهداف علمی دانشجویان می‌گذارید، متشکرم.</p>
396
+ <p>جهت تقدیر از شرکت‌کنندگان، به دو نفر به قید قرعه جایزه 5 میلیون ریالی تقدیم خواهد شد.</p>
397
+ </div>
398
+
399
+ <div style="display: flex; align-items: center; background-color: #f0f2f6; border-radius: 10px; padding: 20px; gap: 20px;">
400
+ <div style="flex: 0 0 100px;">
401
+ <img src="https://huggingface.co/spaces/maryamilka/surge-pricing/resolve/main/shariflogo.png" alt="لوگو دانشگاه شریف" style="width: 100%; max-width: 100px;">
402
+ </div>
403
+ <div style="flex: 1;">
404
+ <h3>درباره تحقیق:</h3>
405
+ <p>این پرسشنامه بخشی از یک پایان‌نامه کارشناسی ارشد در دانشگاه صنعتی شریف است که به بررسی ادراک انصاف در قیمت‌گذاری در پلتفرم‌های درخواست تاکسی اینترنتی می‌پردازد.</p>
406
+ <p>پاسخ‌های شما به سوالات کاملاً محرمانه خواهد بود و فقط در جهت اهداف علمی استفاده خواهد شذ.</p>
407
+ <p>جهت شروع روی دکمه زیر کلیک کنید 👇🏻</p>
408
+ </div>
409
+ </div>
410
+ """, unsafe_allow_html=True)
411
+
412
+ if st.button("شروع پرسشنامه", key="start_btn", type="primary"):
413
+ st.session_state.current_page = "contact"
414
+ st.session_state.start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
415
+ st.rerun()
416
+
417
+
418
+ def user_contact():
419
+ """راه ارتباطی ساده"""
420
+ st.markdown("""
421
+ <div style="text-align: center; margin-bottom: 30px;">
422
+ <h3>📩 راه ارتباطی شما (اختیاری)</h3>
423
+ <p>در صورت تمایل به شرکت در قرعه‌کشی می‌توانید آیدی تلگرام، شماره تماس یا ایمیل خود را وارد کنید:</p>
424
+ </div>
425
+ """, unsafe_allow_html=True)
426
+
427
+ contact_info = st.text_input(
428
+ "راه ارتباطی (اختیاری)",
429
+ placeholder="مثال: @username یا 09123456789 یا example@email.com",
430
+ key="user_contact_input"
431
+ )
432
+
433
+ if st.button("ادامه", key="continue_btn", type="primary"):
434
+ st.session_state.user_contact = contact_info
435
+ st.session_state.current_page = "demographic"
436
+ st.rerun()
437
+
438
+ def demographic_form():
439
+ """فرم اطلاعات دموگرافیک"""
440
+ st.markdown("### 📝 اطلاعات دموگرافیک")
441
+
442
+ with st.form("demographic_form"):
443
+ age = st.number_input("سن", min_value=18, max_value=100)
444
+ gender = st.selectbox("جنسیت", ["مرد", "زن", "سایر"])
445
+ education = st.selectbox("تحصیلات", ["دیپلم", "لیسانس", "فوق لیسانس", "دکترا"])
446
+ ride_frequency = st.selectbox("دفعات استفاده از سرویس‌های اشتراک سفر در ماه",
447
+ ["کمتر از 5 بار", "5-10 بار", "بیش از 10 بار"])
448
+
449
+ if st.form_submit_button("ادامه"):
450
+ st.session_state.demographic_data = {
451
+ "age": age,
452
+ "gender": gender,
453
+ "education": education,
454
+ "ride_frequency": ride_frequency
455
+ }
456
+ st.session_state.current_page = "scenario_explanation"
457
+ st.rerun()
458
+
459
+ def scenario_explanation():
460
+ """توضیح سناریو"""
461
+ col1, col2 = st.columns([1, 4])
462
+ with col1:
463
+ try:
464
+ st.image("rahyar.png", width=80)
465
+ except:
466
+ st.image("https://via.placeholder.com/80/6a0dad/FFFFFF?text=LOGO", width=80)
467
+ with col2:
468
+ st.markdown("""
469
+ <h2 class="rahyar-title">رهیار 🚖</h2>
470
+ <p class="rahyar-subtitle">همراه سفرهای درون‌شهری شما، راهی مطمئن، راهی روشن، رهیار</p>
471
+ """, unsafe_allow_html=True)
472
+
473
+ st.markdown("### سناریوی تحقیق")
474
+
475
+ st.markdown("""
476
+ <div style="background-color: #f8f9fa; padding: 15px; border-radius: 10px;">
477
+ <p>فرض کنید یک اپلیکیشن حمل‌ونقل آنلاین ایرانی به اسم رهیار طراحی شده، چیزی شبیه اسنپ یا تپسی، اما جدیدتر و با شعار "همراه سفرهای شما، راهی مطمئن، راهی روشن، رهیار"</p>
478
+ <p>در یک روز عادی، شما قصد دارید برای سفری از طریق این پلتفرم اقدام کنید..</p>
479
+ <p>با کلیک بر دکمه ادامه، اطلاعات سفر را مشاهده کنید.</p>
480
+ </div>
481
+ """, unsafe_allow_html=True)
482
+
483
+ if st.button("ادامه", key="continue_btn", type="primary"):
484
+ st.session_state.current_page = "map_view"
485
+ st.rerun()
486
+
487
+ def map_view():
488
+ """نمایش نقشه و قیمت"""
489
+ col1, col2 = st.columns([1, 4])
490
+ with col1:
491
+ st.image("https://via.placeholder.com/80/6a0dad/FFFFFF?text=LOGO", width=80)
492
+ with col2:
493
+ st.markdown("""
494
+ <h2 style="color: #6a0dad; margin: 0;">رهیار 🚖</h2>
495
+ <p style="color: #6a0dad; margin: 0;">همراه سفرهای درون‌شهری شما، راهی مطمئن، راهی روشن، رهیار</p>
496
+ """, unsafe_allow_html=True)
497
+
498
+ st.markdown("### مسیر سفر شما")
499
+ folium_static(create_ride_map(), width=1000 if st.session_state.is_desktop else 800,
500
+ height=500 if st.session_state.is_desktop else 400)
501
+
502
+ # قیمت
503
+ st.markdown(f"""
504
+ <div class="price-container">
505
+ <div style="display: flex; justify-content: space-between; align-items: center;">
506
+ <span>راهیار <span style="background-color: #e6e6fa; color: #6a0dad; padding: 2px 8px; border-radius: 12px; font-size: 14px;">به صرفه</span></span>
507
+ <span class="rahyar-price">{st.session_state.price:,} تومان</span>
508
+ </div>
509
+ </div>
510
+ """, unsafe_allow_html=True)
511
+
512
+ show_explanation(st.session_state.scenario_type)
513
+
514
+ # دکمه‌ها
515
+ col1, col2 = st.columns(2)
516
+ with col1:
517
+ if st.button("درخواست راهیار", key="accept_btn", use_container_width=True):
518
+ st.session_state.price_accepted = 1
519
+ st.session_state.current_page = "attention_check1"
520
+ st.rerun()
521
+
522
+ with col2:
523
+ if st.button("رد قیمت", key="reject_btn", use_container_width=True):
524
+ st.session_state.price_accepted = 0
525
+ st.session_state.current_page = "attention_check1"
526
+ st.rerun()
527
+
528
 
529
  def attention_check1():
530
  """سوال توجه اول (رادیویی ساده)"""
 
606
  else:
607
  st.session_state.current_page = "attention_check2"
608
  st.rerun()
609
+
610
+ def explanation_questions():
611
+ """سوالات درباره توضیحات قیمت"""
612
+ st.markdown("""
613
+ <style>
614
+ /* تضمین رنگ متن برای تمام سطوح */
615
+ .st-ec, .st-ed, .st-ee, .st-ef, .st-eg, .st-eh, .st-ei, .st-ej {
616
+ color: black !important;
617
+ }
618
+ </style>
619
+ """, unsafe_allow_html=True)
620
+ st.markdown("### 📋 سوالات تکمیلی")
621
 
622
+ # سوال اول
623
+ explanation_received = st.radio(
624
+ "آیا برای قیمت پیشنهادی این سفر، توضیحی به شما ارائه شد؟",
625
+ ["بله", "خیر"],
626
+ index=None,
627
+ key="explanation_received"
628
+ )
629
+
630
+ # سوال دوم (فقط اگر پاسخ بله باشد)
631
+ explanation_type = None
632
+ if explanation_received == "بله":
633
+ explanation_type = st.radio(
634
+ "اگر توضیحی دریافت کردید، این توضیح بیشتر به کدام مورد شباهت داشت؟",
635
+ [
636
+ "بر اساس عواملی که در قیمت‌گذاری لحاظ شده‌اند",
637
+ "شامل سناریوهای جایگزین که می‌توانستند قیمت متفاوتی ایجاد کنند",
638
+ "توضیحی دریافت نکردم"
639
+ ],
640
+ index=None,
641
+ key="explanation_type"
642
+ )
643
+
644
+ if st.button("ثبت پاسخ‌ها", type="primary"):
645
+ if explanation_received is None:
646
+ st.warning("لطفاً به سوال اول پاسخ دهید")
647
+ elif explanation_received == "بله" and explanation_type is None:
648
+ st.warning("لطفاً به سوال دوم پاسخ دهید")
649
+ else:
650
+ st.session_state.explanation_data = {
651
+ "explanation_received": explanation_received,
652
+ "explanation_type": explanation_type if explanation_received == "بله" else "N/A"
653
+ }
654
+
655
+ # جمع‌آوری تمام داده‌ها برای ذخیره‌سازی
656
+ end_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
657
+ start_time = datetime.strptime(st.session_state.start_time, "%Y-%m-%d %H:%M:%S")
658
+ completion_time = (datetime.now() - start_time).total_seconds()
659
+
660
+ save_data = {
661
+ "start_time": st.session_state.start_time,
662
+ "end_time": end_time,
663
+ "completion_time": completion_time,
664
+ "scenario_type": st.session_state.scenario_type,
665
+ "price": st.session_state.price,
666
+ "user_contact": st.session_state.get("user_contact", ""),
667
+ "price_accepted": st.session_state.get("price_accepted", 0),
668
+ "attention_check1": st.session_state.get("attention_check1", None),
669
+ "attention_check2": st.session_state.get("attention_check2", None),
670
+ "explanation_received": explanation_received,
671
+ "explanation_type": explanation_type if explanation_received == "بله" else "N/A",
672
+ **st.session_state.demographic_data
673
+ }
674
+
675
+ # اضافه کردن پاسخ‌های لیکرت
676
+ for q in st.session_state.all_questions:
677
+ save_data[q["label"]] = st.session_state.get(q["key"], None)
678
+
679
+ if save_to_sheet(save_data):
680
+ st.session_state.current_page = "thank_you"
681
+ st.rerun()
682
+ else:
683
+ st.error("خطا در ذخیره‌سازی داده‌ها. لطفاً دوباره تلاش کنید.")
684
+
685
+
686
+ def thank_you_page():
687
+ """صفحه تشکر"""
688
+ st.success("✅ پاسخ‌های شما با موفقیت ثبت شد. با تشکر از مشارکت شما در این تحقیق!")
689
+ st.balloons()
690
+
691
+ if st.button("بازگشت به ابتدا"):
692
+ st.session_state.clear()
693
+ st.rerun()
694
 
695
  # ========== مدیریت وضعیت و صفحه‌بندی ==========
696
  def main():