GSMEthesis commited on
Commit
1fd1c1c
·
verified ·
1 Parent(s): 0c3f896

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +133 -84
app.py CHANGED
@@ -773,7 +773,7 @@ body, .stApp {
773
 
774
  # ========== توابع اصلی ==========
775
  def enhanced_likert_scale(question_data):
776
- """لیکرت اسکیل با محدوده 0 تا scale و عدم نمایش نقطه برای 0"""
777
  question = question_data["question"]
778
  key = question_data["key"]
779
  scale = question_data["scale"]
@@ -787,97 +787,126 @@ def enhanced_likert_scale(question_data):
787
  st.markdown(f"<div style='text-align:center; font-weight:bold; margin-bottom:15px;'>{question}</div>",
788
  unsafe_allow_html=True)
789
 
790
- # ایجاد خط و نقاط با HTML/CSS
791
  scale_html = f"""
792
- <style>
793
- @font-face {{
794
- font-family: 'Vazir';
795
- src: url('https://cdn.fontcdn.ir/Font/Persian/Vazir/Vazir-Bold.woff2') format('woff2');
796
- }}
797
- .likert-line {{
798
- width: 80%;
799
- height: 2px;
800
- background: #6a0dad;
801
- margin: 0 auto;
802
- position: relative;
803
- display: flex;
804
- justify-content: space-between;
805
- direction: rtl;
806
- }}
807
- .likert-dot {{
808
- width: 18px;
809
- height: 18px;
810
- border-radius: 50%;
811
- background: white;
812
- border: 2px solid #6a0dad;
813
- position: relative;
814
- top: -9px;
815
- }}
816
- .likert-dot.active {{
817
- background: #6a0dad;
818
- }}
819
- .likert-labels {{
820
- width: 80%;
821
- margin: 5px auto 15px;
822
- display: flex;
823
- justify-content: space-between;
824
- direction: rtl;
825
- font-size: 14px;
826
- font-family: 'Vazir', sans-serif;
827
- font-weight: bold;
828
- color: #6a0dad;
829
- }}
830
- .separator-line {{
831
- width: 80%;
832
- height: 2px;
833
- background: #6a0dad;
834
- margin: 20px auto;
835
- }}
836
- @media (max-width: 768px) {{
837
  .likert-line {{
838
- width: 90%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
839
  }}
840
  .likert-labels {{
841
- width: 90%;
 
 
 
 
842
  }}
843
- }}
844
- </style>
845
-
846
- <div>
847
- <div class="likert-labels">
848
- <span>{labels[0]}</span>
849
- <span>{labels[1]}</span>
 
 
 
 
850
  </div>
851
- <div class="likert-line">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
852
  """
853
-
854
- # اضافه کردن نقاط فقط برای مقادیر 1 تا scale
855
- current_value = st.session_state.get(key, 0)
856
- for i in range(1, scale+1):
857
- value = i # مقادیر از 1 تا scale
858
- active_class = "active" if current_value == value else ""
859
- scale_html += f"<div class='likert-dot {active_class}'></div>"
860
 
861
- scale_html += "</div></div>"
 
862
 
863
- # نمایش کامپوننت HTML
864
- components.html(scale_html, height=60)
865
-
866
- # ورودی عددی با محدوده 0 تا scale (0 قابل انتخاب است)
867
- value = st.number_input(
868
- "پاسخ شما (از 1 تا 7):",
869
- min_value=0, # 0 مجاز است
870
- max_value=scale,
871
- value=st.session_state.get(key, 0),
872
- step=1,
873
- key=f"{key}_input",
874
- placeholder="0 (پاسخ نداده) یا 1-7",
875
- format="%d",
876
- on_change=lambda: st.session_state.update({key: st.session_state[f"{key}_input"]})
877
- )
878
-
879
- # خط جداکننده بنفش
880
- # خط جداکننده بنفش - تعریف استایل و HTML با هم
881
  st.markdown("""
882
  <style>
883
  .likert-separator {
@@ -889,8 +918,28 @@ def enhanced_likert_scale(question_data):
889
  </style>
890
  <div class="likert-separator"></div>
891
  """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
892
 
893
- return st.session_state.get(key)
 
 
 
 
 
 
 
 
 
 
894
 
895
 
896
  def create_ride_map():
 
773
 
774
  # ========== توابع اصلی ==========
775
  def enhanced_likert_scale(question_data):
776
+ """لیکرت اسکیل کاملاً تعاملی با هماهنگی کامل بین نقاط و عدد"""
777
  question = question_data["question"]
778
  key = question_data["key"]
779
  scale = question_data["scale"]
 
787
  st.markdown(f"<div style='text-align:center; font-weight:bold; margin-bottom:15px;'>{question}</div>",
788
  unsafe_allow_html=True)
789
 
790
+ # ایجاد HTML/JS برای بخش تعاملی
791
  scale_html = f"""
792
+ <!DOCTYPE html>
793
+ <html>
794
+ <head>
795
+ <style>
796
+ @font-face {{
797
+ font-family: 'Vazir';
798
+ src: url('https://cdn.fontcdn.ir/Font/Persian/Vazir/Vazir-Bold.woff2') format('woff2');
799
+ }}
800
+ .likert-container {{
801
+ width: 80%;
802
+ margin: 0 auto;
803
+ direction: rtl;
804
+ font-family: 'Vazir', sans-serif;
805
+ }}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
806
  .likert-line {{
807
+ width: 100%;
808
+ height: 2px;
809
+ background: #6a0dad;
810
+ position: relative;
811
+ margin: 20px 0;
812
+ }}
813
+ .likert-dot {{
814
+ width: 18px;
815
+ height: 18px;
816
+ border-radius: 50%;
817
+ background: white;
818
+ border: 2px solid #6a0dad;
819
+ position: absolute;
820
+ top: -9px;
821
+ cursor: pointer;
822
+ transform: translateX(-50%);
823
+ transition: all 0.3s ease;
824
+ }}
825
+ .likert-dot:hover {{
826
+ transform: translateX(-50%) scale(1.2);
827
+ }}
828
+ .likert-dot.active {{
829
+ background: #6a0dad;
830
  }}
831
  .likert-labels {{
832
+ display: flex;
833
+ justify-content: space-between;
834
+ margin-bottom: 10px;
835
+ font-weight: bold;
836
+ color: #6a0dad;
837
  }}
838
+ </style>
839
+ </head>
840
+ <body>
841
+ <div class="likert-container">
842
+ <div class="likert-labels">
843
+ <span>{labels[1]}</span>
844
+ <span>{labels[0]}</span>
845
+ </div>
846
+ <div class="likert-line" id="likert-line">
847
+ <!-- نقاط به صورت پویا اضافه خواهند شد -->
848
+ </div>
849
  </div>
850
+
851
+ <script>
852
+ // تنظیمات اولیه
853
+ const line = document.getElementById('likert-line');
854
+ const scale = {scale};
855
+ const currentValue = {st.session_state.get(key, 0)};
856
+
857
+ // ایجاد نقاط
858
+ line.innerHTML = '';
859
+
860
+ for (let i = 1; i <= scale; i++) {{
861
+ const dot = document.createElement('div');
862
+ dot.className = 'likert-dot' + (i === currentValue ? ' active' : '');
863
+ dot.dataset.value = i;
864
+
865
+ // محاسبه موقعیت نقطه
866
+ const position = 100 - ((i - 1) / (scale - 1)) * 100;
867
+ dot.style.left = `${{position}}%`;
868
+
869
+ // رویداد کلیک
870
+ dot.addEventListener('click', () => {{
871
+ // به روزرسانی ظاهر
872
+ document.querySelectorAll('.likert-dot').forEach(d => {{
873
+ d.classList.remove('active');
874
+ }});
875
+ dot.classList.add('active');
876
+
877
+ // ارسال مقدار به Streamlit
878
+ const value = parseInt(dot.dataset.value);
879
+ window.parent.postMessage({{
880
+ type: 'likertValueChanged',
881
+ key: '{key}',
882
+ value: value
883
+ }}, '*');
884
+ }});
885
+
886
+ line.appendChild(dot);
887
+ }}
888
+ </script>
889
+ </body>
890
+ </html>
891
  """
 
 
 
 
 
 
 
892
 
893
+ # نمایش کامپوننت
894
+ html(scale_html, height=120)
895
 
896
+ # ایجاد input عددی هماهنگ
897
+ col1, col2 = st.columns([3, 1])
898
+ with col2:
899
+ value = st.number_input(
900
+ "مقدار انتخاب شده:",
901
+ min_value=0,
902
+ max_value=scale,
903
+ value=st.session_state.get(key, 0),
904
+ step=1,
905
+ key=f"{key}_input",
906
+ on_change=lambda: st.session_state.update({key: st.session_state[f"{key}_input"]})
907
+ )
908
+
909
+ # خط جداکننده
 
 
 
 
910
  st.markdown("""
911
  <style>
912
  .likert-separator {
 
918
  </style>
919
  <div class="likert-separator"></div>
920
  """, unsafe_allow_html=True)
921
+
922
+ # گوش دادن به تغییرات از JS
923
+ js_value = st.session_state.get(f"js_{key}")
924
+ if js_value is not None:
925
+ st.session_state[key] = js_value
926
+ st.session_state[f"{key}_input"] = js_value
927
+ del st.session_state[f"js_{key}"]
928
+ st.experimental_rerun()
929
+
930
+ return st.session_state.get(key, 0)
931
 
932
+ # کد JavaScript برای ارتباط با Streamlit (در بخش head صفحه اصلی)
933
+ st.markdown("""
934
+ <script>
935
+ window.addEventListener('message', function(event) {
936
+ if (event.data.type === 'likertValueChanged') {
937
+ const {key, value} = event.data;
938
+ Streamlit.setComponentValue({key: `js_${key}`, value: value});
939
+ }
940
+ });
941
+ </script>
942
+ """, unsafe_allow_html=True)
943
 
944
 
945
  def create_ride_map():