Maryam Ilka commited on
Commit
63a38c5
·
verified ·
1 Parent(s): ff958b9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -125
app.py CHANGED
@@ -15,7 +15,7 @@ st.set_page_config(layout="wide", page_title="راهیار - تحلیل انصا
15
  SHEET_ID = "1mmdWAyOCYq4yXMgP53Duq712AnlqZWLkfIo76JqM7wM"
16
  SHEET_NAME = "Condition1"
17
 
18
- # ========== استایل‌های سفارشی ==========
19
  st.markdown("""
20
  <style>
21
  @font-face {
@@ -28,7 +28,8 @@ st.markdown("""
28
  --text: #333333;
29
  --background: #ffffff;
30
  --border: #dddddd;
31
- --input-bg: #ffffff; /* تغییر به سفید */
 
32
  }
33
 
34
  * {
@@ -37,13 +38,18 @@ st.markdown("""
37
  direction: rtl !important;
38
  }
39
 
40
- /* تنظیمات اصلی استریملیت */
41
  body, .stApp, [data-testid="stAppViewContainer"] {
42
  background-color: var(--background) !important;
43
  color: var(--text) !important;
44
  }
45
 
46
- /* باکس‌های ورودی - اصلاح شده */
 
 
 
 
 
47
  .stTextInput input,
48
  .stNumberInput input,
49
  .stSelectbox select,
@@ -59,7 +65,7 @@ st.markdown("""
59
  padding: 8px 12px !important;
60
  }
61
 
62
- /* دکمه‌های اصلی - اصلاح شده */
63
  .stButton>button,
64
  [data-testid="baseButton-primary"],
65
  .accept-btn,
@@ -70,10 +76,9 @@ st.markdown("""
70
  border-radius: 8px !important;
71
  padding: 10px 20px !important;
72
  font-weight: bold !important;
73
- margin-top: 20px !important;
74
  }
75
 
76
- /* دکمه‌های ثانویه - اصلاح شده */
77
  .stFormSubmitButton>button,
78
  [data-testid="baseButton-secondary"],
79
  .reject-btn {
@@ -85,25 +90,6 @@ st.markdown("""
85
  font-weight: bold !important;
86
  }
87
 
88
- /* دکمه‌های درخواست و رد راهیار - اصلاح شده */
89
- .accept-btn, .reject-btn {
90
- color: white !important;
91
- background-color: var(--primary) !important;
92
- border: none !important;
93
- }
94
-
95
- .reject-btn {
96
- color: var(--primary) !important;
97
- background-color: white !important;
98
- border: 1px solid var(--primary) !important;
99
- }
100
-
101
- /* سوالات - اصلاح شده */
102
- .stMarkdown h2, .stMarkdown h3, .stMarkdown p,
103
- .stRadio > label, .stCheckbox > label {
104
- color: var(--text) !important;
105
- }
106
-
107
  /* کامپوننت‌های سفارشی */
108
  .rahyar-header {
109
  background-color: var(--primary) !important;
@@ -115,7 +101,7 @@ st.markdown("""
115
  }
116
 
117
  .price-container {
118
- background-color: #f8f9fa !important;
119
  border-radius: 10px !important;
120
  padding: 15px !important;
121
  margin: 15px 0 !important;
@@ -128,7 +114,7 @@ st.markdown("""
128
  font-weight: bold !important;
129
  }
130
 
131
- /* استایل explanation در مپ ویو */
132
  .explanation-title {
133
  color: var(--primary) !important;
134
  font-weight: bold !important;
@@ -137,20 +123,17 @@ st.markdown("""
137
  }
138
 
139
  .explanation-item {
140
- background-color: #f8f9fa !important;
141
  border-radius: 8px !important;
142
  padding: 12px 15px !important;
143
  margin: 8px 0 !important;
144
  border-right: 3px solid var(--primary) !important;
145
- color: var(--text) !important;
146
  }
147
 
148
- /* غیرفعال کردن کامل تم تاریک */
149
- .st-emotion-cache-1v0mbdj,
150
- .st-emotion-cache-1pbsqtx,
151
- .st-emotion-cache-1y4p8pa {
152
  color: var(--text) !important;
153
- background-color: var(--background) !important;
154
  }
155
 
156
  /* تنظیمات مخصوص دسکتاپ */
@@ -328,34 +311,12 @@ def welcome_page():
328
  def user_contact():
329
  """راه ارتباطی ساده"""
330
  st.markdown("""
331
- <style>
332
- /* استایل برای فیلدهای ورودی */
333
- .stTextInput input,
334
- .stNumberInput input,
335
- .stSelectbox select {
336
- color: #333333 !important;
337
- background-color: white !important;
338
- }
339
-
340
- /* استایل برای placeholder (متن راهنما) */
341
- .stTextInput input::placeholder,
342
- .stNumberInput input::placeholder {
343
- color: #333333 !important;
344
- opacity: 1 !important; /* برای اطمینان از نمایش کامل رنگ */
345
- }
346
 
347
- /* استایل برای select box */
348
- .stSelectbox select option {
349
- color: #333333 !important;
350
- background-color: white !important;
351
- }
352
- </style>
353
-
354
- <div style="text-align: center; margin-bottom: 30px;">
355
- <h3>📩 راه ارتباطی شما (اختیاری)</h3>
356
- <p>در صورت تمایل به شرکت در قرعه‌کشی می‌توانید آیدی تلگرام، شماره تماس یا ایمیل خود را وارد کنید:</p>
357
- </div>
358
- """, unsafe_allow_html=True)
359
  contact_info = st.text_input(
360
  "راه ارتباطی (اختیاری)",
361
  placeholder="مثال: @username یا 09123456789 یا example@email.com",
@@ -369,8 +330,9 @@ def user_contact():
369
 
370
  def demographic_form():
371
  """فرم اطلاعات دموگرافیک"""
372
- with st.form("demographic"):
373
- st.header("📝 اطلاعات دموگرافیک")
 
374
  age = st.number_input("سن", min_value=18, max_value=100)
375
  gender = st.selectbox("جنسیت", ["مرد", "زن", "سایر"])
376
  education = st.selectbox("تحصیلات", ["دیپلم", "لیسانس", "فوق لیسانس", "دکترا"])
@@ -391,10 +353,7 @@ def scenario_explanation():
391
  """توضیح سناریو"""
392
  col1, col2 = st.columns([1, 4])
393
  with col1:
394
- try:
395
- st.image("rahyar.png", width=80)
396
- except:
397
- st.image("https://via.placeholder.com/80/6a0dad/FFFFFF?text=LOGO", width=80)
398
  with col2:
399
  st.markdown("""
400
  <h2 style="color: #6a0dad; margin: 0;">رهیار 🚖</h2>
@@ -403,22 +362,13 @@ def scenario_explanation():
403
 
404
  st.markdown("### سناریوی تحقیق")
405
 
406
- if st.session_state.scenario_type == "control":
407
- st.markdown("""
408
- <div style="background-color: #f8f9fa; padding: 15px; border-radius: 10px;">
409
- <p>فرض کنید یک اپلیکیشن حمل‌ونقل آنلاین ایرانی به اسم رهیار طراحی شده، چیزی شبیه اسنپ یا تپسی، اما جدیدتر و با شعار "همراه سفرهای شما، راهی مطمئن، راهی روشن، رهیار"</p>
410
- <p>در یک روز عادی، شما قصد دارید برای سفری از طریق این پلتفرم اقدام کنید..</p>
411
- <p>با کلیک بر دکمه ادامه، اطلاعات سفر را مشاهده کنید.</p>
412
- </div>
413
- """, unsafe_allow_html=True)
414
- else:
415
- st.markdown("""
416
- <div style="background-color: #f8f9fa; padding: 15px; border-radius: 10px;">
417
- <p>فرض کنید یک اپلیکیشن حمل‌ونقل آنلاین ایرانی به اسم رهیار طراحی شده، چیزی شبیه اسنپ یا تپسی، اما جدیدتر و با شعار "همراه سفرهای شما، راهی مطمئن، راهی روشن، رهیار"</p>
418
- <p>در یک روز عادی، شما قصد دارید برای سفری از طریق این پلتفرم اقدام کنید..</p>
419
- <p>با کلیک بر دکمه ادامه، اطلاعات سفر را مشاهده کنید.</p>
420
- </div>
421
- """, unsafe_allow_html=True)
422
 
423
  if st.button("ادامه", key="continue_btn", type="primary"):
424
  st.session_state.current_page = "map_view"
@@ -428,10 +378,7 @@ def map_view():
428
  """نمایش نقشه و قیمت"""
429
  col1, col2 = st.columns([1, 4])
430
  with col1:
431
- try:
432
- st.image("rahyar.png", width=80)
433
- except:
434
- st.image("https://via.placeholder.com/80/6a0dad/FFFFFF?text=LOGO", width=80)
435
  with col2:
436
  st.markdown("""
437
  <h2 style="color: #6a0dad; margin: 0;">رهیار 🚖</h2>
@@ -439,15 +386,14 @@ def map_view():
439
  """, unsafe_allow_html=True)
440
 
441
  st.markdown("### مسیر سفر شما")
442
- map_obj = create_ride_map()
443
- folium_static(map_obj, width=1000 if st.session_state.is_desktop else 800,
444
  height=500 if st.session_state.is_desktop else 400)
445
 
446
  # قیمت
447
  st.markdown(f"""
448
  <div class="price-container">
449
  <div style="display: flex; justify-content: space-between; align-items: center;">
450
- <span>راهیار <span class="rahyar-badge">به صرفه</span></span>
451
  <span class="rahyar-price">{st.session_state.price:,} تومان</span>
452
  </div>
453
  </div>
@@ -455,27 +401,23 @@ def map_view():
455
 
456
  show_explanation(st.session_state.scenario_type)
457
 
458
- # دکمه‌های جدید با استایل‌های سفارشی
459
  col1, col2 = st.columns(2)
460
  with col1:
461
- if st.button("درخواست راهیار", key="accept_btn",
462
- help="برای تایید قیمت و درخواست سفر کلیک کنید",
463
- use_container_width=True):
464
  st.session_state.price_accepted = 1
465
  st.session_state.current_page = "transparency_questions"
466
  st.rerun()
467
 
468
  with col2:
469
- if st.button("رد قیمت", key="reject_btn",
470
- help="برای رد قیمت و ادامه به سوالات کلیک کنید",
471
- use_container_width=True):
472
  st.session_state.price_accepted = 0
473
  st.session_state.current_page = "transparency_questions"
474
  st.rerun()
475
 
476
  def transparency_questions():
477
  """سوالات شفافیت"""
478
- st.header("📊")
479
  st.markdown("**لطفاً میزان موافقت خود با جملات زیر را مشخص کنید:**")
480
 
481
  questions = [
@@ -488,8 +430,7 @@ def transparency_questions():
488
 
489
  answers = []
490
  for i, question in enumerate(questions):
491
- answer = create_likert_question(question, f"transparency_q{i}")
492
- answers.append(answer)
493
 
494
  if None not in answers:
495
  st.session_state.transparency_answers = answers
@@ -499,7 +440,7 @@ def transparency_questions():
499
 
500
  def fairness_questions():
501
  """سوالات انصاف"""
502
- st.header("📊")
503
  st.markdown("**لطفاً میزان موافقت خود با جملات زیر را مشخص کنید:**")
504
 
505
  questions = [
@@ -513,8 +454,7 @@ def fairness_questions():
513
 
514
  answers = []
515
  for i, question in enumerate(questions):
516
- answer = create_likert_question(question, f"fairness_q{i}")
517
- answers.append(answer)
518
 
519
  if None not in answers:
520
  st.session_state.fairness_answers = answers
@@ -524,17 +464,11 @@ def fairness_questions():
524
 
525
  def explanation_questions():
526
  """سوالات درباره توضیحات قیمت"""
527
- st.header("📋سوالات تکمیلی")
528
 
529
  # سوال اول
530
- st.markdown("""
531
- <div class="survey-section">
532
- <h3>آیا برای قیمت پیشنهادی این سفر، توضیحی به شما ارائه شد؟</h3>
533
- </div>
534
- """, unsafe_allow_html=True)
535
-
536
  explanation_received = st.radio(
537
- "",
538
  ["بله", "خیر"],
539
  index=None,
540
  key="explanation_received"
@@ -543,14 +477,8 @@ def explanation_questions():
543
  # سوال دوم (فقط اگر پاسخ بله باشد)
544
  explanation_type = None
545
  if explanation_received == "بله":
546
- st.markdown("""
547
- <div class="survey-section">
548
- <h3>اگر توضیحی دریافت کردید، این توضیح بیشتر به کدام مورد شباهت داشت؟</h3>
549
- </div>
550
- """, unsafe_allow_html=True)
551
-
552
  explanation_type = st.radio(
553
- "",
554
  [
555
  "بر اساس عواملی که در قیمت‌گذاری لحاظ شده‌اند",
556
  "شامل سناریوهای جایگزین که می‌توانستند قیمت متفاوتی ایجاد کنند",
@@ -571,19 +499,16 @@ def explanation_questions():
571
  "explanation_type": explanation_type if explanation_received == "بله" else "N/A"
572
  }
573
 
574
- all_data = {
575
  "scenario_type": st.session_state.scenario_type,
576
  "price": st.session_state.price,
577
  **st.session_state.demographic_data,
578
- "user_contact": st.session_state.get("user_contact", ""),
579
  "transparency_answers": st.session_state.transparency_answers,
580
  "fairness_answers": st.session_state.fairness_answers,
581
  "explanation_received": explanation_received,
582
  "explanation_type": explanation_type if explanation_received == "بله" else "N/A",
583
  "price_accepted": st.session_state.get("price_accepted", 0)
584
- }
585
-
586
- if save_to_sheet(all_data):
587
  st.session_state.current_page = "thank_you"
588
  st.rerun()
589
  else:
@@ -600,7 +525,7 @@ def thank_you_page():
600
 
601
  # ========== مدیریت وضعیت و صفحه‌بندی ==========
602
  def main():
603
- # تشخیص دستگاه با استفاده از st.query_params جدید
604
  user_agent = st.query_params.get("user_agent", [""])[0]
605
  st.session_state.is_desktop = "mobile" not in user_agent.lower()
606
 
 
15
  SHEET_ID = "1mmdWAyOCYq4yXMgP53Duq712AnlqZWLkfIo76JqM7wM"
16
  SHEET_NAME = "Condition1"
17
 
18
+ # ========== استایل‌های سفارشی یکپارچه ==========
19
  st.markdown("""
20
  <style>
21
  @font-face {
 
28
  --text: #333333;
29
  --background: #ffffff;
30
  --border: #dddddd;
31
+ --input-bg: #ffffff;
32
+ --secondary-bg: #f8f9fa;
33
  }
34
 
35
  * {
 
38
  direction: rtl !important;
39
  }
40
 
41
+ /* تنظیمات اصلی */
42
  body, .stApp, [data-testid="stAppViewContainer"] {
43
  background-color: var(--background) !important;
44
  color: var(--text) !important;
45
  }
46
 
47
+ /* تمام متن‌ها */
48
+ h1, h2, h3, h4, h5, h6, p, div, span, label {
49
+ color: var(--text) !important;
50
+ }
51
+
52
+ /* باکس‌های ورودی */
53
  .stTextInput input,
54
  .stNumberInput input,
55
  .stSelectbox select,
 
65
  padding: 8px 12px !important;
66
  }
67
 
68
+ /* دکمه اصلی (بنفش) */
69
  .stButton>button,
70
  [data-testid="baseButton-primary"],
71
  .accept-btn,
 
76
  border-radius: 8px !important;
77
  padding: 10px 20px !important;
78
  font-weight: bold !important;
 
79
  }
80
 
81
+ /* دکمه ثانویه (سفید با حاشیه بنفش) */
82
  .stFormSubmitButton>button,
83
  [data-testid="baseButton-secondary"],
84
  .reject-btn {
 
90
  font-weight: bold !important;
91
  }
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  /* کامپوننت‌های سفارشی */
94
  .rahyar-header {
95
  background-color: var(--primary) !important;
 
101
  }
102
 
103
  .price-container {
104
+ background-color: var(--secondary-bg) !important;
105
  border-radius: 10px !important;
106
  padding: 15px !important;
107
  margin: 15px 0 !important;
 
114
  font-weight: bold !important;
115
  }
116
 
117
+ /* توضیحات */
118
  .explanation-title {
119
  color: var(--primary) !important;
120
  font-weight: bold !important;
 
123
  }
124
 
125
  .explanation-item {
126
+ background-color: var(--secondary-bg) !important;
127
  border-radius: 8px !important;
128
  padding: 12px 15px !important;
129
  margin: 8px 0 !important;
130
  border-right: 3px solid var(--primary) !important;
 
131
  }
132
 
133
+ /* پیام موفقیت */
134
+ .stAlert .stSuccess {
 
 
135
  color: var(--text) !important;
136
+ background-color: #f0fff0 !important;
137
  }
138
 
139
  /* تنظیمات مخصوص دسکتاپ */
 
311
  def user_contact():
312
  """راه ارتباطی ساده"""
313
  st.markdown("""
314
+ <div style="text-align: center; margin-bottom: 30px;">
315
+ <h3>📩 راه ارتباطی شما (اختیاری)</h3>
316
+ <p>در صورت تمایل به شرکت در قرعه‌کشی می‌توانید آیدی تلگرام�� شماره تماس یا ایمیل خود را وارد کنید:</p>
317
+ </div>
318
+ """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
319
 
 
 
 
 
 
 
 
 
 
 
 
 
320
  contact_info = st.text_input(
321
  "راه ارتباطی (اختیاری)",
322
  placeholder="مثال: @username یا 09123456789 یا example@email.com",
 
330
 
331
  def demographic_form():
332
  """فرم اطلاعات دموگرافیک"""
333
+ st.markdown("### 📝 اطلاعات دموگرافیک")
334
+
335
+ with st.form("demographic_form"):
336
  age = st.number_input("سن", min_value=18, max_value=100)
337
  gender = st.selectbox("جنسیت", ["مرد", "زن", "سایر"])
338
  education = st.selectbox("تحصیلات", ["دیپلم", "لیسانس", "فوق لیسانس", "دکترا"])
 
353
  """توضیح سناریو"""
354
  col1, col2 = st.columns([1, 4])
355
  with col1:
356
+ st.image("https://via.placeholder.com/80/6a0dad/FFFFFF?text=LOGO", width=80)
 
 
 
357
  with col2:
358
  st.markdown("""
359
  <h2 style="color: #6a0dad; margin: 0;">رهیار 🚖</h2>
 
362
 
363
  st.markdown("### سناریوی تحقیق")
364
 
365
+ st.markdown("""
366
+ <div style="background-color: #f8f9fa; padding: 15px; border-radius: 10px;">
367
+ <p>فرض کنید یک اپلیکیشن حمل‌ونقل آنلاین ایرانی به اسم رهیار طراحی شده، چیزی شبیه اسنپ یا تپسی، اما جدیدتر و با شعار "همراه سفرهای شما، راهی مطمئن، راهی روشن، رهیار"</p>
368
+ <p>در یک روز عادی، شما قصد دارید برای سفری از طریق این پلتفرم اقدام کنید..</p>
369
+ <p>با کلیک بر دکمه ادامه، اطلاعات سفر را مشاهده کنید.</p>
370
+ </div>
371
+ """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
372
 
373
  if st.button("ادامه", key="continue_btn", type="primary"):
374
  st.session_state.current_page = "map_view"
 
378
  """نمایش نقشه و قیمت"""
379
  col1, col2 = st.columns([1, 4])
380
  with col1:
381
+ st.image("https://via.placeholder.com/80/6a0dad/FFFFFF?text=LOGO", width=80)
 
 
 
382
  with col2:
383
  st.markdown("""
384
  <h2 style="color: #6a0dad; margin: 0;">رهیار 🚖</h2>
 
386
  """, unsafe_allow_html=True)
387
 
388
  st.markdown("### مسیر سفر شما")
389
+ folium_static(create_ride_map(), width=1000 if st.session_state.is_desktop else 800,
 
390
  height=500 if st.session_state.is_desktop else 400)
391
 
392
  # قیمت
393
  st.markdown(f"""
394
  <div class="price-container">
395
  <div style="display: flex; justify-content: space-between; align-items: center;">
396
+ <span>راهیار <span style="background-color: #e6e6fa; color: #6a0dad; padding: 2px 8px; border-radius: 12px; font-size: 14px;">به صرفه</span></span>
397
  <span class="rahyar-price">{st.session_state.price:,} تومان</span>
398
  </div>
399
  </div>
 
401
 
402
  show_explanation(st.session_state.scenario_type)
403
 
404
+ # دکمه‌ها
405
  col1, col2 = st.columns(2)
406
  with col1:
407
+ if st.button("درخواست راهیار", key="accept_btn", use_container_width=True):
 
 
408
  st.session_state.price_accepted = 1
409
  st.session_state.current_page = "transparency_questions"
410
  st.rerun()
411
 
412
  with col2:
413
+ if st.button("رد قیمت", key="reject_btn", use_container_width=True):
 
 
414
  st.session_state.price_accepted = 0
415
  st.session_state.current_page = "transparency_questions"
416
  st.rerun()
417
 
418
  def transparency_questions():
419
  """سوالات شفافیت"""
420
+ st.markdown("### 📊 سوالات شفافیت")
421
  st.markdown("**لطفاً میزان موافقت خود با جملات زیر را مشخص کنید:**")
422
 
423
  questions = [
 
430
 
431
  answers = []
432
  for i, question in enumerate(questions):
433
+ answers.append(create_likert_question(question, f"transparency_q{i}"))
 
434
 
435
  if None not in answers:
436
  st.session_state.transparency_answers = answers
 
440
 
441
  def fairness_questions():
442
  """سوالات انصاف"""
443
+ st.markdown("### 📊 سوالات انصاف")
444
  st.markdown("**لطفاً میزان موافقت خود با جملات زیر را مشخص کنید:**")
445
 
446
  questions = [
 
454
 
455
  answers = []
456
  for i, question in enumerate(questions):
457
+ answers.append(create_likert_question(question, f"fairness_q{i}"))
 
458
 
459
  if None not in answers:
460
  st.session_state.fairness_answers = answers
 
464
 
465
  def explanation_questions():
466
  """سوالات درباره توضیحات قیمت"""
467
+ st.markdown("### 📋 سوالات تکمیلی")
468
 
469
  # سوال اول
 
 
 
 
 
 
470
  explanation_received = st.radio(
471
+ "آیا برای قیمت پیشنهادی این سفر، توضیحی به شما ارائه شد؟",
472
  ["بله", "خیر"],
473
  index=None,
474
  key="explanation_received"
 
477
  # سوال دوم (فقط اگر پاسخ بله باشد)
478
  explanation_type = None
479
  if explanation_received == "بله":
 
 
 
 
 
 
480
  explanation_type = st.radio(
481
+ "اگر توضیحی دریافت کردید، این توضیح بیشتر به کدام مورد شباهت داشت؟",
482
  [
483
  "بر اساس عواملی که در قیمت‌گذاری لحاظ شده‌اند",
484
  "شامل سناریوهای جایگزین که می‌توانستند قیمت متفاوتی ایجاد کنند",
 
499
  "explanation_type": explanation_type if explanation_received == "بله" else "N/A"
500
  }
501
 
502
+ if save_to_sheet({
503
  "scenario_type": st.session_state.scenario_type,
504
  "price": st.session_state.price,
505
  **st.session_state.demographic_data,
 
506
  "transparency_answers": st.session_state.transparency_answers,
507
  "fairness_answers": st.session_state.fairness_answers,
508
  "explanation_received": explanation_received,
509
  "explanation_type": explanation_type if explanation_received == "بله" else "N/A",
510
  "price_accepted": st.session_state.get("price_accepted", 0)
511
+ }):
 
 
512
  st.session_state.current_page = "thank_you"
513
  st.rerun()
514
  else:
 
525
 
526
  # ========== مدیریت وضعیت و صفحه‌بندی ==========
527
  def main():
528
+ # تشخیص دستگاه
529
  user_agent = st.query_params.get("user_agent", [""])[0]
530
  st.session_state.is_desktop = "mobile" not in user_agent.lower()
531