Shrey0405 commited on
Commit
75cb91d
·
verified ·
1 Parent(s): 8ec3d63

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +96 -263
src/streamlit_app.py CHANGED
@@ -1,284 +1,117 @@
1
  import streamlit as st
2
- import math
3
 
4
- # Enhanced Custom CSS - Reduced spacing, professional profile layout
 
 
 
 
 
 
 
5
  st.markdown("""
6
- <style>
7
- @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
8
-
9
  .main {
10
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
11
- padding: 1rem 2rem 2rem;
12
- font-family: 'Poppins', sans-serif;
13
- }
14
-
15
- .stApp {
16
- background-color: transparent;
17
- }
18
-
19
- h1 {
20
- color: white !important;
21
- font-weight: 700;
22
- text-align: center;
23
- text-shadow: 0 4px 8px rgba(0,0,0,0.3);
24
- margin: 1rem 0 1rem 0 !important;
25
- font-size: 2.5rem;
26
- }
27
-
28
- .profile-section {
29
- background: rgba(255, 255, 255, 0.95);
30
- padding: 2rem;
31
- border-radius: 24px;
32
- box-shadow: 0 25px 50px rgba(0,0,0,0.15);
33
- backdrop-filter: blur(15px);
34
- border: 1px solid rgba(255,255,255,0.3);
35
- margin-bottom: 1rem;
36
- }
37
-
38
- .section-header {
39
- color: #333;
40
- font-weight: 600;
41
- font-size: 1.4rem;
42
- margin-bottom: 1.5rem;
43
- display: flex;
44
- align-items: center;
45
- gap: 0.5rem;
46
- }
47
-
48
- .stTextInput > div > div > input,
49
- .stNumberInput > div > div > input {
50
- border-radius: 12px !important;
51
- border: 2px solid #e1e5e9 !important;
52
- padding: 14px 16px !important;
53
- font-size: 16px !important;
54
- transition: all 0.3s ease !important;
55
- height: 50px !important;
56
- }
57
-
58
- .stTextInput > div > div > input:focus,
59
- .stNumberInput > div > div > input:focus {
60
- border-color: #667eea !important;
61
- box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.15) !important;
62
- }
63
-
64
- .stSelectbox > div > div > select,
65
- .stMultiSelect > div > div > select {
66
- border-radius: 12px !important;
67
- border: 2px solid #e1e5e9 !important;
68
- padding: 14px 16px !important;
69
- font-size: 16px !important;
70
  }
71
-
72
- .stButton > button {
73
- background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
74
- color: white !important;
75
- border: none !important;
76
- border-radius: 16px !important;
77
- padding: 16px 40px !important;
78
- font-weight: 600 !important;
79
- font-size: 17px !important;
80
- transition: all 0.3s ease !important;
81
- box-shadow: 0 12px 35px rgba(17, 153, 142, 0.4) !important;
82
- width: 100% !important;
83
- height: 56px !important;
84
- }
85
-
86
- .stButton > button:hover {
87
- transform: translateY(-3px) !important;
88
- box-shadow: 0 18px 45px rgba(17, 153, 142, 0.6) !important;
89
- }
90
-
91
- .bmi-result {
92
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
93
- color: white;
94
- padding: 2.5rem;
95
- border-radius: 24px;
96
- text-align: center;
97
- box-shadow: 0 25px 60px rgba(102, 126, 234, 0.4);
98
- font-size: 1.4rem;
99
- font-weight: 700;
100
- margin: 2rem 0;
101
- }
102
-
103
- .bmi-category {
104
- font-size: 2.2rem;
105
- margin: 1rem 0;
106
- text-shadow: 0 4px 12px rgba(0,0,0,0.3);
107
- }
108
-
109
- .bmi-underweight { background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); }
110
- .bmi-normal { background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); }
111
- .bmi-overweight { background: linear-gradient(135deg, #fa709a 0%, #fee140 100%); }
112
- .bmi-obese { background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%); }
113
-
114
- .metric-card {
115
- background: linear-gradient(135deg, #f8f9ff 0%, #e8f4ff 100%);
116
- padding: 1.8rem;
117
- border-radius: 20px;
118
- text-align: center;
119
- box-shadow: 0 15px 40px rgba(0,0,0,0.08);
120
- border: 1px solid rgba(102, 126, 234, 0.1);
121
- transition: transform 0.3s ease;
122
- }
123
-
124
- .metric-card:hover {
125
- transform: translateY(-5px);
126
- }
127
-
128
- .progress-bar {
129
- background: #e1e5e9;
130
- height: 10px;
131
  border-radius: 10px;
132
- overflow: hidden;
133
- margin: 1rem 0;
134
- }
135
-
136
- .progress-fill {
137
- height: 100%;
138
- border-radius: 10px;
139
- transition: width 1s ease;
140
- }
141
-
142
- .error-message {
143
- background: linear-gradient(90deg, #fee 0%, #fcc 100%);
144
- color: #c33;
145
- padding: 1.2rem;
146
- border-radius: 16px;
147
- border-left: 5px solid #c33;
148
- margin: 1rem 0;
149
  }
150
-
151
- /* Remove default margins */
152
- section[data-testid="stHorizontalBlock"] {
153
- margin-bottom: 0.5rem !important;
 
154
  }
155
-
156
- .stMarkdown {
157
- margin-bottom: 1rem !important;
158
- }
159
- </style>
160
- """, unsafe_allow_html=True)
161
-
162
- # Reduced title spacing
163
- st.title("💪 Smart Fitness Profile")
164
-
165
- # Single unified profile section
166
- st.markdown('<div class="profile-section">', unsafe_allow_html=True)
167
-
168
- # Multi-column layout for better space usage
169
- col1, col2 = st.columns(2)
170
 
171
- with col1:
172
- st.markdown('<div class="section-header">👤 Personal Details</div>', unsafe_allow_html=True)
173
- name = st.text_input("👤 Full Name *", key="name")
174
- height_cm = st.number_input("📏 Height (cm) *", min_value=0.1, value=170.0, step=1.0, key="height")
175
- weight_kg = st.number_input("⚖️ Weight (kg) *", min_value=0.1, value=70.0, step=0.1, key="weight")
176
- age = st.number_input("🎂 Age", min_value=12, max_value=100, value=30, key="age")
177
 
178
- with col2:
179
- st.markdown('<div class="section-header">🎯 Fitness Goals</div>', unsafe_allow_html=True)
180
- goal = st.selectbox("🏆 Primary Goal",
181
- ["Build Muscle", "Weight Loss", "Strength Gain", "Abs Building", "Flexible", "Endurance"],
182
- key="goal")
183
- fitness_level = st.selectbox("📊 Experience Level",
184
- ["Beginner", "Intermediate", "Advanced", "Elite"],
185
- key="level")
186
- equipment = st.multiselect("🛠️ Available Equipment",
187
- ["Dumbbells", "Resistance Band", "Yoga Mat", "No Equipment",
188
- "Barbell", "Pull-up Bar", "Treadmill", "Kettlebells"],
189
- default=["No Equipment"], key="equip")
190
- weekly_hours = st.slider("⏰ Weekly Training Hours", 0, 20, 5, key="hours")
191
-
192
- st.markdown('</div>', unsafe_allow_html=True)
193
-
194
- # Calculate Button
195
- if st.button("🚀 Generate Fitness Profile", key="calc"):
196
- if not name.strip() or height_cm <= 0 or weight_kg <= 0:
197
- st.error("❌ Please fill all required fields with valid values (name, height, weight).")
198
  else:
199
- height_m = height_cm / 100
200
- bmi = round(weight_kg / (height_m ** 2), 2)
201
-
202
- if bmi < 18.5:
203
- category = "Underweight"
204
- cat_class = "bmi-underweight"
205
- elif 18.5 <= bmi < 25:
206
- category = "Normal"
207
- cat_class = "bmi-normal"
208
- elif 25 <= bmi < 30:
209
- category = "Overweight"
210
- cat_class = "bmi-overweight"
211
- else:
212
- category = "Obese"
213
- cat_class = "bmi-obese"
214
-
215
- st.session_state.profile = {
216
- 'name': name, 'bmi': bmi, 'category': category, 'cat_class': cat_class,
217
- 'height': height_cm, 'weight': weight_kg, 'age': age, 'goal': goal,
218
- 'level': fitness_level, 'equipment': equipment, 'hours': weekly_hours
219
- }
220
 
221
- # Results Section - Innovative modules
222
- if 'profile' in st.session_state:
223
- profile = st.session_state.profile
224
-
225
- # Main BMI Result
226
- bmi_html = f'''
227
- <div class="bmi-result {profile['cat_class']}">
228
- <div style="font-size: 3rem; margin-bottom: 0.5rem;">{profile['bmi']}</div>
229
- <div class="bmi-category">{profile['category']}</div>
230
- <div style="font-size: 1.1rem; opacity: 0.9;">
231
- {profile['height']}cm | {profile['weight']}kg | {profile['age']}yrs
232
- </div>
233
- </div>
234
- '''
235
- st.markdown(bmi_html, unsafe_allow_html=True)
236
 
237
- # Progress Metrics Row 1
238
- col1, col2, col3 = st.columns(3)
239
  with col1:
240
- st.markdown('<div class="metric-card">', unsafe_allow_html=True)
241
- st.metric("🥗 BMI Goal", "22.0", profile['bmi'])
242
- st.markdown('<div class="progress-bar"><div class="progress-fill" style="width: 60%; background: linear-gradient(90deg, #4facfe, #00f2fe);"></div></div>', unsafe_allow_html=True)
243
- st.markdown('</div>', unsafe_allow_html=True)
244
-
245
  with col2:
246
- st.markdown('<div class="metric-card">', unsafe_allow_html=True)
247
- st.metric("💪 Training Intensity", profile['hours'], "10h")
248
- st.markdown('</div>', unsafe_allow_html=True)
 
249
 
250
- with col3:
251
- st.markdown('<div class="metric-card">', unsafe_allow_html=True)
252
- st.metric("🎯 Experience", profile['level'])
253
- st.markdown('</div>', unsafe_allow_html=True)
254
 
255
- # Profile Summary Row 2
256
- col4, col5 = st.columns(2)
257
- with col4:
258
- st.markdown('<div class="metric-card">', unsafe_allow_html=True)
259
- st.markdown(f"**👤 {profile['name'].title()}**")
260
- st.markdown(f"**🏆 Goal:** {profile['goal']}")
261
- st.markdown(f"**🛠️ Equipment:** {', '.join(profile['equipment'])}")
262
- st.markdown('</div>', unsafe_allow_html=True)
263
 
264
- with col5:
265
- st.markdown('<div class="metric-card">', unsafe_allow_html=True)
266
- st.markdown("### 💡 Quick Recommendations")
267
- recs = {
268
- 'Underweight': "Increase calories, strength training",
269
- 'Normal': "Maintain balance, progressive overload",
270
- 'Overweight': "Cardio + strength, calorie deficit",
271
- 'Obese': "Consult doctor, sustainable changes"
272
- }
273
- st.markdown(f"**{recs[profile['category']]}**")
274
- st.markdown('</div>', unsafe_allow_html=True)
275
 
276
- # Footer
277
- st.markdown("---")
278
- st.markdown("""
279
- <div style='text-align: center; color: rgba(255,255,255,0.9); font-size: 0.95rem; padding: 1rem;'>
280
- 🚀 Smart Fitness Profile | Powered by Streamlit | Deployed on Hugging Face Spaces
281
- </div>
282
- """, unsafe_allow_html=True)
283
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
 
 
 
 
1
  import streamlit as st
 
2
 
3
+ # --- Page Configuration ---
4
+ st.set_page_config(
5
+ page_title="FitPulse Profile Builder",
6
+ page_icon="💪",
7
+ layout="centered"
8
+ )
9
+
10
+ # --- Custom CSS for "App-like" Feel ---
11
  st.markdown("""
12
+ <style>
 
 
13
  .main {
14
+ background-color: #f8f9fa;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  }
16
+ .stButton>button {
17
+ width: 100%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  border-radius: 10px;
19
+ height: 3em;
20
+ background-color: #FF4B4B;
21
+ color: white;
22
+ font-weight: bold;
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  }
24
+ .css-1544g2n {
25
+ padding: 2rem 1rem;
26
+ border-radius: 15px;
27
+ background-color: white;
28
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
29
  }
30
+ </style>
31
+ """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
+ def calculate_bmi(weight, height_cm):
34
+ height_m = height_cm / 100
35
+ bmi = weight / (height_m ** 2)
36
+ return round(bmi, 2)
 
 
37
 
38
+ def get_bmi_category(bmi):
39
+ if bmi < 18.5:
40
+ return "Underweight", "blue"
41
+ elif 18.5 <= bmi < 24.9:
42
+ return "Normal", "green"
43
+ elif 25 <= bmi < 29.9:
44
+ return "Overweight", "orange"
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  else:
46
+ return "Obese", "red"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
+ # --- Header ---
49
+ st.title("💪 FitPulse")
50
+ st.subheader("Create Your Fitness Profile")
51
+ st.write("Complete the details below to unlock your personalized health metrics.")
52
+
53
+ # --- Form Section ---
54
+ with st.form("fitness_form"):
55
+ st.markdown("### 👤 Personal Information")
56
+ name = st.text_input("Full Name", placeholder="e.g. John Doe")
 
 
 
 
 
 
57
 
58
+ col1, col2 = st.columns(2)
 
59
  with col1:
60
+ height = st.number_input("Height (cm)", min_value=0.0, step=0.1, help="Enter your height in centimeters")
 
 
 
 
61
  with col2:
62
+ weight = st.number_input("Weight (kg)", min_value=0.0, step=0.1, help="Enter your weight in kilograms")
63
+
64
+ st.markdown("---")
65
+ st.markdown("### 🎯 Fitness Details")
66
 
67
+ goal = st.selectbox("Fitness Goal",
68
+ ["Build Muscle", "Weight Loss", "Strength Gain", "Abs Building", "Flexible"])
 
 
69
 
70
+ level = st.select_slider("Fitness Level",
71
+ options=["Beginner", "Intermediate", "Advanced"])
 
 
 
 
 
 
72
 
73
+ equipment = st.multiselect("Available Equipment",
74
+ ["Dumbbells", "Resistance Band", "Yoga Mat", "Barbell", "Kettlebell", "No Equipment"],
75
+ default=["No Equipment"])
 
 
 
 
 
 
 
 
76
 
77
+ submitted = st.form_submit_button("Generate My Profile")
 
 
 
 
 
 
78
 
79
+ # --- Logic & Output ---
80
+ if submitted:
81
+ # Validation
82
+ if not name:
83
+ st.error("Please enter your name.")
84
+ elif height <= 0 or weight <= 0:
85
+ st.error("Height and Weight must be greater than zero.")
86
+ else:
87
+ # Calculations
88
+ bmi_val = calculate_bmi(weight, height)
89
+ category, color = get_bmi_category(bmi_val)
90
+
91
+ # Results Display
92
+ st.success(f"Profile Created Successfully for **{name}**!")
93
+
94
+ res_col1, res_col2 = st.columns(2)
95
+
96
+ with res_col1:
97
+ st.metric(label="Calculated BMI", value=f"{bmi_val}")
98
+
99
+ with res_col2:
100
+ st.markdown(f"**Category:**")
101
+ if category == "Normal":
102
+ st.info(f"✨ {category}")
103
+ elif category == "Underweight":
104
+ st.warning(f"⚠️ {category}")
105
+ else:
106
+ st.error(f"🚨 {category}")
107
+
108
+ # Summary Table
109
+ st.markdown("### 📋 Profile Summary")
110
+ data = {
111
+ "Detail": ["Goal", "Level", "Equipment"],
112
+ "Value": [goal, level, ", ".join(equipment)]
113
+ }
114
+ st.table(data)
115
 
116
+ # --- Footer ---
117
+ st.caption("Data is processed locally and not stored. Stay healthy!")