Iammcqwory commited on
Commit
f8c06d8
·
verified ·
1 Parent(s): c46f409

Upload 22 files

Browse files
AfyaMindSpace/.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
AfyaMindSpace/.vscode/settings.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ {
2
+ "files.associations": {
3
+ "plyconfig.json": "jsonc"
4
+ }
5
+ }
AfyaMindSpace/README.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: AfyaMindSpace
3
+ emoji: 🏢
4
+ colorFrom: blue
5
+ colorTo: green
6
+ sdk: streamlit
7
+ sdk_version: 1.41.1
8
+ app_file: app.py
9
+ pinned: false
10
+ short_description: AfyaMind Space is a technology-driven mental health platform
11
+ ---
12
+
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
AfyaMindSpace/__pycache__/analytics.cpython-313.pyc ADDED
Binary file (20.3 kB). View file
 
AfyaMindSpace/__pycache__/auth.cpython-313.pyc ADDED
Binary file (10 kB). View file
 
AfyaMindSpace/__pycache__/chatbox.cpython-313.pyc ADDED
Binary file (11.7 kB). View file
 
AfyaMindSpace/__pycache__/forum.cpython-313.pyc ADDED
Binary file (23.3 kB). View file
 
AfyaMindSpace/__pycache__/goals.cpython-313.pyc ADDED
Binary file (28.3 kB). View file
 
AfyaMindSpace/__pycache__/meditation.cpython-313.pyc ADDED
Binary file (19.8 kB). View file
 
AfyaMindSpace/analytics.py ADDED
@@ -0,0 +1,469 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import altair as alt
4
+ from datetime import datetime, timedelta
5
+ import numpy as np
6
+
7
+ # Function to analyze mood data and provide insights
8
+ def analyze_mood_data(mood_history):
9
+ if not mood_history:
10
+ return None
11
+
12
+ # Convert mood history to DataFrame
13
+ mood_df = pd.DataFrame(mood_history, columns=["timestamp", "mood"])
14
+ mood_df["date"] = pd.to_datetime(mood_df["timestamp"]).dt.date
15
+ mood_df["time"] = pd.to_datetime(mood_df["timestamp"]).dt.time
16
+ mood_df["hour"] = pd.to_datetime(mood_df["timestamp"]).dt.hour
17
+ mood_df["day_of_week"] = pd.to_datetime(mood_df["timestamp"]).dt.day_name()
18
+
19
+ # Basic statistics
20
+ total_entries = len(mood_df)
21
+ unique_days = mood_df["date"].nunique()
22
+ most_common_mood = mood_df["mood"].value_counts().index[0]
23
+ mood_counts = mood_df["mood"].value_counts().to_dict()
24
+
25
+ # Time patterns
26
+ mood_by_hour = mood_df.groupby("hour")["mood"].value_counts().unstack().fillna(0)
27
+ mood_by_day = mood_df.groupby("day_of_week")["mood"].value_counts().unstack().fillna(0)
28
+
29
+ # Reorder days of week
30
+ days_order = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
31
+ if not mood_by_day.empty:
32
+ mood_by_day = mood_by_day.reindex(days_order)
33
+
34
+ # Mood transitions (how mood changes from one entry to the next)
35
+ mood_transitions = {}
36
+ if len(mood_df) > 1:
37
+ for i in range(len(mood_df) - 1):
38
+ current_mood = mood_df.iloc[i]["mood"]
39
+ next_mood = mood_df.iloc[i+1]["mood"]
40
+
41
+ if current_mood not in mood_transitions:
42
+ mood_transitions[current_mood] = {}
43
+
44
+ if next_mood not in mood_transitions[current_mood]:
45
+ mood_transitions[current_mood][next_mood] = 0
46
+
47
+ mood_transitions[current_mood][next_mood] += 1
48
+
49
+ # Mood streaks
50
+ mood_streaks = {}
51
+ current_streak = 1
52
+ current_mood = None
53
+
54
+ for mood in mood_df["mood"]:
55
+ if mood == current_mood:
56
+ current_streak += 1
57
+ else:
58
+ if current_mood is not None:
59
+ if current_mood not in mood_streaks or current_streak > mood_streaks[current_mood]:
60
+ mood_streaks[current_mood] = current_streak
61
+
62
+ current_mood = mood
63
+ current_streak = 1
64
+
65
+ # Add the last streak
66
+ if current_mood is not None and (current_mood not in mood_streaks or current_streak > mood_streaks[current_mood]):
67
+ mood_streaks[current_mood] = current_streak
68
+
69
+ # Recent trends (last 7 days)
70
+ today = datetime.now().date()
71
+ one_week_ago = today - timedelta(days=7)
72
+ recent_df = mood_df[pd.to_datetime(mood_df["date"]) >= pd.Timestamp(one_week_ago)]
73
+
74
+ recent_mood_counts = recent_df["mood"].value_counts().to_dict() if not recent_df.empty else {}
75
+ recent_most_common = recent_df["mood"].value_counts().index[0] if not recent_df.empty and len(recent_df["mood"].value_counts()) > 0 else None
76
+
77
+ # Calculate mood variability (how much the mood changes)
78
+ mood_values = {
79
+ "happy": 5,
80
+ "calm": 4,
81
+ "anxious": 3,
82
+ "sad": 2,
83
+ "angry": 1
84
+ }
85
+
86
+ mood_df["mood_value"] = mood_df["mood"].map(mood_values)
87
+ mood_variability = mood_df["mood_value"].std() if len(mood_df) > 1 else 0
88
+
89
+ # Prepare data for visualization
90
+ mood_over_time = mood_df[["date", "mood"]].copy()
91
+ mood_over_time["date"] = pd.to_datetime(mood_over_time["date"])
92
+
93
+ return {
94
+ "total_entries": total_entries,
95
+ "unique_days": unique_days,
96
+ "most_common_mood": most_common_mood,
97
+ "mood_counts": mood_counts,
98
+ "mood_by_hour": mood_by_hour,
99
+ "mood_by_day": mood_by_day,
100
+ "mood_transitions": mood_transitions,
101
+ "mood_streaks": mood_streaks,
102
+ "recent_mood_counts": recent_mood_counts,
103
+ "recent_most_common": recent_most_common,
104
+ "mood_variability": mood_variability,
105
+ "mood_over_time": mood_over_time
106
+ }
107
+
108
+ # Function to generate insights based on mood analysis
109
+ def generate_mood_insights(analysis):
110
+ if not analysis:
111
+ return []
112
+
113
+ insights = []
114
+
115
+ # Most common mood
116
+ insights.append(f"Your most common mood is '{analysis['most_common_mood']}'. You've recorded this mood {analysis['mood_counts'].get(analysis['most_common_mood'], 0)} times.")
117
+
118
+ # Recent trends
119
+ if analysis["recent_most_common"]:
120
+ if analysis["recent_most_common"] == analysis["most_common_mood"]:
121
+ insights.append(f"Your mood has been consistent. '{analysis['recent_most_common']}' is your most common mood recently and overall.")
122
+ else:
123
+ insights.append(f"Your mood has shifted recently. While your overall most common mood is '{analysis['most_common_mood']}', recently you've been feeling '{analysis['recent_most_common']}' more often.")
124
+
125
+ # Mood variability
126
+ if analysis["mood_variability"] < 0.5:
127
+ insights.append("Your mood has been very stable, with little variation.")
128
+ elif analysis["mood_variability"] < 1.0:
129
+ insights.append("Your mood shows moderate variation, which is typical.")
130
+ else:
131
+ insights.append("Your mood shows significant variation, with frequent changes.")
132
+
133
+ # Time patterns
134
+ if not analysis["mood_by_hour"].empty:
135
+ # Find the hour with the most positive moods (happy, calm)
136
+ # Handle both DataFrame and Series cases
137
+ positive_moods = analysis["mood_by_hour"].get(["happy", "calm"], pd.Series(0))
138
+ if not positive_moods.empty:
139
+ # Check if positive_moods is a Series or DataFrame
140
+ if isinstance(positive_moods, pd.Series):
141
+ best_hour = positive_moods.idxmax() if not positive_moods.empty else None
142
+ else: # It's a DataFrame
143
+ best_hour = positive_moods.sum(axis=1).idxmax() if not positive_moods.sum(axis=1).empty else None
144
+
145
+ if best_hour is not None:
146
+ am_pm = "AM" if best_hour < 12 else "PM"
147
+ hour_12 = best_hour % 12
148
+ if hour_12 == 0:
149
+ hour_12 = 12
150
+ insights.append(f"You tend to feel your best around {hour_12} {am_pm}.")
151
+
152
+ # Find the hour with the most negative moods (sad, angry, anxious)
153
+ negative_moods = analysis["mood_by_hour"].get(["sad", "angry", "anxious"], pd.Series(0))
154
+ if not negative_moods.empty:
155
+ # Check if negative_moods is a Series or DataFrame
156
+ if isinstance(negative_moods, pd.Series):
157
+ worst_hour = negative_moods.idxmax() if not negative_moods.empty else None
158
+ else: # It's a DataFrame
159
+ worst_hour = negative_moods.sum(axis=1).idxmax() if not negative_moods.sum(axis=1).empty else None
160
+
161
+ if worst_hour is not None:
162
+ am_pm = "AM" if worst_hour < 12 else "PM"
163
+ hour_12 = worst_hour % 12
164
+ if hour_12 == 0:
165
+ hour_12 = 12
166
+ insights.append(f"You tend to experience more challenging emotions around {hour_12} {am_pm}.")
167
+
168
+ # Day of week patterns
169
+ if not analysis["mood_by_day"].empty:
170
+ # Find the day with the most positive moods
171
+ positive_moods = analysis["mood_by_day"].get(["happy", "calm"], pd.Series(0))
172
+ if not positive_moods.empty:
173
+ # Check if positive_moods is a Series or DataFrame
174
+ if isinstance(positive_moods, pd.Series):
175
+ best_day = positive_moods.idxmax() if not positive_moods.empty else None
176
+ else: # It's a DataFrame
177
+ best_day = positive_moods.sum(axis=1).idxmax() if not positive_moods.sum(axis=1).empty else None
178
+
179
+ if best_day is not None:
180
+ insights.append(f"{best_day} tends to be your best day of the week emotionally.")
181
+
182
+ # Find the day with the most negative moods
183
+ negative_moods = analysis["mood_by_day"].get(["sad", "angry", "anxious"], pd.Series(0))
184
+ if not negative_moods.empty:
185
+ # Check if negative_moods is a Series or DataFrame
186
+ if isinstance(negative_moods, pd.Series):
187
+ worst_day = negative_moods.idxmax() if not negative_moods.empty else None
188
+ else: # It's a DataFrame
189
+ worst_day = negative_moods.sum(axis=1).idxmax() if not negative_moods.sum(axis=1).empty else None
190
+
191
+ if worst_day is not None:
192
+ insights.append(f"{worst_day} tends to be your most challenging day emotionally.")
193
+
194
+ # Mood transitions
195
+ if analysis["mood_transitions"]:
196
+ for mood, transitions in analysis["mood_transitions"].items():
197
+ most_common_next = max(transitions.items(), key=lambda x: x[1])[0] if transitions else None
198
+ if most_common_next and most_common_next != mood:
199
+ insights.append(f"When you feel '{mood}', you most often transition to feeling '{most_common_next}' next.")
200
+
201
+ # Mood streaks
202
+ if analysis["mood_streaks"]:
203
+ longest_streak_mood = max(analysis["mood_streaks"].items(), key=lambda x: x[1])[0]
204
+ longest_streak = analysis["mood_streaks"][longest_streak_mood]
205
+ if longest_streak > 1:
206
+ insights.append(f"Your longest mood streak was feeling '{longest_streak_mood}' for {longest_streak} consecutive recordings.")
207
+
208
+ # Consistency in tracking
209
+ tracking_consistency = (analysis["unique_days"] / 7) * 100 if analysis["unique_days"] <= 7 else 100
210
+ if tracking_consistency < 50:
211
+ insights.append("You're tracking your mood occasionally. More consistent tracking will provide better insights.")
212
+ elif tracking_consistency < 80:
213
+ insights.append("You're tracking your mood fairly regularly. Keep it up!")
214
+ else:
215
+ insights.append("You're very consistent with tracking your mood, which gives you the most accurate insights.")
216
+
217
+ return insights
218
+
219
+ # Function to recommend actions based on mood analysis
220
+ def recommend_mood_actions(analysis):
221
+ if not analysis:
222
+ return {}
223
+
224
+ recommendations = {
225
+ "happy": [
226
+ "Maintain your positive state by engaging in activities you enjoy",
227
+ "Share your positive energy with others through connection",
228
+ "Practice gratitude to reinforce positive emotions",
229
+ "Document what contributed to your happiness for future reference"
230
+ ],
231
+ "calm": [
232
+ "Continue mindfulness practices that help maintain this balanced state",
233
+ "Use this calm state for creative or focused work",
234
+ "Practice deep breathing to maintain your sense of calm",
235
+ "Engage in gentle movement like walking or stretching"
236
+ ],
237
+ "anxious": [
238
+ "Try grounding techniques like the 5-4-3-2-1 sensory exercise",
239
+ "Practice deep breathing or progressive muscle relaxation",
240
+ "Limit caffeine and other stimulants",
241
+ "Break large tasks into smaller, manageable steps",
242
+ "Consider talking to someone you trust about your feelings"
243
+ ],
244
+ "sad": [
245
+ "Engage in light physical activity like walking",
246
+ "Reach out to a supportive friend or family member",
247
+ "Practice self-compassion and avoid self-criticism",
248
+ "Listen to uplifting music or watch a comforting show",
249
+ "Set small, achievable goals for the day"
250
+ ],
251
+ "angry": [
252
+ "Take a timeout and practice deep breathing",
253
+ "Engage in physical activity to release tension",
254
+ "Write down your thoughts to process them",
255
+ "Use 'I' statements when communicating your feelings",
256
+ "Practice progressive muscle relaxation to release physical tension"
257
+ ]
258
+ }
259
+
260
+ # Determine which recommendations to prioritize based on recent moods
261
+ prioritized_recommendations = {}
262
+
263
+ if analysis["recent_mood_counts"]:
264
+ # Sort recent moods by frequency
265
+ sorted_moods = sorted(analysis["recent_mood_counts"].items(), key=lambda x: x[1], reverse=True)
266
+
267
+ # Add recommendations for the top 2 most frequent moods
268
+ for mood, count in sorted_moods[:2]:
269
+ if mood in recommendations:
270
+ prioritized_recommendations[mood] = recommendations[mood]
271
+ else:
272
+ # If no recent data, use overall most common mood
273
+ most_common = analysis["most_common_mood"]
274
+ if most_common in recommendations:
275
+ prioritized_recommendations[most_common] = recommendations[most_common]
276
+
277
+ return prioritized_recommendations
278
+
279
+ # UI components for mood analytics
280
+ def mood_analytics_page():
281
+ st.subheader("Mood Analytics & Insights")
282
+
283
+ if not st.session_state.get("mood_history", []):
284
+ st.warning("No mood data available. Start tracking your mood to see analytics.")
285
+ return
286
+
287
+ # Analyze mood data
288
+ analysis = analyze_mood_data(st.session_state.mood_history)
289
+
290
+ if not analysis:
291
+ st.warning("Not enough mood data to generate analytics.")
292
+ return
293
+
294
+ # Display basic statistics
295
+ st.write(f"**Total mood entries:** {analysis['total_entries']}")
296
+ st.write(f"**Days with mood tracking:** {analysis['unique_days']}")
297
+ st.write(f"**Most common mood:** {analysis['most_common_mood']}")
298
+
299
+ # Mood distribution chart
300
+ st.subheader("Mood Distribution")
301
+
302
+ mood_counts_df = pd.DataFrame({
303
+ "mood": list(analysis["mood_counts"].keys()),
304
+ "count": list(analysis["mood_counts"].values())
305
+ })
306
+
307
+ # Define color scale for moods
308
+ color_scale = {
309
+ "happy": "#FFD700", # Gold
310
+ "calm": "#90EE90", # Light green
311
+ "anxious": "#ADD8E6", # Light blue
312
+ "sad": "#A9A9A9", # Dark gray
313
+ "angry": "#FF6347" # Tomato
314
+ }
315
+
316
+ chart = alt.Chart(mood_counts_df).mark_bar().encode(
317
+ x=alt.X("mood:N", title="Mood", sort=list(color_scale.keys())),
318
+ y=alt.Y("count:Q", title="Frequency"),
319
+ color=alt.Color("mood:N", scale=alt.Scale(
320
+ domain=list(color_scale.keys()),
321
+ range=list(color_scale.values())
322
+ ))
323
+ ).properties(
324
+ title="Overall Mood Distribution",
325
+ width=600,
326
+ height=300
327
+ )
328
+
329
+ st.altair_chart(chart, use_container_width=True)
330
+
331
+ # Mood over time
332
+ st.subheader("Mood Over Time")
333
+
334
+ # Prepare data for time series chart
335
+ mood_time_df = analysis["mood_over_time"].copy()
336
+
337
+ # Create a time series chart
338
+ time_chart = alt.Chart(mood_time_df).mark_line(point=True).encode(
339
+ x=alt.X("date:T", title="Date"),
340
+ y=alt.Y("mood:N", title="Mood", sort=list(reversed(list(color_scale.keys())))),
341
+ color=alt.Color("mood:N", scale=alt.Scale(
342
+ domain=list(color_scale.keys()),
343
+ range=list(color_scale.values())
344
+ ))
345
+ ).properties(
346
+ title="Mood Trends Over Time",
347
+ width=600,
348
+ height=300
349
+ )
350
+
351
+ st.altair_chart(time_chart, use_container_width=True)
352
+
353
+ # Mood by time of day
354
+ st.subheader("Mood Patterns by Time of Day")
355
+
356
+ if not analysis["mood_by_hour"].empty:
357
+ # Convert the mood by hour data to a format suitable for Altair
358
+ hour_data = []
359
+ for hour, moods in analysis["mood_by_hour"].iterrows():
360
+ for mood, count in moods.items():
361
+ if count > 0: # Only include non-zero counts
362
+ hour_data.append({
363
+ "hour": hour,
364
+ "mood": mood,
365
+ "count": count
366
+ })
367
+
368
+ hour_df = pd.DataFrame(hour_data)
369
+
370
+ if not hour_df.empty:
371
+ hour_chart = alt.Chart(hour_df).mark_bar().encode(
372
+ x=alt.X("hour:O", title="Hour of Day"),
373
+ y=alt.Y("count:Q", title="Frequency"),
374
+ color=alt.Color("mood:N", scale=alt.Scale(
375
+ domain=list(color_scale.keys()),
376
+ range=list(color_scale.values())
377
+ )),
378
+ tooltip=["hour", "mood", "count"]
379
+ ).properties(
380
+ title="Mood Distribution by Hour of Day",
381
+ width=600,
382
+ height=300
383
+ )
384
+
385
+ st.altair_chart(hour_chart, use_container_width=True)
386
+ else:
387
+ st.write("Not enough data to show mood patterns by time of day.")
388
+ else:
389
+ st.write("Not enough data to show mood patterns by time of day.")
390
+
391
+ # Mood by day of week
392
+ st.subheader("Mood Patterns by Day of Week")
393
+
394
+ if not analysis["mood_by_day"].empty:
395
+ # Convert the mood by day data to a format suitable for Altair
396
+ day_data = []
397
+ for day, moods in analysis["mood_by_day"].iterrows():
398
+ for mood, count in moods.items():
399
+ if count > 0: # Only include non-zero counts
400
+ day_data.append({
401
+ "day": day,
402
+ "mood": mood,
403
+ "count": count
404
+ })
405
+
406
+ day_df = pd.DataFrame(day_data)
407
+
408
+ if not day_df.empty:
409
+ # Define the order of days
410
+ days_order = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
411
+
412
+ day_chart = alt.Chart(day_df).mark_bar().encode(
413
+ x=alt.X("day:N", title="Day of Week", sort=days_order),
414
+ y=alt.Y("count:Q", title="Frequency"),
415
+ color=alt.Color("mood:N", scale=alt.Scale(
416
+ domain=list(color_scale.keys()),
417
+ range=list(color_scale.values())
418
+ )),
419
+ tooltip=["day", "mood", "count"]
420
+ ).properties(
421
+ title="Mood Distribution by Day of Week",
422
+ width=600,
423
+ height=300
424
+ )
425
+
426
+ st.altair_chart(day_chart, use_container_width=True)
427
+ else:
428
+ st.write("Not enough data to show mood patterns by day of week.")
429
+ else:
430
+ st.write("Not enough data to show mood patterns by day of week.")
431
+
432
+ # Insights
433
+ st.subheader("Mood Insights")
434
+
435
+ insights = generate_mood_insights(analysis)
436
+
437
+ for insight in insights:
438
+ st.markdown(f"- {insight}")
439
+
440
+ # Recommendations
441
+ st.subheader("Recommended Actions")
442
+
443
+ recommendations = recommend_mood_actions(analysis)
444
+
445
+ if recommendations:
446
+ for mood, actions in recommendations.items():
447
+ with st.expander(f"When you're feeling {mood}"):
448
+ for action in actions:
449
+ st.markdown(f"- {action}")
450
+ else:
451
+ st.write("Continue tracking your mood to receive personalized recommendations.")
452
+
453
+ # Export data option
454
+ st.subheader("Export Your Mood Data")
455
+
456
+ if st.button("Export Mood Data as CSV"):
457
+ # Create a DataFrame from mood history
458
+ export_df = pd.DataFrame(st.session_state.mood_history, columns=["timestamp", "mood"])
459
+
460
+ # Convert to CSV
461
+ csv = export_df.to_csv(index=False)
462
+
463
+ # Create a download button
464
+ st.download_button(
465
+ label="Download CSV",
466
+ data=csv,
467
+ file_name="mood_history.csv",
468
+ mime="text/csv"
469
+ )
AfyaMindSpace/app.py ADDED
@@ -0,0 +1,685 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from datetime import datetime, timedelta
3
+ import random
4
+ import pandas as pd
5
+ import altair as alt
6
+
7
+ # Import custom modules
8
+ from auth import auth_page
9
+ from forum import forum_page
10
+ from meditation import meditation_page
11
+ from goals import goals_page
12
+ from analytics import mood_analytics_page
13
+ from chatbox import create_chat_interface
14
+
15
+ # Set page configuration
16
+ st.set_page_config(
17
+ page_title="AfyaMind Space",
18
+ page_icon="🧠",
19
+ layout="wide",
20
+ initial_sidebar_state="expanded"
21
+ )
22
+
23
+ # Custom CSS for better UI
24
+ st.markdown("""
25
+ <style>
26
+ .main-header {
27
+ font-size: 2.5rem;
28
+ color: #4A90E2;
29
+ text-align: center;
30
+ margin-bottom: 1rem;
31
+ }
32
+ .subheader {
33
+ font-size: 1.5rem;
34
+ color: #6C757D;
35
+ margin-bottom: 1rem;
36
+ }
37
+ .resource-card {
38
+ background-color: #F8F9FA;
39
+ padding: 1rem;
40
+ border-radius: 0.5rem;
41
+ margin-bottom: 1rem;
42
+ border-left: 4px solid #4A90E2;
43
+ }
44
+ .resource-title {
45
+ font-weight: bold;
46
+ color: #4A90E2;
47
+ }
48
+ .resource-type {
49
+ color: #6C757D;
50
+ font-size: 0.8rem;
51
+ }
52
+ .action-button {
53
+ margin-right: 0.5rem;
54
+ }
55
+ </style>
56
+ """, unsafe_allow_html=True)
57
+
58
+ # Mock database for user data and resources
59
+ if "mood_history" not in st.session_state:
60
+ st.session_state.mood_history = []
61
+
62
+ if "streak" not in st.session_state:
63
+ st.session_state.streak = 0
64
+
65
+ if "last_login" not in st.session_state:
66
+ st.session_state.last_login = None
67
+
68
+ if "personalized_resources" not in st.session_state:
69
+ st.session_state.personalized_resources = []
70
+
71
+ if "saved_resources" not in st.session_state:
72
+ st.session_state.saved_resources = []
73
+
74
+ if "liked_resources" not in st.session_state:
75
+ st.session_state.liked_resources = []
76
+
77
+ if "comments" not in st.session_state:
78
+ st.session_state.comments = {}
79
+
80
+ if "user_name" not in st.session_state:
81
+ st.session_state.user_name = ""
82
+
83
+ if "show_comment_input" not in st.session_state:
84
+ st.session_state.show_comment_input = {}
85
+
86
+ # Enhanced resources with more detailed information and tags
87
+ resources = {
88
+ "stress_management": [
89
+ {
90
+ "title": "5 Ways to Manage Stress",
91
+ "link": "https://example.com/stress-management",
92
+ "type": "Article",
93
+ "description": "Learn practical techniques to manage daily stress and anxiety.",
94
+ "tags": ["stress", "anxiety", "coping skills"],
95
+ "difficulty": "Beginner"
96
+ },
97
+ {
98
+ "title": "Mindfulness Techniques",
99
+ "link": "https://example.com/mindfulness",
100
+ "type": "Video",
101
+ "description": "A 10-minute guided video on mindfulness practices for stress reduction.",
102
+ "tags": ["mindfulness", "meditation", "stress"],
103
+ "difficulty": "Beginner"
104
+ },
105
+ {
106
+ "title": "Stress Relief Tips",
107
+ "link": "https://example.com/stress-relief",
108
+ "type": "Podcast",
109
+ "description": "Expert advice on managing stress in school and social situations.",
110
+ "tags": ["stress", "school", "social anxiety"],
111
+ "difficulty": "Intermediate"
112
+ }
113
+ ],
114
+ "mindfulness": [
115
+ {
116
+ "title": "Introduction to Mindfulness",
117
+ "link": "https://example.com/intro-mindfulness",
118
+ "type": "Article",
119
+ "description": "A beginner's guide to mindfulness and its benefits for mental health.",
120
+ "tags": ["mindfulness", "beginners", "mental health"],
121
+ "difficulty": "Beginner"
122
+ },
123
+ {
124
+ "title": "Guided Meditation",
125
+ "link": "https://example.com/guided-meditation",
126
+ "type": "Video",
127
+ "description": "A 15-minute guided meditation for anxiety and stress relief.",
128
+ "tags": ["meditation", "anxiety", "relaxation"],
129
+ "difficulty": "Beginner"
130
+ },
131
+ {
132
+ "title": "Daily Mindfulness Practices",
133
+ "link": "https://example.com/daily-mindfulness",
134
+ "type": "Podcast",
135
+ "description": "Simple mindfulness exercises you can incorporate into your daily routine.",
136
+ "tags": ["mindfulness", "daily practice", "habits"],
137
+ "difficulty": "Intermediate"
138
+ }
139
+ ],
140
+ "emotional_intelligence": [
141
+ {
142
+ "title": "Understanding Emotions",
143
+ "link": "https://example.com/understanding-emotions",
144
+ "type": "Article",
145
+ "description": "Learn to identify and understand different emotions and their triggers.",
146
+ "tags": ["emotions", "self-awareness", "emotional intelligence"],
147
+ "difficulty": "Beginner"
148
+ },
149
+ {
150
+ "title": "Building Emotional Resilience",
151
+ "link": "https://example.com/emotional-resilience",
152
+ "type": "Video",
153
+ "description": "Techniques to build emotional resilience and bounce back from challenges.",
154
+ "tags": ["resilience", "coping", "emotional strength"],
155
+ "difficulty": "Intermediate"
156
+ },
157
+ {
158
+ "title": "Emotional Intelligence 101",
159
+ "link": "https://example.com/emotional-intelligence",
160
+ "type": "Podcast",
161
+ "description": "An introduction to emotional intelligence and why it matters for teens.",
162
+ "tags": ["emotional intelligence", "teens", "social skills"],
163
+ "difficulty": "Beginner"
164
+ }
165
+ ],
166
+ "depression": [
167
+ {
168
+ "title": "Understanding Depression in Teens",
169
+ "link": "https://example.com/teen-depression",
170
+ "type": "Article",
171
+ "description": "Signs, symptoms, and coping strategies for depression in adolescents.",
172
+ "tags": ["depression", "teens", "mental health"],
173
+ "difficulty": "Intermediate"
174
+ },
175
+ {
176
+ "title": "Overcoming Negative Thoughts",
177
+ "link": "https://example.com/negative-thoughts",
178
+ "type": "Video",
179
+ "description": "Cognitive techniques to challenge and reframe negative thinking patterns.",
180
+ "tags": ["cognitive techniques", "negative thoughts", "depression"],
181
+ "difficulty": "Intermediate"
182
+ }
183
+ ],
184
+ "social_skills": [
185
+ {
186
+ "title": "Building Healthy Relationships",
187
+ "link": "https://example.com/healthy-relationships",
188
+ "type": "Article",
189
+ "description": "Tips for developing and maintaining healthy friendships and relationships.",
190
+ "tags": ["relationships", "communication", "social skills"],
191
+ "difficulty": "Beginner"
192
+ },
193
+ {
194
+ "title": "Effective Communication Skills",
195
+ "link": "https://example.com/communication-skills",
196
+ "type": "Video",
197
+ "description": "Learn how to express yourself clearly and listen effectively to others.",
198
+ "tags": ["communication", "listening", "expression"],
199
+ "difficulty": "Intermediate"
200
+ }
201
+ ]
202
+ }
203
+
204
+ # Function to toggle comment input visibility
205
+ def toggle_comment_input(resource_title):
206
+ if resource_title in st.session_state.show_comment_input:
207
+ st.session_state.show_comment_input[resource_title] = not st.session_state.show_comment_input[resource_title]
208
+ else:
209
+ st.session_state.show_comment_input[resource_title] = True
210
+
211
+ # Function to add comment
212
+ def add_comment(resource_title, comment):
213
+ if resource_title not in st.session_state.comments:
214
+ st.session_state.comments[resource_title] = []
215
+ st.session_state.comments[resource_title].append(comment)
216
+ st.session_state.show_comment_input[resource_title] = False
217
+
218
+ # Function to like resource
219
+ def like_resource(resource):
220
+ if resource not in st.session_state.liked_resources:
221
+ st.session_state.liked_resources.append(resource)
222
+
223
+ # Function to bookmark resource
224
+ def bookmark_resource(resource):
225
+ if resource not in st.session_state.saved_resources:
226
+ st.session_state.saved_resources.append(resource)
227
+
228
+ # Function to track mood with improved UI
229
+ def track_mood():
230
+ st.markdown("<h2 class='subheader'>Track Your Mood</h2>", unsafe_allow_html=True)
231
+
232
+ col1, col2 = st.columns([3, 2])
233
+
234
+ with col1:
235
+ # Mood tracking with emojis
236
+ st.write("How are you feeling today?")
237
+ mood_options = {
238
+ "😊 Happy": "happy",
239
+ "😢 Sad": "sad",
240
+ "😰 Anxious": "anxious",
241
+ "😠 Angry": "angry",
242
+ "😌 Calm": "calm"
243
+ }
244
+
245
+ mood_cols = st.columns(len(mood_options))
246
+ selected_mood = None
247
+
248
+ for i, (emoji_mood, mood_value) in enumerate(mood_options.items()):
249
+ with mood_cols[i]:
250
+ if st.button(emoji_mood, key=f"mood_{mood_value}"):
251
+ selected_mood = mood_value
252
+
253
+ if selected_mood:
254
+ # Check if this is a new day login
255
+ today = datetime.now().date()
256
+ if st.session_state.last_login is None or datetime.strptime(st.session_state.last_login, "%Y-%m-%d").date() < today:
257
+ st.session_state.streak += 1
258
+ st.session_state.last_login = today.strftime("%Y-%m-%d")
259
+
260
+ # Record the mood
261
+ st.session_state.mood_history.append((datetime.now().strftime("%Y-%m-%d %H:%M:%S"), selected_mood))
262
+ st.success(f"Your mood '{selected_mood}' has been recorded. Thank you for sharing!")
263
+
264
+ # Show streak celebration if streak is a multiple of 5
265
+ if st.session_state.streak > 0 and st.session_state.streak % 5 == 0:
266
+ st.balloons()
267
+ st.success(f"🎉 Congratulations! You've maintained a {st.session_state.streak}-day streak of mood tracking!")
268
+
269
+ with col2:
270
+ # Display mood statistics and streak
271
+ if st.session_state.mood_history:
272
+ st.write(f"🔥 Current streak: {st.session_state.streak} days")
273
+
274
+ # Create a mood history dataframe for visualization
275
+ if len(st.session_state.mood_history) > 0:
276
+ mood_df = pd.DataFrame(st.session_state.mood_history, columns=["timestamp", "mood"])
277
+ mood_df["date"] = pd.to_datetime(mood_df["timestamp"]).dt.date
278
+
279
+ # Count moods for the past week
280
+ today = datetime.now().date()
281
+ one_week_ago = today - timedelta(days=7)
282
+ recent_moods = mood_df[pd.to_datetime(mood_df["date"]) >= pd.Timestamp(one_week_ago)]
283
+
284
+ if not recent_moods.empty:
285
+ mood_counts = recent_moods["mood"].value_counts().reset_index()
286
+ mood_counts.columns = ["mood", "count"]
287
+
288
+ # Create a bar chart
289
+ chart = alt.Chart(mood_counts).mark_bar().encode(
290
+ x=alt.X("mood:N", title="Mood"),
291
+ y=alt.Y("count:Q", title="Frequency"),
292
+ color=alt.Color("mood:N", scale=alt.Scale(
293
+ domain=["happy", "calm", "anxious", "sad", "angry"],
294
+ range=["#FFD700", "#90EE90", "#ADD8E6", "#A9A9A9", "#FF6347"]
295
+ ))
296
+ ).properties(
297
+ title="Your Mood Over the Past Week",
298
+ width=300,
299
+ height=200
300
+ )
301
+
302
+ st.altair_chart(chart, use_container_width=True)
303
+ else:
304
+ st.info("Track your mood for a week to see mood patterns.")
305
+ else:
306
+ st.info("Start tracking your mood to see statistics.")
307
+
308
+ # Function to provide personalized resources with improved recommendation algorithm
309
+ def recommend_resources():
310
+ st.markdown("<h2 class='subheader'>Personalized Resources</h2>", unsafe_allow_html=True)
311
+
312
+ if not st.session_state.mood_history:
313
+ st.warning("No mood data available. Please track your mood first.")
314
+ return
315
+
316
+ # Get the latest mood and the mood history
317
+ latest_mood = st.session_state.mood_history[-1][1]
318
+
319
+ # Create a more sophisticated recommendation algorithm
320
+ # Count mood frequencies from the last 5 entries
321
+ recent_moods = [mood for _, mood in st.session_state.mood_history[-5:]]
322
+ mood_counts = {}
323
+ for mood in recent_moods:
324
+ if mood in mood_counts:
325
+ mood_counts[mood] += 1
326
+ else:
327
+ mood_counts[mood] = 1
328
+
329
+ # Determine primary and secondary mood states
330
+ primary_mood = max(mood_counts, key=mood_counts.get)
331
+
332
+ # Resource recommendation logic based on mood patterns
333
+ recommended_categories = []
334
+
335
+ if primary_mood in ["sad", "angry"]:
336
+ recommended_categories.extend(["stress_management", "emotional_intelligence"])
337
+ if mood_counts.get("sad", 0) > mood_counts.get("angry", 0):
338
+ recommended_categories.append("depression")
339
+
340
+ if primary_mood == "anxious":
341
+ recommended_categories.extend(["mindfulness", "stress_management"])
342
+
343
+ if primary_mood in ["happy", "calm"]:
344
+ recommended_categories.extend(["mindfulness", "emotional_intelligence"])
345
+ if "social_skills" in resources:
346
+ recommended_categories.append("social_skills")
347
+
348
+ # If we have liked resources, factor those in
349
+ if st.session_state.liked_resources:
350
+ liked_tags = []
351
+ for resource in st.session_state.liked_resources:
352
+ if "tags" in resource:
353
+ liked_tags.extend(resource["tags"])
354
+
355
+ # Count tag frequencies
356
+ tag_counts = {}
357
+ for tag in liked_tags:
358
+ if tag in tag_counts:
359
+ tag_counts[tag] += 1
360
+ else:
361
+ tag_counts[tag] = 1
362
+
363
+ # Add categories based on liked tags
364
+ if tag_counts:
365
+ top_tags = sorted(tag_counts.items(), key=lambda x: x[1], reverse=True)[:2]
366
+ for tag, _ in top_tags:
367
+ for category, resource_list in resources.items():
368
+ for resource in resource_list:
369
+ if "tags" in resource and tag in resource["tags"] and category not in recommended_categories:
370
+ recommended_categories.append(category)
371
+ break
372
+
373
+ # Ensure we have at least one category
374
+ if not recommended_categories:
375
+ recommended_categories = [random.choice(list(resources.keys()))]
376
+
377
+ # Get resources from recommended categories
378
+ st.session_state.personalized_resources = []
379
+ for category in recommended_categories:
380
+ if category in resources:
381
+ st.session_state.personalized_resources.extend(resources[category])
382
+
383
+ # Limit to 5 resources and shuffle for variety
384
+ if len(st.session_state.personalized_resources) > 5:
385
+ st.session_state.personalized_resources = random.sample(st.session_state.personalized_resources, 5)
386
+ else:
387
+ random.shuffle(st.session_state.personalized_resources)
388
+
389
+ st.markdown("<h3>Here are some resources tailored for you:</h3>", unsafe_allow_html=True)
390
+
391
+ # Display resources in an improved UI
392
+ for i, resource in enumerate(st.session_state.personalized_resources):
393
+ with st.container():
394
+ st.markdown(f"""
395
+ <div class="resource-card">
396
+ <div class="resource-title">{resource['title']}</div>
397
+ <div class="resource-type">{resource['type']}</div>
398
+ </div>
399
+ """, unsafe_allow_html=True)
400
+
401
+ st.markdown(f"**[{resource['title']}]({resource['link']})**")
402
+ st.write(resource.get("description", ""))
403
+
404
+ # Display tags
405
+ if "tags" in resource:
406
+ st.write("Tags: " + ", ".join([f"#{tag}" for tag in resource["tags"]]))
407
+
408
+ # Display difficulty
409
+ if "difficulty" in resource:
410
+ st.write(f"Difficulty: {resource['difficulty']}")
411
+
412
+ # Like, Comment, Share, and Bookmark buttons in a row
413
+ col1, col2, col3, col4 = st.columns(4)
414
+
415
+ with col1:
416
+ liked = any(r.get('title') == resource['title'] for r in st.session_state.liked_resources)
417
+ like_label = "👍 Liked" if liked else "👍 Like"
418
+ if st.button(like_label, key=f"like_{i}_{resource['title']}"):
419
+ like_resource(resource)
420
+ st.experimental_rerun()
421
+
422
+ with col2:
423
+ if st.button("💬 Comment", key=f"comment_btn_{i}_{resource['title']}"):
424
+ toggle_comment_input(resource['title'])
425
+ st.experimental_rerun()
426
+
427
+ with col3:
428
+ if st.button("🔗 Share", key=f"share_{i}_{resource['title']}"):
429
+ st.code(f"{resource['link']}", language="text")
430
+
431
+ with col4:
432
+ saved = any(r.get('title') == resource['title'] for r in st.session_state.saved_resources)
433
+ save_label = "🔖 Saved" if saved else "🔖 Save"
434
+ if st.button(save_label, key=f"save_{i}_{resource['title']}"):
435
+ bookmark_resource(resource)
436
+ st.experimental_rerun()
437
+
438
+ # Show comment input if toggled
439
+ if resource['title'] in st.session_state.show_comment_input and st.session_state.show_comment_input[resource['title']]:
440
+ comment = st.text_area(f"Add a comment for {resource['title']}:", key=f"comment_text_{i}_{resource['title']}")
441
+ if st.button("Submit Comment", key=f"submit_comment_{i}_{resource['title']}"):
442
+ if comment:
443
+ add_comment(resource['title'], comment)
444
+ st.success("Comment added!")
445
+ st.experimental_rerun()
446
+
447
+ # Show existing comments
448
+ if resource['title'] in st.session_state.comments and st.session_state.comments[resource['title']]:
449
+ with st.expander(f"View {len(st.session_state.comments[resource['title']])} comments"):
450
+ for comment in st.session_state.comments[resource['title']]:
451
+ st.write(f"- {comment}")
452
+
453
+ st.markdown("---")
454
+
455
+ # Function to display user profile with improved UI
456
+ def user_profile():
457
+ st.markdown("<h2 class='subheader'>Your Profile</h2>", unsafe_allow_html=True)
458
+
459
+ # User name input
460
+ if not st.session_state.user_name:
461
+ user_name = st.text_input("What should we call you?")
462
+ if user_name:
463
+ st.session_state.user_name = user_name
464
+ st.success(f"Welcome, {user_name}!")
465
+ st.experimental_rerun()
466
+ else:
467
+ st.write(f"Welcome back, {st.session_state.user_name}! 👋")
468
+ if st.button("Change name"):
469
+ st.session_state.user_name = ""
470
+ st.experimental_rerun()
471
+
472
+ # Create tabs for different sections of the profile
473
+ profile_tab1, profile_tab2, profile_tab3 = st.tabs(["Mood History", "Saved Resources", "Activity"])
474
+
475
+ with profile_tab1:
476
+ st.subheader("Mood History")
477
+ if st.session_state.mood_history:
478
+ # Create a dataframe for visualization
479
+ mood_df = pd.DataFrame(st.session_state.mood_history, columns=["timestamp", "mood"])
480
+ mood_df["date"] = pd.to_datetime(mood_df["timestamp"]).dt.date
481
+ mood_df["time"] = pd.to_datetime(mood_df["timestamp"]).dt.time
482
+
483
+ # Group by date and get the last mood for each day
484
+ daily_mood = mood_df.sort_values("timestamp").groupby("date").last().reset_index()
485
+
486
+ # Create a calendar heatmap-like visualization
487
+ if len(daily_mood) > 0:
488
+ # Create a color mapping for moods
489
+ color_scale = {
490
+ "happy": "#FFD700", # Gold
491
+ "calm": "#90EE90", # Light green
492
+ "anxious": "#ADD8E6", # Light blue
493
+ "sad": "#A9A9A9", # Dark gray
494
+ "angry": "#FF6347" # Tomato
495
+ }
496
+
497
+ daily_mood["color"] = daily_mood["mood"].map(color_scale)
498
+
499
+ # Create a chart
500
+ chart = alt.Chart(daily_mood).mark_rect().encode(
501
+ x=alt.X('date:T', title='Date', axis=alt.Axis(format='%b %d')),
502
+ color=alt.Color('mood:N', scale=alt.Scale(
503
+ domain=list(color_scale.keys()),
504
+ range=list(color_scale.values())
505
+ ))
506
+ ).properties(
507
+ title="Your Mood Calendar",
508
+ width=600,
509
+ height=100
510
+ )
511
+
512
+ st.altair_chart(chart, use_container_width=True)
513
+
514
+ # Show a table of recent moods
515
+ st.subheader("Recent Mood Entries")
516
+ recent_moods = mood_df.sort_values("timestamp", ascending=False).head(10)
517
+ for _, row in recent_moods.iterrows():
518
+ st.write(f"{row['timestamp']}: {row['mood']}")
519
+ else:
520
+ st.write("No mood history available.")
521
+ else:
522
+ st.write("No mood history available.")
523
+
524
+ with profile_tab2:
525
+ st.subheader("Saved Resources")
526
+ if st.session_state.saved_resources:
527
+ for i, resource in enumerate(st.session_state.saved_resources):
528
+ with st.container():
529
+ st.markdown(f"""
530
+ <div class="resource-card">
531
+ <div class="resource-title">{resource['title']}</div>
532
+ <div class="resource-type">{resource['type']}</div>
533
+ </div>
534
+ """, unsafe_allow_html=True)
535
+
536
+ st.markdown(f"**[{resource['title']}]({resource['link']})**")
537
+
538
+ if "description" in resource:
539
+ st.write(resource["description"])
540
+
541
+ # Remove from saved button
542
+ if st.button("❌ Remove", key=f"remove_saved_{i}"):
543
+ st.session_state.saved_resources.remove(resource)
544
+ st.experimental_rerun()
545
+
546
+ st.markdown("---")
547
+ else:
548
+ st.write("No saved resources yet.")
549
+
550
+ with profile_tab3:
551
+ col1, col2 = st.columns(2)
552
+
553
+ with col1:
554
+ st.subheader("Liked Resources")
555
+ if st.session_state.liked_resources:
556
+ for resource in st.session_state.liked_resources:
557
+ st.markdown(f"**[{resource['title']}]({resource['link']})**")
558
+ else:
559
+ st.write("No liked resources yet.")
560
+
561
+ with col2:
562
+ st.subheader("Your Comments")
563
+ if st.session_state.comments:
564
+ for resource_title, comments in st.session_state.comments.items():
565
+ with st.expander(f"{resource_title} ({len(comments)} comments)"):
566
+ for comment in comments:
567
+ st.write(f"- {comment}")
568
+ else:
569
+ st.write("No comments yet.")
570
+
571
+ # About Us section in the sidebar with improved content
572
+ def about_us():
573
+ st.sidebar.markdown("<h2>About Us</h2>", unsafe_allow_html=True)
574
+ st.sidebar.write("""
575
+ **AfyaMind Space** is a technology-driven mental health platform designed to empower adolescents in low-resource settings.
576
+
577
+ Our mission is to provide accessible, culturally adaptive, and engaging mental health resources to help young people
578
+ manage their emotional well-being and build resilience.
579
+
580
+ ### Our Approach
581
+ - **Personalized Resources**: Get content tailored to your emotional needs
582
+ - **Mood Tracking**: Monitor your emotional patterns over time
583
+ - **Community Support**: Connect with peers in a safe environment
584
+ - **Offline Access**: Access key resources even without internet
585
+ """)
586
+
587
+ # FAQs section in the sidebar with improved content
588
+ def faqs():
589
+ st.sidebar.markdown("<h2>FAQs</h2>", unsafe_allow_html=True)
590
+
591
+ # Create expandable FAQ items
592
+ with st.sidebar.expander("What is AfyaMind Space?"):
593
+ st.write("AfyaMind Space is a digital platform offering AI-powered mental health resources, mood tracking, and peer support for adolescents.")
594
+
595
+ with st.sidebar.expander("Is AfyaMind free to use?"):
596
+ st.write("Yes, AfyaMind is completely free and accessible to all users.")
597
+
598
+ with st.sidebar.expander("How does AfyaMind protect my data?"):
599
+ st.write("We use strong encryption and comply with global data protection standards to ensure your privacy.")
600
+
601
+ with st.sidebar.expander("Can I use AfyaMind offline?"):
602
+ st.write("Yes, AfyaMind offers offline features like mood tracking and downloadable resources for users without internet access.")
603
+
604
+ with st.sidebar.expander("How can I get help in a crisis?"):
605
+ st.write("""
606
+ If you're experiencing a mental health crisis:
607
+ - Call your local emergency number
608
+ - Text a crisis helpline
609
+ - Reach out to a trusted adult
610
+ - Visit the nearest hospital emergency room
611
+
612
+ Remember, you're not alone and help is available.
613
+ """)
614
+
615
+ # Help resources in the sidebar
616
+ def help_resources():
617
+ st.sidebar.markdown("<h2>Help Resources</h2>", unsafe_allow_html=True)
618
+ st.sidebar.write("""
619
+ ### Crisis Helplines
620
+ - **Kenya Mental Health Helpline**: 1199 (toll-free)
621
+ - **Befrienders Kenya**: 0722 178 177
622
+
623
+ ### Online Resources
624
+ - [Mental Health Kenya](https://mentalhealthkenya.org/)
625
+ - [Chiromo Hospital Group](https://www.chiromohospital.org/)
626
+ """)
627
+
628
+ # Main app layout with improved UI
629
+ def main():
630
+ st.markdown("<h1 class='main-header'>AfyaMind Space: Your Mental Health Companion</h1>", unsafe_allow_html=True)
631
+
632
+ # Check if user is logged in
633
+ is_logged_in = auth_page()
634
+
635
+ # Sidebar with About Us, FAQs, and Help Resources
636
+ about_us()
637
+ faqs()
638
+ help_resources()
639
+
640
+ # Only show main content if user is logged in or authentication is not required for this section
641
+ if "require_auth" not in st.session_state:
642
+ st.session_state.require_auth = True
643
+
644
+ if is_logged_in or not st.session_state.require_auth:
645
+ # Tabs for different sections with better styling
646
+ tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8 = st.tabs(["🌡️ Track Mood", "📊 Analytics", "📚 Resources", "🧘 Meditation", "🎯 Goals", "💬 Community", "👤 Profile", "💬 Chat Assistant"])
647
+
648
+ with tab1:
649
+ track_mood()
650
+
651
+ with tab2:
652
+ mood_analytics_page()
653
+
654
+ with tab3:
655
+ recommend_resources()
656
+
657
+ with tab4:
658
+ meditation_page()
659
+
660
+ with tab5:
661
+ goals_page()
662
+
663
+ with tab6:
664
+ forum_page()
665
+
666
+ with tab7:
667
+ user_profile()
668
+
669
+ with tab8:
670
+ create_chat_interface()
671
+
672
+ # Footer
673
+ st.markdown("---")
674
+ st.markdown(
675
+ """
676
+ <div style="text-align: center; color: #6C757D; font-size: 0.8rem;">
677
+ &copy; 2025 AfyaMind Space. Made with &hearts; for adolescent mental health.
678
+ </div>
679
+ """,
680
+ unsafe_allow_html=True
681
+ )
682
+
683
+ # Run the app
684
+ if __name__ == "__main__":
685
+ main()
AfyaMindSpace/app.py.new ADDED
File without changes
AfyaMindSpace/auth.py ADDED
@@ -0,0 +1,244 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import hashlib
3
+ import json
4
+ import os
5
+ from datetime import datetime
6
+
7
+ # File to store user data
8
+ USER_DB_FILE = "user_data.json"
9
+
10
+ # Initialize user database
11
+ def initialize_user_db():
12
+ if not os.path.exists(USER_DB_FILE):
13
+ with open(USER_DB_FILE, "w") as f:
14
+ json.dump({"users": {}}, f)
15
+ return {"users": {}}
16
+
17
+ try:
18
+ with open(USER_DB_FILE, "r") as f:
19
+ return json.load(f)
20
+ except json.JSONDecodeError:
21
+ # If file is corrupted, create a new one
22
+ with open(USER_DB_FILE, "w") as f:
23
+ json.dump({"users": {}}, f)
24
+ return {"users": {}}
25
+
26
+ # Save user database
27
+ def save_user_db(db):
28
+ with open(USER_DB_FILE, "w") as f:
29
+ json.dump(db, f)
30
+
31
+ # Hash password
32
+ def hash_password(password):
33
+ return hashlib.sha256(password.encode()).hexdigest()
34
+
35
+ # Register new user
36
+ def register_user(username, password, email):
37
+ db = initialize_user_db()
38
+
39
+ if username in db["users"]:
40
+ return False, "Username already exists"
41
+
42
+ # Check for email duplicates
43
+ for user in db["users"].values():
44
+ if user["email"] == email:
45
+ return False, "Email already registered"
46
+
47
+ # Create new user
48
+ db["users"][username] = {
49
+ "password_hash": hash_password(password),
50
+ "email": email,
51
+ "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
52
+ "last_login": None,
53
+ "profile": {
54
+ "display_name": username,
55
+ "bio": "",
56
+ "preferences": {
57
+ "notifications": True,
58
+ "privacy": "public"
59
+ }
60
+ }
61
+ }
62
+
63
+ save_user_db(db)
64
+ return True, "Registration successful"
65
+
66
+ # Authenticate user
67
+ def authenticate_user(username, password):
68
+ db = initialize_user_db()
69
+
70
+ if username not in db["users"]:
71
+ return False, "Invalid username or password"
72
+
73
+ if db["users"][username]["password_hash"] != hash_password(password):
74
+ return False, "Invalid username or password"
75
+
76
+ # Update last login
77
+ db["users"][username]["last_login"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
78
+ save_user_db(db)
79
+
80
+ return True, "Login successful"
81
+
82
+ # Update user profile
83
+ def update_user_profile(username, profile_data):
84
+ db = initialize_user_db()
85
+
86
+ if username not in db["users"]:
87
+ return False, "User not found"
88
+
89
+ # Update profile fields
90
+ for key, value in profile_data.items():
91
+ if key in db["users"][username]["profile"]:
92
+ db["users"][username]["profile"][key] = value
93
+
94
+ save_user_db(db)
95
+ return True, "Profile updated successfully"
96
+
97
+ # Get user profile
98
+ def get_user_profile(username):
99
+ db = initialize_user_db()
100
+
101
+ if username not in db["users"]:
102
+ return None
103
+
104
+ return db["users"][username]["profile"]
105
+
106
+ # Change password
107
+ def change_password(username, old_password, new_password):
108
+ db = initialize_user_db()
109
+
110
+ if username not in db["users"]:
111
+ return False, "User not found"
112
+
113
+ if db["users"][username]["password_hash"] != hash_password(old_password):
114
+ return False, "Incorrect password"
115
+
116
+ db["users"][username]["password_hash"] = hash_password(new_password)
117
+ save_user_db(db)
118
+
119
+ return True, "Password changed successfully"
120
+
121
+ # Reset password (simplified version - in a real app, this would involve email verification)
122
+ def reset_password(email):
123
+ db = initialize_user_db()
124
+
125
+ # Find user with this email
126
+ username = None
127
+ for user, data in db["users"].items():
128
+ if data["email"] == email:
129
+ username = user
130
+ break
131
+
132
+ if not username:
133
+ return False, "Email not found"
134
+
135
+ # In a real app, we would send an email with a reset link
136
+ # For this demo, we'll just generate a temporary password
137
+ temp_password = "temp" + datetime.now().strftime("%H%M%S")
138
+ db["users"][username]["password_hash"] = hash_password(temp_password)
139
+ save_user_db(db)
140
+
141
+ return True, f"Password reset to: {temp_password}"
142
+
143
+ # Authentication UI components
144
+ def login_form():
145
+ st.subheader("Login")
146
+
147
+ username = st.text_input("Username", key="login_username")
148
+ password = st.text_input("Password", type="password", key="login_password")
149
+
150
+ if st.button("Login", key="login_button"):
151
+ if username and password:
152
+ success, message = authenticate_user(username, password)
153
+ if success:
154
+ st.session_state.logged_in = True
155
+ st.session_state.username = username
156
+ st.success(message)
157
+ st.rerun()
158
+ else:
159
+ st.error(message)
160
+ else:
161
+ st.warning("Please enter both username and password")
162
+
163
+ def register_form():
164
+ st.subheader("Register")
165
+
166
+ # Add asterisks to indicate required fields
167
+ username = st.text_input("Username *", key="register_username")
168
+ email = st.text_input("Email *", key="register_email")
169
+ password = st.text_input("Password *", type="password", key="register_password")
170
+ confirm_password = st.text_input("Confirm Password *", type="password", key="confirm_password")
171
+
172
+ # Add a note about required fields
173
+ st.markdown("<small>* Required fields</small>", unsafe_allow_html=True)
174
+
175
+ if st.button("Register", key="register_button"):
176
+ # Check each field individually and provide specific feedback
177
+ missing_fields = []
178
+ if not username:
179
+ missing_fields.append("Username")
180
+ if not email:
181
+ missing_fields.append("Email")
182
+ if not password:
183
+ missing_fields.append("Password")
184
+ if not confirm_password:
185
+ missing_fields.append("Confirm Password")
186
+
187
+ if missing_fields:
188
+ st.error(f"Please fill in the following required fields: {', '.join(missing_fields)}")
189
+ elif password != confirm_password:
190
+ st.error("Passwords do not match")
191
+ else:
192
+ success, message = register_user(username, password, email)
193
+ if success:
194
+ st.success(message)
195
+ st.info("Please login with your new account")
196
+ else:
197
+ st.error(message)
198
+
199
+ def forgot_password_form():
200
+ st.subheader("Reset Password")
201
+
202
+ email = st.text_input("Email", key="reset_email")
203
+
204
+ if st.button("Reset Password", key="reset_button"):
205
+ if email:
206
+ success, message = reset_password(email)
207
+ if success:
208
+ st.success("Password reset successful")
209
+ st.info(message)
210
+ else:
211
+ st.error(message)
212
+ else:
213
+ st.warning("Please enter your email")
214
+
215
+ def logout_user():
216
+ if st.sidebar.button("Logout"):
217
+ st.session_state.logged_in = False
218
+ st.session_state.username = None
219
+ st.rerun()
220
+
221
+ def auth_page():
222
+ if "logged_in" not in st.session_state:
223
+ st.session_state.logged_in = False
224
+
225
+ if "username" not in st.session_state:
226
+ st.session_state.username = None
227
+
228
+ if not st.session_state.logged_in:
229
+ tab1, tab2, tab3 = st.tabs(["Login", "Register", "Forgot Password"])
230
+
231
+ with tab1:
232
+ login_form()
233
+
234
+ with tab2:
235
+ register_form()
236
+
237
+ with tab3:
238
+ forgot_password_form()
239
+
240
+ return False
241
+ else:
242
+ # User is logged in
243
+ logout_user()
244
+ return True
AfyaMindSpace/chatbox.py ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import time
3
+ import json
4
+ from datetime import datetime
5
+
6
+ class ChatMessage:
7
+ def __init__(self, content, is_user=True, timestamp=None):
8
+ self.content = content
9
+ self.is_user = is_user
10
+ self.timestamp = timestamp or datetime.now()
11
+ self.feedback = None
12
+
13
+ def to_dict(self):
14
+ return {
15
+ "content": self.content,
16
+ "is_user": self.is_user,
17
+ "timestamp": self.timestamp.isoformat(),
18
+ "feedback": self.feedback
19
+ }
20
+
21
+ @classmethod
22
+ def from_dict(cls, data):
23
+ msg = cls(
24
+ content=data["content"],
25
+ is_user=data["is_user"],
26
+ timestamp=datetime.fromisoformat(data["timestamp"])
27
+ )
28
+ msg.feedback = data.get("feedback")
29
+ return msg
30
+
31
+ class ChatBox:
32
+ def __init__(self, user_theme="green", assistant_theme="blue"):
33
+ self.user_theme = user_theme
34
+ self.assistant_theme = assistant_theme
35
+ self.init_session()
36
+
37
+ def init_session(self, clear=False):
38
+ """Initialize or clear the chat session"""
39
+ if "chat_messages" not in st.session_state or clear:
40
+ st.session_state.chat_messages = []
41
+
42
+ def user_say(self, message):
43
+ """Add a user message to the chat"""
44
+ if message and message.strip():
45
+ st.session_state.chat_messages.append(ChatMessage(message, is_user=True))
46
+ return True
47
+ return False
48
+
49
+ def ai_say(self, message, streaming=False):
50
+ """Add an AI message to the chat"""
51
+ if message and message.strip():
52
+ st.session_state.chat_messages.append(ChatMessage(message, is_user=False))
53
+ return True
54
+ return False
55
+
56
+ def update_last_ai_message(self, message, streaming=False):
57
+ """Update the last AI message in the chat"""
58
+ for i in range(len(st.session_state.chat_messages) - 1, -1, -1):
59
+ if not st.session_state.chat_messages[i].is_user:
60
+ st.session_state.chat_messages[i].content = message
61
+ return True
62
+ return False
63
+
64
+ def set_feedback(self, message_index, feedback):
65
+ """Set feedback for a message"""
66
+ if 0 <= message_index < len(st.session_state.chat_messages):
67
+ st.session_state.chat_messages[message_index].feedback = feedback
68
+ return True
69
+ return False
70
+
71
+ def render_message(self, message, index):
72
+ """Render a single message in the chat"""
73
+ if message.is_user:
74
+ with st.chat_message("user", avatar="👤"):
75
+ st.markdown(message.content)
76
+ else:
77
+ with st.chat_message("assistant", avatar="🧠"):
78
+ st.markdown(message.content)
79
+
80
+ # Add feedback buttons if needed
81
+ col1, col2, col3 = st.columns([1, 1, 8])
82
+ if col1.button("👍", key=f"like_{index}"):
83
+ self.set_feedback(index, "positive")
84
+ st.rerun()
85
+ if col2.button("👎", key=f"dislike_{index}"):
86
+ self.set_feedback(index, "negative")
87
+ st.rerun()
88
+
89
+ def render_chat(self):
90
+ """Render the entire chat history"""
91
+ for i, message in enumerate(st.session_state.chat_messages):
92
+ self.render_message(message, i)
93
+
94
+ def to_json(self):
95
+ """Export chat history to JSON"""
96
+ return json.dumps([msg.to_dict() for msg in st.session_state.chat_messages], indent=2)
97
+
98
+ def from_json(self, json_str):
99
+ """Import chat history from JSON"""
100
+ try:
101
+ data = json.loads(json_str)
102
+ st.session_state.chat_messages = [ChatMessage.from_dict(msg) for msg in data]
103
+ return True
104
+ except Exception as e:
105
+ st.error(f"Error loading chat history: {e}")
106
+ return False
107
+
108
+ def clear_history(self):
109
+ """Clear chat history"""
110
+ self.init_session(clear=True)
111
+
112
+ # Mock AI response generator for demonstration
113
+ class MockAI:
114
+ def __init__(self):
115
+ self.responses = {
116
+ "hello": "Hello! How can I help you with your mental health today?",
117
+ "how are you": "I'm just a program, but I'm here to support you. How are you feeling today?",
118
+ "feeling sad": "I'm sorry to hear you're feeling sad. Would you like to try a quick mood-lifting exercise or talk about what's bothering you?",
119
+ "feeling anxious": "Anxiety can be challenging. Have you tried any breathing exercises? Taking slow, deep breaths can help calm your nervous system.",
120
+ "meditation": "Meditation is a great practice for mental health. We have several guided meditations available in the Meditation tab. Would you like me to recommend one?",
121
+ "help": "I'm here to support your mental health journey. You can ask me about coping strategies, resources, or just chat about how you're feeling."
122
+ }
123
+ self.default_response = "I'm here to support you. Could you tell me more about what's on your mind?"
124
+
125
+ def get_response(self, query):
126
+ """Get a response based on the user query"""
127
+ query = query.lower()
128
+ for key, response in self.responses.items():
129
+ if key in query:
130
+ return response
131
+ return self.default_response
132
+
133
+ def get_streaming_response(self, query):
134
+ """Simulate a streaming response"""
135
+ response = self.get_response(query)
136
+ words = response.split()
137
+ result = ""
138
+ for word in words:
139
+ result += word + " "
140
+ yield result
141
+ time.sleep(0.1)
142
+
143
+ # Function to create a chat interface
144
+ def create_chat_interface():
145
+ st.markdown("<h2>Chat with AfyaMind Assistant</h2>", unsafe_allow_html=True)
146
+
147
+ # Initialize chat components
148
+ if "chatbox" not in st.session_state:
149
+ st.session_state.chatbox = ChatBox()
150
+
151
+ if "ai" not in st.session_state:
152
+ st.session_state.ai = MockAI()
153
+
154
+ # Chat settings
155
+ with st.expander("Chat Settings"):
156
+ col1, col2 = st.columns(2)
157
+ streaming = col1.checkbox("Enable streaming responses", value=True)
158
+ col2.download_button(
159
+ "Export Chat History",
160
+ st.session_state.chatbox.to_json(),
161
+ file_name="afyamind_chat_history.json",
162
+ mime="application/json"
163
+ )
164
+ if st.button("Clear Chat History"):
165
+ st.session_state.chatbox.clear_history()
166
+ st.rerun()
167
+
168
+ # Display chat history
169
+ st.session_state.chatbox.render_chat()
170
+
171
+ # Chat input
172
+ if prompt := st.chat_input("Type your message here..."):
173
+ # Add user message
174
+ st.session_state.chatbox.user_say(prompt)
175
+
176
+ # Generate AI response
177
+ if streaming:
178
+ # Initial placeholder for streaming response
179
+ st.session_state.chatbox.ai_say("Thinking...", streaming=True)
180
+ st.rerun()
181
+
182
+ # This part will run after the rerun
183
+ # In a real implementation, you would use a proper streaming API
184
+ # For now, we'll simulate streaming with our mock AI
185
+ else:
186
+ response = st.session_state.ai.get_response(prompt)
187
+ st.session_state.chatbox.ai_say(response)
188
+ st.rerun()
189
+
190
+ # For testing the module independently
191
+ if __name__ == "__main__":
192
+ st.set_page_config(page_title="AfyaMind Chat", page_icon="🧠")
193
+ create_chat_interface()
AfyaMindSpace/forum.py ADDED
@@ -0,0 +1,563 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import json
3
+ import os
4
+ from datetime import datetime
5
+
6
+ # File to store forum data
7
+ FORUM_DB_FILE = "forum_data.json"
8
+
9
+ # Initialize forum database
10
+ def initialize_forum_db():
11
+ if not os.path.exists(FORUM_DB_FILE):
12
+ forum_data = {
13
+ "categories": [
14
+ {
15
+ "id": "general",
16
+ "name": "General Discussion",
17
+ "description": "General topics related to mental health and wellbeing"
18
+ },
19
+ {
20
+ "id": "stress",
21
+ "name": "Stress Management",
22
+ "description": "Discuss strategies for managing stress and anxiety"
23
+ },
24
+ {
25
+ "id": "mindfulness",
26
+ "name": "Mindfulness & Meditation",
27
+ "description": "Share experiences and tips about mindfulness practices"
28
+ },
29
+ {
30
+ "id": "support",
31
+ "name": "Peer Support",
32
+ "description": "A safe space to seek support from others"
33
+ },
34
+ {
35
+ "id": "success",
36
+ "name": "Success Stories",
37
+ "description": "Share your mental health journey and achievements"
38
+ }
39
+ ],
40
+ "topics": {},
41
+ "posts": {}
42
+ }
43
+ with open(FORUM_DB_FILE, "w") as f:
44
+ json.dump(forum_data, f)
45
+ return forum_data
46
+
47
+ try:
48
+ with open(FORUM_DB_FILE, "r") as f:
49
+ return json.load(f)
50
+ except json.JSONDecodeError:
51
+ # If file is corrupted, create a new one
52
+ forum_data = {
53
+ "categories": [
54
+ {
55
+ "id": "general",
56
+ "name": "General Discussion",
57
+ "description": "General topics related to mental health and wellbeing"
58
+ },
59
+ {
60
+ "id": "stress",
61
+ "name": "Stress Management",
62
+ "description": "Discuss strategies for managing stress and anxiety"
63
+ },
64
+ {
65
+ "id": "mindfulness",
66
+ "name": "Mindfulness & Meditation",
67
+ "description": "Share experiences and tips about mindfulness practices"
68
+ },
69
+ {
70
+ "id": "support",
71
+ "name": "Peer Support",
72
+ "description": "A safe space to seek support from others"
73
+ },
74
+ {
75
+ "id": "success",
76
+ "name": "Success Stories",
77
+ "description": "Share your mental health journey and achievements"
78
+ }
79
+ ],
80
+ "topics": {},
81
+ "posts": {}
82
+ }
83
+ with open(FORUM_DB_FILE, "w") as f:
84
+ json.dump(forum_data, f)
85
+ return forum_data
86
+
87
+ # Save forum database
88
+ def save_forum_db(db):
89
+ with open(FORUM_DB_FILE, "w") as f:
90
+ json.dump(db, f)
91
+
92
+ # Create a new topic
93
+ def create_topic(category_id, title, content, author):
94
+ db = initialize_forum_db()
95
+
96
+ # Check if category exists
97
+ category_exists = False
98
+ for category in db["categories"]:
99
+ if category["id"] == category_id:
100
+ category_exists = True
101
+ break
102
+
103
+ if not category_exists:
104
+ return False, "Category does not exist"
105
+
106
+ # Generate a unique topic ID
107
+ topic_id = f"topic_{len(db['topics']) + 1}_{datetime.now().strftime('%Y%m%d%H%M%S')}"
108
+
109
+ # Create the topic
110
+ db["topics"][topic_id] = {
111
+ "id": topic_id,
112
+ "category_id": category_id,
113
+ "title": title,
114
+ "author": author,
115
+ "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
116
+ "updated_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
117
+ "views": 0,
118
+ "likes": 0,
119
+ "is_pinned": False,
120
+ "is_locked": False,
121
+ "tags": []
122
+ }
123
+
124
+ # Create the first post in the topic
125
+ post_id = f"post_{len(db['posts']) + 1}_{datetime.now().strftime('%Y%m%d%H%M%S')}"
126
+ db["posts"][post_id] = {
127
+ "id": post_id,
128
+ "topic_id": topic_id,
129
+ "author": author,
130
+ "content": content,
131
+ "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
132
+ "updated_at": None,
133
+ "likes": 0,
134
+ "is_solution": False,
135
+ "replies": []
136
+ }
137
+
138
+ save_forum_db(db)
139
+ return True, topic_id
140
+
141
+ # Get all categories
142
+ def get_categories():
143
+ db = initialize_forum_db()
144
+ return db["categories"]
145
+
146
+ # Get topics by category
147
+ def get_topics_by_category(category_id):
148
+ db = initialize_forum_db()
149
+
150
+ topics = []
151
+ for topic_id, topic in db["topics"].items():
152
+ if topic["category_id"] == category_id:
153
+ topics.append(topic)
154
+
155
+ # Sort topics by pinned status and then by creation date (newest first)
156
+ topics.sort(key=lambda x: (not x["is_pinned"], x["created_at"]), reverse=True)
157
+
158
+ return topics
159
+
160
+ # Get topic by ID
161
+ def get_topic(topic_id):
162
+ db = initialize_forum_db()
163
+
164
+ if topic_id in db["topics"]:
165
+ # Increment view count
166
+ db["topics"][topic_id]["views"] += 1
167
+ save_forum_db(db)
168
+ return db["topics"][topic_id]
169
+
170
+ return None
171
+
172
+ # Get posts by topic ID
173
+ def get_posts_by_topic(topic_id):
174
+ db = initialize_forum_db()
175
+
176
+ posts = []
177
+ for post_id, post in db["posts"].items():
178
+ if post["topic_id"] == topic_id:
179
+ posts.append(post)
180
+
181
+ # Sort posts by creation date
182
+ posts.sort(key=lambda x: x["created_at"])
183
+
184
+ return posts
185
+
186
+ # Create a reply to a post
187
+ def create_reply(post_id, content, author):
188
+ db = initialize_forum_db()
189
+
190
+ if post_id not in db["posts"]:
191
+ return False, "Post not found"
192
+
193
+ # Generate a unique reply ID
194
+ reply_id = f"reply_{len(db['posts'][post_id]['replies']) + 1}_{datetime.now().strftime('%Y%m%d%H%M%S')}"
195
+
196
+ # Add the reply
197
+ db["posts"][post_id]["replies"].append({
198
+ "id": reply_id,
199
+ "author": author,
200
+ "content": content,
201
+ "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
202
+ "updated_at": None,
203
+ "likes": 0
204
+ })
205
+
206
+ # Update the topic's updated_at timestamp
207
+ topic_id = db["posts"][post_id]["topic_id"]
208
+ db["topics"][topic_id]["updated_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
209
+
210
+ save_forum_db(db)
211
+ return True, reply_id
212
+
213
+ # Like a post
214
+ def like_post(post_id, username):
215
+ db = initialize_forum_db()
216
+
217
+ if post_id not in db["posts"]:
218
+ return False, "Post not found"
219
+
220
+ # In a real app, we would track which users liked which posts
221
+ # For simplicity, we'll just increment the like count
222
+ db["posts"][post_id]["likes"] += 1
223
+
224
+ save_forum_db(db)
225
+ return True, "Post liked"
226
+
227
+ # Like a topic
228
+ def like_topic(topic_id, username):
229
+ db = initialize_forum_db()
230
+
231
+ if topic_id not in db["topics"]:
232
+ return False, "Topic not found"
233
+
234
+ # In a real app, we would track which users liked which topics
235
+ # For simplicity, we'll just increment the like count
236
+ db["topics"][topic_id]["likes"] += 1
237
+
238
+ save_forum_db(db)
239
+ return True, "Topic liked"
240
+
241
+ # Search topics and posts
242
+ def search_forum(query):
243
+ db = initialize_forum_db()
244
+
245
+ results = {
246
+ "topics": [],
247
+ "posts": []
248
+ }
249
+
250
+ # Search in topics
251
+ for topic_id, topic in db["topics"].items():
252
+ if query.lower() in topic["title"].lower():
253
+ results["topics"].append(topic)
254
+
255
+ # Search in posts
256
+ for post_id, post in db["posts"].items():
257
+ if query.lower() in post["content"].lower():
258
+ # Add the associated topic
259
+ topic = db["topics"][post["topic_id"]]
260
+ if topic not in results["topics"]:
261
+ results["topics"].append(topic)
262
+ results["posts"].append(post)
263
+
264
+ return results
265
+
266
+ # Forum UI components
267
+ def forum_categories():
268
+ st.subheader("Community Forum")
269
+ st.write("Connect with others, share experiences, and find support in our community forums.")
270
+
271
+ categories = get_categories()
272
+
273
+ # Display categories in a grid
274
+ cols = st.columns(2)
275
+ for i, category in enumerate(categories):
276
+ with cols[i % 2]:
277
+ with st.container():
278
+ st.markdown(f"### {category['name']}")
279
+ st.write(category['description'])
280
+ if st.button(f"Browse {category['name']}", key=f"browse_{category['id']}"):
281
+ st.session_state.forum_view = "topics"
282
+ st.session_state.forum_category = category['id']
283
+ st.experimental_rerun()
284
+
285
+ def forum_topics(category_id):
286
+ db = initialize_forum_db()
287
+
288
+ # Find category name
289
+ category_name = "Unknown Category"
290
+ for category in db["categories"]:
291
+ if category["id"] == category_id:
292
+ category_name = category["name"]
293
+ break
294
+
295
+ st.subheader(f"{category_name} - Topics")
296
+
297
+ # Back button
298
+ if st.button("← Back to Categories"):
299
+ st.session_state.forum_view = "categories"
300
+ st.session_state.forum_category = None
301
+ st.experimental_rerun()
302
+
303
+ # New topic button
304
+ if st.session_state.get("logged_in", False):
305
+ if st.button("+ New Topic"):
306
+ st.session_state.forum_view = "new_topic"
307
+ st.experimental_rerun()
308
+ else:
309
+ st.info("Please log in to create a new topic")
310
+
311
+ # Get topics
312
+ topics = get_topics_by_category(category_id)
313
+
314
+ if not topics:
315
+ st.write("No topics in this category yet. Be the first to start a discussion!")
316
+ else:
317
+ # Display topics
318
+ for topic in topics:
319
+ with st.container():
320
+ col1, col2, col3 = st.columns([3, 1, 1])
321
+
322
+ with col1:
323
+ title = topic["title"]
324
+ if topic["is_pinned"]:
325
+ title = "📌 " + title
326
+ if topic["is_locked"]:
327
+ title = "🔒 " + title
328
+
329
+ if st.button(title, key=f"topic_{topic['id']}"):
330
+ st.session_state.forum_view = "topic"
331
+ st.session_state.forum_topic = topic['id']
332
+ st.experimental_rerun()
333
+
334
+ with col2:
335
+ st.write(f"👁️ {topic['views']} | ❤️ {topic['likes']}")
336
+
337
+ with col3:
338
+ st.write(f"by {topic['author']}")
339
+ st.write(f"{topic['created_at']}")
340
+
341
+ st.markdown("---")
342
+
343
+ def new_topic_form(category_id):
344
+ db = initialize_forum_db()
345
+
346
+ # Find category name
347
+ category_name = "Unknown Category"
348
+ for category in db["categories"]:
349
+ if category["id"] == category_id:
350
+ category_name = category["name"]
351
+ break
352
+
353
+ st.subheader(f"New Topic in {category_name}")
354
+
355
+ # Back button
356
+ if st.button("← Back to Topics"):
357
+ st.session_state.forum_view = "topics"
358
+ st.experimental_rerun()
359
+
360
+ # Topic form
361
+ title = st.text_input("Topic Title")
362
+ content = st.text_area("Content", height=200)
363
+
364
+ if st.button("Create Topic"):
365
+ if title and content:
366
+ success, result = create_topic(
367
+ category_id,
368
+ title,
369
+ content,
370
+ st.session_state.username
371
+ )
372
+
373
+ if success:
374
+ st.success("Topic created successfully!")
375
+ st.session_state.forum_view = "topic"
376
+ st.session_state.forum_topic = result
377
+ st.experimental_rerun()
378
+ else:
379
+ st.error(result)
380
+ else:
381
+ st.warning("Please fill in both title and content")
382
+
383
+ def view_topic(topic_id):
384
+ topic = get_topic(topic_id)
385
+
386
+ if not topic:
387
+ st.error("Topic not found")
388
+ if st.button("Back to Categories"):
389
+ st.session_state.forum_view = "categories"
390
+ st.session_state.forum_topic = None
391
+ st.experimental_rerun()
392
+ return
393
+
394
+ st.subheader(topic["title"])
395
+
396
+ # Back button
397
+ if st.button("← Back to Topics"):
398
+ st.session_state.forum_view = "topics"
399
+ st.session_state.forum_topic = None
400
+ st.experimental_rerun()
401
+
402
+ # Topic metadata
403
+ st.write(f"Started by {topic['author']} on {topic['created_at']}")
404
+ st.write(f"👁️ {topic['views']} views | ❤️ {topic['likes']} likes")
405
+
406
+ # Like button
407
+ if st.session_state.get("logged_in", False):
408
+ if st.button("❤️ Like", key="like_topic"):
409
+ like_topic(topic_id, st.session_state.username)
410
+ st.experimental_rerun()
411
+
412
+ st.markdown("---")
413
+
414
+ # Get posts
415
+ posts = get_posts_by_topic(topic_id)
416
+
417
+ # Display posts
418
+ for post in posts:
419
+ with st.container():
420
+ st.write(f"**{post['author']}** - {post['created_at']}")
421
+ st.write(post["content"])
422
+
423
+ # Like button for post
424
+ col1, col2 = st.columns([1, 10])
425
+ with col1:
426
+ if st.session_state.get("logged_in", False):
427
+ if st.button("👍", key=f"like_post_{post['id']}"):
428
+ like_post(post['id'], st.session_state.username)
429
+ st.experimental_rerun()
430
+ with col2:
431
+ st.write(f"{post['likes']} likes")
432
+
433
+ # Reply button
434
+ if st.session_state.get("logged_in", False) and not topic["is_locked"]:
435
+ if st.button("Reply", key=f"reply_button_{post['id']}"):
436
+ st.session_state.replying_to = post['id']
437
+ st.experimental_rerun()
438
+
439
+ # Reply form
440
+ if st.session_state.get("replying_to") == post['id']:
441
+ reply_content = st.text_area("Your reply", key=f"reply_{post['id']}", height=100)
442
+
443
+ col1, col2 = st.columns([1, 5])
444
+ with col1:
445
+ if st.button("Submit", key=f"submit_reply_{post['id']}"):
446
+ if reply_content:
447
+ success, _ = create_reply(
448
+ post['id'],
449
+ reply_content,
450
+ st.session_state.username
451
+ )
452
+
453
+ if success:
454
+ st.session_state.replying_to = None
455
+ st.experimental_rerun()
456
+ else:
457
+ st.warning("Please enter a reply")
458
+ with col2:
459
+ if st.button("Cancel", key=f"cancel_reply_{post['id']}"):
460
+ st.session_state.replying_to = None
461
+ st.experimental_rerun()
462
+
463
+ # Display replies
464
+ if post["replies"]:
465
+ with st.expander(f"View {len(post['replies'])} replies"):
466
+ for reply in post["replies"]:
467
+ st.write(f"**{reply['author']}** - {reply['created_at']}")
468
+ st.write(reply["content"])
469
+ st.write(f"{reply['likes']} likes")
470
+ st.markdown("---")
471
+
472
+ st.markdown("---")
473
+
474
+ # Reply to topic
475
+ if st.session_state.get("logged_in", False) and not topic["is_locked"]:
476
+ st.subheader("Add a Reply")
477
+ reply_content = st.text_area("Your reply", key="main_reply", height=150)
478
+
479
+ if st.button("Post Reply"):
480
+ if reply_content:
481
+ # Get the first post (original post)
482
+ original_post_id = posts[0]["id"] if posts else None
483
+
484
+ if original_post_id:
485
+ success, _ = create_reply(
486
+ original_post_id,
487
+ reply_content,
488
+ st.session_state.username
489
+ )
490
+
491
+ if success:
492
+ st.success("Reply posted successfully!")
493
+ st.experimental_rerun()
494
+ else:
495
+ st.error("Could not find the original post")
496
+ else:
497
+ st.warning("Please enter a reply")
498
+ elif not st.session_state.get("logged_in", False):
499
+ st.info("Please log in to reply")
500
+ elif topic["is_locked"]:
501
+ st.warning("This topic is locked and cannot be replied to")
502
+
503
+ def forum_search():
504
+ st.subheader("Search the Forum")
505
+
506
+ query = st.text_input("Search for topics and posts")
507
+
508
+ if query:
509
+ results = search_forum(query)
510
+
511
+ if not results["topics"] and not results["posts"]:
512
+ st.write("No results found")
513
+ else:
514
+ st.write(f"Found {len(results['topics'])} topics and {len(results['posts'])} posts")
515
+
516
+ # Display topic results
517
+ if results["topics"]:
518
+ st.subheader("Topics")
519
+ for topic in results["topics"]:
520
+ if st.button(topic["title"], key=f"search_topic_{topic['id']}"):
521
+ st.session_state.forum_view = "topic"
522
+ st.session_state.forum_topic = topic['id']
523
+ st.experimental_rerun()
524
+ st.write(f"by {topic['author']} on {topic['created_at']}")
525
+ st.markdown("---")
526
+
527
+ def forum_page():
528
+ # Initialize session state variables if they don't exist
529
+ if "forum_view" not in st.session_state:
530
+ st.session_state.forum_view = "categories"
531
+
532
+ if "forum_category" not in st.session_state:
533
+ st.session_state.forum_category = None
534
+
535
+ if "forum_topic" not in st.session_state:
536
+ st.session_state.forum_topic = None
537
+
538
+ if "replying_to" not in st.session_state:
539
+ st.session_state.replying_to = None
540
+
541
+ # Search box in sidebar
542
+ with st.sidebar:
543
+ st.subheader("Forum Search")
544
+ search_query = st.text_input("Search", key="forum_search")
545
+ if search_query:
546
+ st.session_state.forum_view = "search"
547
+ st.experimental_rerun()
548
+
549
+ # Display the appropriate view
550
+ if st.session_state.forum_view == "categories":
551
+ forum_categories()
552
+ elif st.session_state.forum_view == "topics" and st.session_state.forum_category:
553
+ forum_topics(st.session_state.forum_category)
554
+ elif st.session_state.forum_view == "topic" and st.session_state.forum_topic:
555
+ view_topic(st.session_state.forum_topic)
556
+ elif st.session_state.forum_view == "new_topic" and st.session_state.forum_category:
557
+ new_topic_form(st.session_state.forum_category)
558
+ elif st.session_state.forum_view == "search":
559
+ forum_search()
560
+ else:
561
+ # Default to categories view
562
+ st.session_state.forum_view = "categories"
563
+ forum_categories()
AfyaMindSpace/forum_data.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"categories": [{"id": "general", "name": "General Discussion", "description": "General topics related to mental health and wellbeing"}, {"id": "stress", "name": "Stress Management", "description": "Discuss strategies for managing stress and anxiety"}, {"id": "mindfulness", "name": "Mindfulness & Meditation", "description": "Share experiences and tips about mindfulness practices"}, {"id": "support", "name": "Peer Support", "description": "A safe space to seek support from others"}, {"id": "success", "name": "Success Stories", "description": "Share your mental health journey and achievements"}], "topics": {}, "posts": {}}
AfyaMindSpace/goals.py ADDED
@@ -0,0 +1,778 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import json
3
+ import os
4
+ from datetime import datetime, timedelta
5
+ import pandas as pd
6
+ import altair as alt
7
+
8
+ # File to store goals data
9
+ GOALS_DB_FILE = "goals_data.json"
10
+
11
+ # Initialize goals database
12
+ def initialize_goals_db():
13
+ if not os.path.exists(GOALS_DB_FILE):
14
+ goals_data = {
15
+ "goals": {},
16
+ "templates": [
17
+ {
18
+ "id": "stress_reduction",
19
+ "title": "Stress Reduction",
20
+ "description": "Develop habits to reduce and manage stress in your daily life.",
21
+ "suggested_activities": [
22
+ "Practice deep breathing for 5 minutes",
23
+ "Take a short walk outside",
24
+ "Write in a journal",
25
+ "Complete a guided meditation",
26
+ "Do a body scan relaxation exercise"
27
+ ],
28
+ "duration_options": [7, 14, 30],
29
+ "category": "Stress Management",
30
+ "icon": "🧘"
31
+ },
32
+ {
33
+ "id": "mood_tracking",
34
+ "title": "Consistent Mood Tracking",
35
+ "description": "Build a habit of tracking your mood daily to identify patterns.",
36
+ "suggested_activities": [
37
+ "Record your mood in the morning",
38
+ "Record your mood in the evening",
39
+ "Note what influenced your mood today",
40
+ "Reflect on mood patterns from the past week"
41
+ ],
42
+ "duration_options": [7, 14, 30],
43
+ "category": "Self-Awareness",
44
+ "icon": "📊"
45
+ },
46
+ {
47
+ "id": "positive_thinking",
48
+ "title": "Positive Thinking Practice",
49
+ "description": "Train your mind to focus more on positive aspects of life.",
50
+ "suggested_activities": [
51
+ "Write down three things you're grateful for",
52
+ "Give someone a genuine compliment",
53
+ "Reframe a negative thought into a positive one",
54
+ "Practice positive affirmations",
55
+ "Notice and appreciate small joys"
56
+ ],
57
+ "duration_options": [7, 14, 21],
58
+ "category": "Emotional Wellbeing",
59
+ "icon": "✨"
60
+ },
61
+ {
62
+ "id": "social_connection",
63
+ "title": "Strengthen Social Connections",
64
+ "description": "Build and maintain meaningful social relationships.",
65
+ "suggested_activities": [
66
+ "Reach out to a friend or family member",
67
+ "Have a meaningful conversation with someone",
68
+ "Participate in a group activity",
69
+ "Practice active listening",
70
+ "Express appreciation to someone important to you"
71
+ ],
72
+ "duration_options": [7, 14, 30],
73
+ "category": "Social Skills",
74
+ "icon": "👥"
75
+ },
76
+ {
77
+ "id": "mindfulness",
78
+ "title": "Daily Mindfulness Practice",
79
+ "description": "Develop a regular mindfulness practice to stay present and aware.",
80
+ "suggested_activities": [
81
+ "Practice mindful eating for one meal",
82
+ "Do a 5-minute mindfulness meditation",
83
+ "Take a mindful walk focusing on your senses",
84
+ "Practice mindful breathing for 3 minutes",
85
+ "Do a mindful check-in during a stressful moment"
86
+ ],
87
+ "duration_options": [7, 14, 30],
88
+ "category": "Mindfulness",
89
+ "icon": "🌿"
90
+ },
91
+ {
92
+ "id": "custom",
93
+ "title": "Custom Goal",
94
+ "description": "Create your own personalized mental health goal.",
95
+ "suggested_activities": [],
96
+ "duration_options": [7, 14, 21, 30],
97
+ "category": "Custom",
98
+ "icon": "🎯"
99
+ }
100
+ ]
101
+ }
102
+ with open(GOALS_DB_FILE, "w") as f:
103
+ json.dump(goals_data, f)
104
+ return goals_data
105
+
106
+ try:
107
+ with open(GOALS_DB_FILE, "r") as f:
108
+ return json.load(f)
109
+ except json.JSONDecodeError:
110
+ # If file is corrupted, create a new one
111
+ goals_data = {
112
+ "goals": {},
113
+ "templates": [
114
+ {
115
+ "id": "stress_reduction",
116
+ "title": "Stress Reduction",
117
+ "description": "Develop habits to reduce and manage stress in your daily life.",
118
+ "suggested_activities": [
119
+ "Practice deep breathing for 5 minutes",
120
+ "Take a short walk outside",
121
+ "Write in a journal",
122
+ "Complete a guided meditation",
123
+ "Do a body scan relaxation exercise"
124
+ ],
125
+ "duration_options": [7, 14, 30],
126
+ "category": "Stress Management",
127
+ "icon": "🧘"
128
+ },
129
+ {
130
+ "id": "mood_tracking",
131
+ "title": "Consistent Mood Tracking",
132
+ "description": "Build a habit of tracking your mood daily to identify patterns.",
133
+ "suggested_activities": [
134
+ "Record your mood in the morning",
135
+ "Record your mood in the evening",
136
+ "Note what influenced your mood today",
137
+ "Reflect on mood patterns from the past week"
138
+ ],
139
+ "duration_options": [7, 14, 30],
140
+ "category": "Self-Awareness",
141
+ "icon": "📊"
142
+ },
143
+ {
144
+ "id": "positive_thinking",
145
+ "title": "Positive Thinking Practice",
146
+ "description": "Train your mind to focus more on positive aspects of life.",
147
+ "suggested_activities": [
148
+ "Write down three things you're grateful for",
149
+ "Give someone a genuine compliment",
150
+ "Reframe a negative thought into a positive one",
151
+ "Practice positive affirmations",
152
+ "Notice and appreciate small joys"
153
+ ],
154
+ "duration_options": [7, 14, 21],
155
+ "category": "Emotional Wellbeing",
156
+ "icon": "✨"
157
+ },
158
+ {
159
+ "id": "social_connection",
160
+ "title": "Strengthen Social Connections",
161
+ "description": "Build and maintain meaningful social relationships.",
162
+ "suggested_activities": [
163
+ "Reach out to a friend or family member",
164
+ "Have a meaningful conversation with someone",
165
+ "Participate in a group activity",
166
+ "Practice active listening",
167
+ "Express appreciation to someone important to you"
168
+ ],
169
+ "duration_options": [7, 14, 30],
170
+ "category": "Social Skills",
171
+ "icon": "👥"
172
+ },
173
+ {
174
+ "id": "mindfulness",
175
+ "title": "Daily Mindfulness Practice",
176
+ "description": "Develop a regular mindfulness practice to stay present and aware.",
177
+ "suggested_activities": [
178
+ "Practice mindful eating for one meal",
179
+ "Do a 5-minute mindfulness meditation",
180
+ "Take a mindful walk focusing on your senses",
181
+ "Practice mindful breathing for 3 minutes",
182
+ "Do a mindful check-in during a stressful moment"
183
+ ],
184
+ "duration_options": [7, 14, 30],
185
+ "category": "Mindfulness",
186
+ "icon": "🌿"
187
+ },
188
+ {
189
+ "id": "custom",
190
+ "title": "Custom Goal",
191
+ "description": "Create your own personalized mental health goal.",
192
+ "suggested_activities": [],
193
+ "duration_options": [7, 14, 21, 30],
194
+ "category": "Custom",
195
+ "icon": "🎯"
196
+ }
197
+ ]
198
+ }
199
+ with open(GOALS_DB_FILE, "w") as f:
200
+ json.dump(goals_data, f)
201
+ return goals_data
202
+
203
+ # Save goals database
204
+ def save_goals_db(db):
205
+ with open(GOALS_DB_FILE, "w") as f:
206
+ json.dump(db, f)
207
+
208
+ # Get all goal templates
209
+ def get_goal_templates():
210
+ db = initialize_goals_db()
211
+ return db["templates"]
212
+
213
+ # Get goal template by ID
214
+ def get_goal_template(template_id):
215
+ db = initialize_goals_db()
216
+
217
+ for template in db["templates"]:
218
+ if template["id"] == template_id:
219
+ return template
220
+
221
+ return None
222
+
223
+ # Create a new goal for a user
224
+ def create_goal(username, template_id, title, description, activities, duration, start_date=None):
225
+ if not username:
226
+ return False, "User not logged in"
227
+
228
+ db = initialize_goals_db()
229
+
230
+ # Generate a unique goal ID
231
+ goal_id = f"goal_{len(db['goals']) + 1}_{datetime.now().strftime('%Y%m%d%H%M%S')}"
232
+
233
+ # Set start date to today if not provided
234
+ if not start_date:
235
+ start_date = datetime.now().strftime("%Y-%m-%d")
236
+
237
+ # Calculate end date
238
+ start_datetime = datetime.strptime(start_date, "%Y-%m-%d")
239
+ end_date = (start_datetime + timedelta(days=duration)).strftime("%Y-%m-%d")
240
+
241
+ # Create the goal
242
+ if username not in db["goals"]:
243
+ db["goals"][username] = {}
244
+
245
+ db["goals"][username][goal_id] = {
246
+ "id": goal_id,
247
+ "template_id": template_id,
248
+ "title": title,
249
+ "description": description,
250
+ "activities": activities,
251
+ "duration": duration,
252
+ "start_date": start_date,
253
+ "end_date": end_date,
254
+ "progress": {},
255
+ "completed": False,
256
+ "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
257
+ }
258
+
259
+ save_goals_db(db)
260
+ return True, goal_id
261
+
262
+ # Get all goals for a user
263
+ def get_user_goals(username):
264
+ if not username:
265
+ return []
266
+
267
+ db = initialize_goals_db()
268
+
269
+ if username not in db["goals"]:
270
+ return []
271
+
272
+ # Convert to list and sort by creation date (newest first)
273
+ goals = list(db["goals"][username].values())
274
+ goals.sort(key=lambda x: x["created_at"], reverse=True)
275
+
276
+ return goals
277
+
278
+ # Get active goals for a user
279
+ def get_active_goals(username):
280
+ goals = get_user_goals(username)
281
+
282
+ # Filter for active goals (not completed and end date not passed)
283
+ today = datetime.now().strftime("%Y-%m-%d")
284
+ active_goals = [g for g in goals if not g["completed"] and g["end_date"] >= today]
285
+
286
+ return active_goals
287
+
288
+ # Get a specific goal
289
+ def get_goal(username, goal_id):
290
+ if not username:
291
+ return None
292
+
293
+ db = initialize_goals_db()
294
+
295
+ if username not in db["goals"] or goal_id not in db["goals"][username]:
296
+ return None
297
+
298
+ return db["goals"][username][goal_id]
299
+
300
+ # Update goal progress
301
+ def update_goal_progress(username, goal_id, activity, completed):
302
+ if not username:
303
+ return False, "User not logged in"
304
+
305
+ db = initialize_goals_db()
306
+
307
+ if username not in db["goals"] or goal_id not in db["goals"][username]:
308
+ return False, "Goal not found"
309
+
310
+ goal = db["goals"][username][goal_id]
311
+
312
+ # Check if activity exists in the goal
313
+ if activity not in goal["activities"]:
314
+ return False, "Activity not found in goal"
315
+
316
+ # Get today's date
317
+ today = datetime.now().strftime("%Y-%m-%d")
318
+
319
+ # Initialize progress for today if needed
320
+ if today not in goal["progress"]:
321
+ goal["progress"][today] = []
322
+
323
+ # Update progress
324
+ if completed and activity not in goal["progress"][today]:
325
+ goal["progress"][today].append(activity)
326
+ elif not completed and activity in goal["progress"][today]:
327
+ goal["progress"][today].remove(activity)
328
+
329
+ save_goals_db(db)
330
+ return True, "Progress updated"
331
+
332
+ # Mark goal as completed
333
+ def complete_goal(username, goal_id):
334
+ if not username:
335
+ return False, "User not logged in"
336
+
337
+ db = initialize_goals_db()
338
+
339
+ if username not in db["goals"] or goal_id not in db["goals"][username]:
340
+ return False, "Goal not found"
341
+
342
+ db["goals"][username][goal_id]["completed"] = True
343
+
344
+ save_goals_db(db)
345
+ return True, "Goal marked as completed"
346
+
347
+ # Calculate goal statistics
348
+ def calculate_goal_stats(username):
349
+ goals = get_user_goals(username)
350
+
351
+ if not goals:
352
+ return {
353
+ "total": 0,
354
+ "active": 0,
355
+ "completed": 0,
356
+ "expired": 0,
357
+ "streak": 0,
358
+ "completion_rate": 0
359
+ }
360
+
361
+ today = datetime.now().strftime("%Y-%m-%d")
362
+ yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
363
+
364
+ # Count goals by status
365
+ total = len(goals)
366
+ completed = sum(1 for g in goals if g["completed"])
367
+ expired = sum(1 for g in goals if not g["completed"] and g["end_date"] < today)
368
+ active = total - completed - expired
369
+
370
+ # Calculate completion rate
371
+ completion_rate = (completed / total) * 100 if total > 0 else 0
372
+
373
+ # Calculate activity streak
374
+ streak = 0
375
+ check_date = yesterday
376
+ had_activity = False
377
+
378
+ while True:
379
+ # Check if any goal had activity on this date
380
+ for goal in goals:
381
+ if check_date in goal["progress"] and goal["progress"][check_date]:
382
+ had_activity = True
383
+ break
384
+
385
+ if had_activity:
386
+ streak += 1
387
+ # Move to previous day
388
+ check_date = (datetime.strptime(check_date, "%Y-%m-%d") - timedelta(days=1)).strftime("%Y-%m-%d")
389
+ had_activity = False
390
+ else:
391
+ break
392
+
393
+ return {
394
+ "total": total,
395
+ "active": active,
396
+ "completed": completed,
397
+ "expired": expired,
398
+ "streak": streak,
399
+ "completion_rate": round(completion_rate, 1)
400
+ }
401
+
402
+ # Goals UI components
403
+ def goals_dashboard():
404
+ st.subheader("Your Mental Health Goals")
405
+
406
+ if not st.session_state.get("logged_in", False):
407
+ st.info("Please log in to set and track your mental health goals")
408
+ return
409
+
410
+ # Get user goals
411
+ active_goals = get_active_goals(st.session_state.username)
412
+
413
+ # Stats
414
+ stats = calculate_goal_stats(st.session_state.username)
415
+
416
+ # Display stats
417
+ col1, col2, col3, col4 = st.columns(4)
418
+
419
+ with col1:
420
+ st.metric("Active Goals", stats["active"])
421
+
422
+ with col2:
423
+ st.metric("Completed", stats["completed"])
424
+
425
+ with col3:
426
+ st.metric("Activity Streak", f"{stats['streak']} days")
427
+
428
+ with col4:
429
+ st.metric("Completion Rate", f"{stats['completion_rate']}%")
430
+
431
+ # Create new goal button
432
+ if st.button("+ Create New Goal"):
433
+ st.session_state.goals_view = "new_goal"
434
+ st.experimental_rerun()
435
+
436
+ # Display active goals
437
+ if not active_goals:
438
+ st.write("You don't have any active goals. Create one to get started!")
439
+ else:
440
+ st.subheader("Active Goals")
441
+
442
+ for goal in active_goals:
443
+ with st.container():
444
+ # Calculate days remaining
445
+ end_date = datetime.strptime(goal["end_date"], "%Y-%m-%d")
446
+ today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
447
+ days_remaining = (end_date - today).days
448
+
449
+ # Calculate progress percentage
450
+ total_days = goal["duration"]
451
+ days_passed = total_days - days_remaining
452
+ time_progress = min(100, max(0, (days_passed / total_days) * 100))
453
+
454
+ # Calculate activity completion
455
+ today_str = datetime.now().strftime("%Y-%m-%d")
456
+ activities_today = goal["progress"].get(today_str, [])
457
+ activities_completed = len(activities_today)
458
+ activities_total = len(goal["activities"])
459
+ activity_progress = (activities_completed / activities_total) * 100 if activities_total > 0 else 0
460
+
461
+ # Display goal card
462
+ st.markdown(f"### {goal['title']}")
463
+ st.write(goal["description"])
464
+ st.write(f"**Days remaining:** {days_remaining} of {goal['duration']}")
465
+
466
+ # Progress bars
467
+ st.write("**Time progress:**")
468
+ st.progress(time_progress / 100)
469
+
470
+ st.write(f"**Today's activities:** {activities_completed}/{activities_total}")
471
+ st.progress(activity_progress / 100)
472
+
473
+ # View details button
474
+ if st.button("View Details", key=f"view_{goal['id']}"):
475
+ st.session_state.goals_view = "view_goal"
476
+ st.session_state.current_goal = goal["id"]
477
+ st.experimental_rerun()
478
+
479
+ st.markdown("---")
480
+
481
+ def new_goal_form():
482
+ st.subheader("Create a New Mental Health Goal")
483
+
484
+ # Back button
485
+ if st.button("← Back to Dashboard"):
486
+ st.session_state.goals_view = "dashboard"
487
+ st.experimental_rerun()
488
+
489
+ # Get templates
490
+ templates = get_goal_templates()
491
+
492
+ # Step 1: Select template
493
+ if "goal_step" not in st.session_state:
494
+ st.session_state.goal_step = 1
495
+
496
+ if "selected_template" not in st.session_state:
497
+ st.session_state.selected_template = None
498
+
499
+ if st.session_state.goal_step == 1:
500
+ st.write("Step 1: Select a goal template")
501
+
502
+ # Display templates in a grid
503
+ cols = st.columns(2)
504
+ for i, template in enumerate(templates):
505
+ with cols[i % 2]:
506
+ with st.container():
507
+ st.markdown(f"### {template['icon']} {template['title']}")
508
+ st.write(template["description"])
509
+ st.write(f"Category: {template['category']}")
510
+
511
+ if st.button("Select", key=f"select_{template['id']}"):
512
+ st.session_state.selected_template = template["id"]
513
+ st.session_state.goal_step = 2
514
+ st.experimental_rerun()
515
+
516
+ # Step 2: Customize goal
517
+ elif st.session_state.goal_step == 2 and st.session_state.selected_template:
518
+ template = get_goal_template(st.session_state.selected_template)
519
+
520
+ if not template:
521
+ st.error("Template not found")
522
+ st.session_state.goal_step = 1
523
+ st.experimental_rerun()
524
+ return
525
+
526
+ st.write("Step 2: Customize your goal")
527
+
528
+ # Goal title and description
529
+ title = st.text_input("Goal Title", value=template["title"])
530
+ description = st.text_area("Goal Description", value=template["description"])
531
+
532
+ # Duration
533
+ duration = st.selectbox(
534
+ "Goal Duration (days)",
535
+ template["duration_options"],
536
+ index=0
537
+ )
538
+
539
+ # Start date
540
+ start_date = st.date_input(
541
+ "Start Date",
542
+ value=datetime.now()
543
+ ).strftime("%Y-%m-%d")
544
+
545
+ # Activities
546
+ st.write("Activities to track:")
547
+
548
+ if template["id"] == "custom":
549
+ # For custom goals, let user add their own activities
550
+ if "custom_activities" not in st.session_state:
551
+ st.session_state.custom_activities = [""]
552
+
553
+ for i, activity in enumerate(st.session_state.custom_activities):
554
+ col1, col2 = st.columns([5, 1])
555
+
556
+ with col1:
557
+ st.session_state.custom_activities[i] = st.text_input(
558
+ f"Activity {i+1}",
559
+ value=activity,
560
+ key=f"activity_{i}"
561
+ )
562
+
563
+ with col2:
564
+ if i > 0 and st.button("Remove", key=f"remove_{i}"):
565
+ st.session_state.custom_activities.pop(i)
566
+ st.experimental_rerun()
567
+
568
+ if st.button("+ Add Activity"):
569
+ st.session_state.custom_activities.append("")
570
+ st.experimental_rerun()
571
+
572
+ activities = [a for a in st.session_state.custom_activities if a.strip()]
573
+ else:
574
+ # For predefined templates, let user select from suggested activities
575
+ activities = []
576
+ for activity in template["suggested_activities"]:
577
+ if st.checkbox(activity, value=True):
578
+ activities.append(activity)
579
+
580
+ # Option to add custom activities
581
+ if "additional_activities" not in st.session_state:
582
+ st.session_state.additional_activities = []
583
+
584
+ st.write("Add your own activities:")
585
+
586
+ if "new_activity" not in st.session_state:
587
+ st.session_state.new_activity = ""
588
+
589
+ col1, col2 = st.columns([3, 1])
590
+
591
+ with col1:
592
+ st.session_state.new_activity = st.text_input("New activity")
593
+
594
+ with col2:
595
+ if st.button("Add") and st.session_state.new_activity.strip():
596
+ st.session_state.additional_activities.append(st.session_state.new_activity)
597
+ st.session_state.new_activity = ""
598
+ st.experimental_rerun()
599
+
600
+ for i, activity in enumerate(st.session_state.additional_activities):
601
+ col1, col2 = st.columns([5, 1])
602
+
603
+ with col1:
604
+ if st.checkbox(activity, value=True, key=f"additional_{i}"):
605
+ activities.append(activity)
606
+
607
+ with col2:
608
+ if st.button("Remove", key=f"remove_additional_{i}"):
609
+ st.session_state.additional_activities.pop(i)
610
+ st.experimental_rerun()
611
+
612
+ # Create goal button
613
+ if st.button("Create Goal"):
614
+ if title and description and activities:
615
+ success, goal_id = create_goal(
616
+ st.session_state.username,
617
+ template["id"],
618
+ title,
619
+ description,
620
+ activities,
621
+ duration,
622
+ start_date
623
+ )
624
+
625
+ if success:
626
+ st.success("Goal created successfully!")
627
+ # Reset session state
628
+ st.session_state.goal_step = 1
629
+ st.session_state.selected_template = None
630
+ if "custom_activities" in st.session_state:
631
+ del st.session_state.custom_activities
632
+ if "additional_activities" in st.session_state:
633
+ del st.session_state.additional_activities
634
+ if "new_activity" in st.session_state:
635
+ del st.session_state.new_activity
636
+
637
+ # Go to view goal
638
+ st.session_state.goals_view = "view_goal"
639
+ st.session_state.current_goal = goal_id
640
+ st.experimental_rerun()
641
+ else:
642
+ st.error(goal_id) # Error message
643
+ else:
644
+ st.warning("Please fill in all required fields and add at least one activity")
645
+
646
+ def view_goal(goal_id):
647
+ goal = get_goal(st.session_state.username, goal_id)
648
+
649
+ if not goal:
650
+ st.error("Goal not found")
651
+ st.session_state.goals_view = "dashboard"
652
+ st.experimental_rerun()
653
+ return
654
+
655
+ # Back button
656
+ if st.button("← Back to Dashboard"):
657
+ st.session_state.goals_view = "dashboard"
658
+ st.experimental_rerun()
659
+
660
+ # Goal details
661
+ st.subheader(goal["title"])
662
+ st.write(goal["description"])
663
+
664
+ # Calculate days remaining
665
+ end_date = datetime.strptime(goal["end_date"], "%Y-%m-%d")
666
+ today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
667
+ days_remaining = (end_date - today).days
668
+
669
+ # Display dates and progress
670
+ col1, col2, col3 = st.columns(3)
671
+
672
+ with col1:
673
+ st.write(f"**Start Date:** {goal['start_date']}")
674
+
675
+ with col2:
676
+ st.write(f"**End Date:** {goal['end_date']}")
677
+
678
+ with col3:
679
+ if days_remaining > 0:
680
+ st.write(f"**Days Remaining:** {days_remaining}")
681
+ else:
682
+ st.write("**Status:** Ended")
683
+
684
+ # Calculate overall progress
685
+ total_days = goal["duration"]
686
+ days_passed = total_days - days_remaining
687
+ time_progress = min(100, max(0, (days_passed / total_days) * 100))
688
+
689
+ st.write("**Overall Progress:**")
690
+ st.progress(time_progress / 100)
691
+
692
+ # Today's activities
693
+ st.subheader("Today's Activities")
694
+
695
+ today_str = datetime.now().strftime("%Y-%m-%d")
696
+ today_activities = goal["progress"].get(today_str, [])
697
+
698
+ for activity in goal["activities"]:
699
+ completed = activity in today_activities
700
+ if st.checkbox(activity, value=completed, key=f"activity_{activity}"):
701
+ if not completed:
702
+ update_goal_progress(st.session_state.username, goal_id, activity, True)
703
+ st.experimental_rerun()
704
+ else:
705
+ if completed:
706
+ update_goal_progress(st.session_state.username, goal_id, activity, False)
707
+ st.experimental_rerun()
708
+
709
+ # Progress history
710
+ st.subheader("Progress History")
711
+
712
+ # Create a dataframe for visualization
713
+ history_data = []
714
+
715
+ start_date = datetime.strptime(goal["start_date"], "%Y-%m-%d")
716
+ end_date = datetime.strptime(goal["end_date"], "%Y-%m-%d")
717
+ current_date = min(end_date, datetime.now())
718
+
719
+ date_range = []
720
+ current = start_date
721
+ while current <= current_date:
722
+ date_range.append(current)
723
+ current += timedelta(days=1)
724
+
725
+ for date in date_range:
726
+ date_str = date.strftime("%Y-%m-%d")
727
+ activities_done = len(goal["progress"].get(date_str, []))
728
+ total_activities = len(goal["activities"])
729
+ completion_rate = (activities_done / total_activities) * 100 if total_activities > 0 else 0
730
+
731
+ history_data.append({
732
+ "date": date_str,
733
+ "completion_rate": completion_rate
734
+ })
735
+
736
+ if history_data:
737
+ history_df = pd.DataFrame(history_data)
738
+
739
+ # Create a chart
740
+ chart = alt.Chart(history_df).mark_bar().encode(
741
+ x=alt.X('date:T', title='Date'),
742
+ y=alt.Y('completion_rate:Q', title='Completion Rate (%)')
743
+ ).properties(
744
+ title='Daily Activity Completion',
745
+ width=600,
746
+ height=200
747
+ )
748
+
749
+ st.altair_chart(chart, use_container_width=True)
750
+ else:
751
+ st.write("No progress data available yet.")
752
+
753
+ # Complete goal button
754
+ if not goal["completed"] and days_remaining <= 0:
755
+ if st.button("Mark Goal as Completed"):
756
+ complete_goal(st.session_state.username, goal_id)
757
+ st.success("Goal marked as completed!")
758
+ st.experimental_rerun()
759
+
760
+ def goals_page():
761
+ # Initialize session state variables if they don't exist
762
+ if "goals_view" not in st.session_state:
763
+ st.session_state.goals_view = "dashboard"
764
+
765
+ if "current_goal" not in st.session_state:
766
+ st.session_state.current_goal = None
767
+
768
+ # Display the appropriate view
769
+ if st.session_state.goals_view == "dashboard":
770
+ goals_dashboard()
771
+ elif st.session_state.goals_view == "new_goal":
772
+ new_goal_form()
773
+ elif st.session_state.goals_view == "view_goal" and st.session_state.current_goal:
774
+ view_goal(st.session_state.current_goal)
775
+ else:
776
+ # Default to dashboard view
777
+ st.session_state.goals_view = "dashboard"
778
+ goals_dashboard()
AfyaMindSpace/goals_data.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"goals": {}, "templates": [{"id": "stress_reduction", "title": "Stress Reduction", "description": "Develop habits to reduce and manage stress in your daily life.", "suggested_activities": ["Practice deep breathing for 5 minutes", "Take a short walk outside", "Write in a journal", "Complete a guided meditation", "Do a body scan relaxation exercise"], "duration_options": [7, 14, 30], "category": "Stress Management", "icon": "\ud83e\uddd8"}, {"id": "mood_tracking", "title": "Consistent Mood Tracking", "description": "Build a habit of tracking your mood daily to identify patterns.", "suggested_activities": ["Record your mood in the morning", "Record your mood in the evening", "Note what influenced your mood today", "Reflect on mood patterns from the past week"], "duration_options": [7, 14, 30], "category": "Self-Awareness", "icon": "\ud83d\udcca"}, {"id": "positive_thinking", "title": "Positive Thinking Practice", "description": "Train your mind to focus more on positive aspects of life.", "suggested_activities": ["Write down three things you're grateful for", "Give someone a genuine compliment", "Reframe a negative thought into a positive one", "Practice positive affirmations", "Notice and appreciate small joys"], "duration_options": [7, 14, 21], "category": "Emotional Wellbeing", "icon": "\u2728"}, {"id": "social_connection", "title": "Strengthen Social Connections", "description": "Build and maintain meaningful social relationships.", "suggested_activities": ["Reach out to a friend or family member", "Have a meaningful conversation with someone", "Participate in a group activity", "Practice active listening", "Express appreciation to someone important to you"], "duration_options": [7, 14, 30], "category": "Social Skills", "icon": "\ud83d\udc65"}, {"id": "mindfulness", "title": "Daily Mindfulness Practice", "description": "Develop a regular mindfulness practice to stay present and aware.", "suggested_activities": ["Practice mindful eating for one meal", "Do a 5-minute mindfulness meditation", "Take a mindful walk focusing on your senses", "Practice mindful breathing for 3 minutes", "Do a mindful check-in during a stressful moment"], "duration_options": [7, 14, 30], "category": "Mindfulness", "icon": "\ud83c\udf3f"}, {"id": "custom", "title": "Custom Goal", "description": "Create your own personalized mental health goal.", "suggested_activities": [], "duration_options": [7, 14, 21, 30], "category": "Custom", "icon": "\ud83c\udfaf"}]}
AfyaMindSpace/meditation.py ADDED
@@ -0,0 +1,563 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import time
3
+ import json
4
+ import os
5
+ from datetime import datetime
6
+
7
+ # File to store meditation data
8
+ MEDITATION_DB_FILE = "meditation_data.json"
9
+
10
+ # Initialize meditation database
11
+ def initialize_meditation_db():
12
+ if not os.path.exists(MEDITATION_DB_FILE):
13
+ meditation_data = {
14
+ "sessions": [
15
+ {
16
+ "id": "breathing",
17
+ "title": "Deep Breathing Exercise",
18
+ "description": "A simple breathing exercise to help calm your mind and reduce stress.",
19
+ "duration": 5,
20
+ "difficulty": "Beginner",
21
+ "category": "Stress Relief",
22
+ "steps": [
23
+ "Find a comfortable position and close your eyes.",
24
+ "Take a deep breath in through your nose for 4 seconds.",
25
+ "Hold your breath for 2 seconds.",
26
+ "Exhale slowly through your mouth for 6 seconds.",
27
+ "Repeat this breathing pattern for the duration of the session."
28
+ ],
29
+ "background": "#E6F7FF"
30
+ },
31
+ {
32
+ "id": "body_scan",
33
+ "title": "Body Scan Meditation",
34
+ "description": "A guided meditation to help you become aware of sensations throughout your body.",
35
+ "duration": 10,
36
+ "difficulty": "Intermediate",
37
+ "category": "Mindfulness",
38
+ "steps": [
39
+ "Lie down or sit in a comfortable position and close your eyes.",
40
+ "Begin by bringing awareness to your breath, noticing the natural rhythm.",
41
+ "Slowly shift your attention to your feet, noticing any sensations.",
42
+ "Gradually move your awareness up through your legs, torso, arms, and head.",
43
+ "If you notice any tension, breathe into that area and allow it to relax.",
44
+ "Complete the scan by bringing awareness to your body as a whole."
45
+ ],
46
+ "background": "#F0E6FF"
47
+ },
48
+ {
49
+ "id": "gratitude",
50
+ "title": "Gratitude Meditation",
51
+ "description": "A meditation practice focused on cultivating gratitude and positive emotions.",
52
+ "duration": 7,
53
+ "difficulty": "Beginner",
54
+ "category": "Emotional Wellbeing",
55
+ "steps": [
56
+ "Sit comfortably with your back straight and eyes closed.",
57
+ "Take a few deep breaths to center yourself.",
58
+ "Bring to mind something or someone you're grateful for.",
59
+ "Notice the feelings of appreciation and warmth that arise.",
60
+ "Acknowledge how this person or thing enriches your life.",
61
+ "Expand your awareness to include more things you're grateful for.",
62
+ "Conclude by setting an intention to notice moments of gratitude throughout your day."
63
+ ],
64
+ "background": "#FFF0E6"
65
+ },
66
+ {
67
+ "id": "loving_kindness",
68
+ "title": "Loving-Kindness Meditation",
69
+ "description": "A practice to develop feelings of goodwill, kindness, and warmth towards others.",
70
+ "duration": 12,
71
+ "difficulty": "Intermediate",
72
+ "category": "Compassion",
73
+ "steps": [
74
+ "Sit in a comfortable position with your eyes closed.",
75
+ "Begin by focusing on your breath, allowing yourself to relax.",
76
+ "Bring to mind someone you care about deeply.",
77
+ "Silently repeat phrases like 'May you be happy. May you be healthy. May you be safe.'",
78
+ "Next, direct these wishes toward yourself: 'May I be happy. May I be healthy. May I be safe.'",
79
+ "Gradually extend these wishes to others: acquaintances, difficult people, and all beings.",
80
+ "End by taking a few deep breaths and slowly opening your eyes."
81
+ ],
82
+ "background": "#E6FFE6"
83
+ },
84
+ {
85
+ "id": "visualization",
86
+ "title": "Peaceful Place Visualization",
87
+ "description": "A guided visualization to help you relax by imagining a peaceful, safe place.",
88
+ "duration": 8,
89
+ "difficulty": "Beginner",
90
+ "category": "Relaxation",
91
+ "steps": [
92
+ "Find a comfortable position and close your eyes.",
93
+ "Take several deep breaths, allowing your body to relax.",
94
+ "Imagine a place where you feel completely peaceful and safe.",
95
+ "Notice the details: What do you see? What sounds do you hear?",
96
+ "Experience the sensations: What do you feel? What scents are present?",
97
+ "Allow yourself to fully immerse in this peaceful place.",
98
+ "When ready, slowly bring your awareness back to the present moment."
99
+ ],
100
+ "background": "#E6FFFF"
101
+ }
102
+ ],
103
+ "user_progress": {}
104
+ }
105
+ with open(MEDITATION_DB_FILE, "w") as f:
106
+ json.dump(meditation_data, f)
107
+ return meditation_data
108
+
109
+ try:
110
+ with open(MEDITATION_DB_FILE, "r") as f:
111
+ return json.load(f)
112
+ except json.JSONDecodeError:
113
+ # If file is corrupted, create a new one
114
+ meditation_data = {
115
+ "sessions": [
116
+ {
117
+ "id": "breathing",
118
+ "title": "Deep Breathing Exercise",
119
+ "description": "A simple breathing exercise to help calm your mind and reduce stress.",
120
+ "duration": 5,
121
+ "difficulty": "Beginner",
122
+ "category": "Stress Relief",
123
+ "steps": [
124
+ "Find a comfortable position and close your eyes.",
125
+ "Take a deep breath in through your nose for 4 seconds.",
126
+ "Hold your breath for 2 seconds.",
127
+ "Exhale slowly through your mouth for 6 seconds.",
128
+ "Repeat this breathing pattern for the duration of the session."
129
+ ],
130
+ "background": "#E6F7FF"
131
+ },
132
+ {
133
+ "id": "body_scan",
134
+ "title": "Body Scan Meditation",
135
+ "description": "A guided meditation to help you become aware of sensations throughout your body.",
136
+ "duration": 10,
137
+ "difficulty": "Intermediate",
138
+ "category": "Mindfulness",
139
+ "steps": [
140
+ "Lie down or sit in a comfortable position and close your eyes.",
141
+ "Begin by bringing awareness to your breath, noticing the natural rhythm.",
142
+ "Slowly shift your attention to your feet, noticing any sensations.",
143
+ "Gradually move your awareness up through your legs, torso, arms, and head.",
144
+ "If you notice any tension, breathe into that area and allow it to relax.",
145
+ "Complete the scan by bringing awareness to your body as a whole."
146
+ ],
147
+ "background": "#F0E6FF"
148
+ },
149
+ {
150
+ "id": "gratitude",
151
+ "title": "Gratitude Meditation",
152
+ "description": "A meditation practice focused on cultivating gratitude and positive emotions.",
153
+ "duration": 7,
154
+ "difficulty": "Beginner",
155
+ "category": "Emotional Wellbeing",
156
+ "steps": [
157
+ "Sit comfortably with your back straight and eyes closed.",
158
+ "Take a few deep breaths to center yourself.",
159
+ "Bring to mind something or someone you're grateful for.",
160
+ "Notice the feelings of appreciation and warmth that arise.",
161
+ "Acknowledge how this person or thing enriches your life.",
162
+ "Expand your awareness to include more things you're grateful for.",
163
+ "Conclude by setting an intention to notice moments of gratitude throughout your day."
164
+ ],
165
+ "background": "#FFF0E6"
166
+ },
167
+ {
168
+ "id": "loving_kindness",
169
+ "title": "Loving-Kindness Meditation",
170
+ "description": "A practice to develop feelings of goodwill, kindness, and warmth towards others.",
171
+ "duration": 12,
172
+ "difficulty": "Intermediate",
173
+ "category": "Compassion",
174
+ "steps": [
175
+ "Sit in a comfortable position with your eyes closed.",
176
+ "Begin by focusing on your breath, allowing yourself to relax.",
177
+ "Bring to mind someone you care about deeply.",
178
+ "Silently repeat phrases like 'May you be happy. May you be healthy. May you be safe.'",
179
+ "Next, direct these wishes toward yourself: 'May I be happy. May I be healthy. May I be safe.'",
180
+ "Gradually extend these wishes to others: acquaintances, difficult people, and all beings.",
181
+ "End by taking a few deep breaths and slowly opening your eyes."
182
+ ],
183
+ "background": "#E6FFE6"
184
+ },
185
+ {
186
+ "id": "visualization",
187
+ "title": "Peaceful Place Visualization",
188
+ "description": "A guided visualization to help you relax by imagining a peaceful, safe place.",
189
+ "duration": 8,
190
+ "difficulty": "Beginner",
191
+ "category": "Relaxation",
192
+ "steps": [
193
+ "Find a comfortable position and close your eyes.",
194
+ "Take several deep breaths, allowing your body to relax.",
195
+ "Imagine a place where you feel completely peaceful and safe.",
196
+ "Notice the details: What do you see? What sounds do you hear?",
197
+ "Experience the sensations: What do you feel? What scents are present?",
198
+ "Allow yourself to fully immerse in this peaceful place.",
199
+ "When ready, slowly bring your awareness back to the present moment."
200
+ ],
201
+ "background": "#E6FFFF"
202
+ }
203
+ ],
204
+ "user_progress": {}
205
+ }
206
+ with open(MEDITATION_DB_FILE, "w") as f:
207
+ json.dump(meditation_data, f)
208
+ return meditation_data
209
+
210
+ # Save meditation database
211
+ def save_meditation_db(db):
212
+ with open(MEDITATION_DB_FILE, "w") as f:
213
+ json.dump(db, f)
214
+
215
+ # Get all meditation sessions
216
+ def get_meditation_sessions():
217
+ db = initialize_meditation_db()
218
+ return db["sessions"]
219
+
220
+ # Get meditation session by ID
221
+ def get_meditation_session(session_id):
222
+ db = initialize_meditation_db()
223
+
224
+ for session in db["sessions"]:
225
+ if session["id"] == session_id:
226
+ return session
227
+
228
+ return None
229
+
230
+ # Record completed meditation session
231
+ def record_meditation_completion(username, session_id, duration):
232
+ if not username:
233
+ return False, "User not logged in"
234
+
235
+ db = initialize_meditation_db()
236
+
237
+ # Check if session exists
238
+ session_exists = False
239
+ for session in db["sessions"]:
240
+ if session["id"] == session_id:
241
+ session_exists = True
242
+ break
243
+
244
+ if not session_exists:
245
+ return False, "Meditation session not found"
246
+
247
+ # Initialize user progress if needed
248
+ if username not in db["user_progress"]:
249
+ db["user_progress"][username] = {
250
+ "completed_sessions": [],
251
+ "total_minutes": 0,
252
+ "streak": 0,
253
+ "last_completed": None
254
+ }
255
+
256
+ # Check if this is a new day completion
257
+ today = datetime.now().strftime("%Y-%m-%d")
258
+ if db["user_progress"][username]["last_completed"] != today:
259
+ # Check if the streak should continue or reset
260
+ if db["user_progress"][username]["last_completed"] is None:
261
+ db["user_progress"][username]["streak"] = 1
262
+ else:
263
+ last_date = datetime.strptime(db["user_progress"][username]["last_completed"], "%Y-%m-%d")
264
+ today_date = datetime.strptime(today, "%Y-%m-%d")
265
+ days_diff = (today_date - last_date).days
266
+
267
+ if days_diff == 1:
268
+ # Consecutive day, increase streak
269
+ db["user_progress"][username]["streak"] += 1
270
+ elif days_diff > 1:
271
+ # Streak broken
272
+ db["user_progress"][username]["streak"] = 1
273
+
274
+ db["user_progress"][username]["last_completed"] = today
275
+
276
+ # Record the session
277
+ db["user_progress"][username]["completed_sessions"].append({
278
+ "session_id": session_id,
279
+ "completed_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
280
+ "duration": duration
281
+ })
282
+
283
+ # Update total minutes
284
+ db["user_progress"][username]["total_minutes"] += duration
285
+
286
+ save_meditation_db(db)
287
+ return True, "Meditation session recorded"
288
+
289
+ # Get user meditation stats
290
+ def get_user_meditation_stats(username):
291
+ if not username:
292
+ return None
293
+
294
+ db = initialize_meditation_db()
295
+
296
+ if username not in db["user_progress"]:
297
+ return {
298
+ "completed_sessions": 0,
299
+ "total_minutes": 0,
300
+ "streak": 0,
301
+ "last_completed": None
302
+ }
303
+
304
+ stats = db["user_progress"][username]
305
+ stats["completed_sessions"] = len(stats["completed_sessions"])
306
+
307
+ return stats
308
+
309
+ # Meditation UI components
310
+ def meditation_library():
311
+ st.subheader("Guided Meditation Library")
312
+ st.write("Explore our collection of guided meditations to help you relax, focus, and find peace.")
313
+
314
+ # Get all sessions
315
+ sessions = get_meditation_sessions()
316
+
317
+ # Filter options
318
+ col1, col2 = st.columns(2)
319
+ with col1:
320
+ difficulty_filter = st.selectbox(
321
+ "Filter by difficulty",
322
+ ["All", "Beginner", "Intermediate"],
323
+ key="difficulty_filter"
324
+ )
325
+
326
+ with col2:
327
+ category_filter = st.selectbox(
328
+ "Filter by category",
329
+ ["All", "Stress Relief", "Mindfulness", "Emotional Wellbeing", "Compassion", "Relaxation"],
330
+ key="category_filter"
331
+ )
332
+
333
+ # Apply filters
334
+ filtered_sessions = sessions
335
+ if difficulty_filter != "All":
336
+ filtered_sessions = [s for s in filtered_sessions if s["difficulty"] == difficulty_filter]
337
+
338
+ if category_filter != "All":
339
+ filtered_sessions = [s for s in filtered_sessions if s["category"] == category_filter]
340
+
341
+ # Display sessions in a grid
342
+ if not filtered_sessions:
343
+ st.write("No meditation sessions match your filters.")
344
+ else:
345
+ # Create rows with 2 sessions per row
346
+ for i in range(0, len(filtered_sessions), 2):
347
+ cols = st.columns(2)
348
+
349
+ # First session in the row
350
+ with cols[0]:
351
+ if i < len(filtered_sessions):
352
+ session = filtered_sessions[i]
353
+ with st.container():
354
+ st.markdown(f"""
355
+ <div style="padding: 1rem; border-radius: 0.5rem; background-color: {session['background']}; margin-bottom: 1rem;">
356
+ <h3>{session['title']}</h3>
357
+ <p><strong>{session['duration']} minutes</strong> | {session['difficulty']} | {session['category']}</p>
358
+ <p>{session['description']}</p>
359
+ </div>
360
+ """, unsafe_allow_html=True)
361
+
362
+ if st.button("Start Meditation", key=f"start_{session['id']}"):
363
+ st.session_state.meditation_view = "session"
364
+ st.session_state.meditation_session = session['id']
365
+ st.experimental_rerun()
366
+
367
+ # Second session in the row
368
+ with cols[1]:
369
+ if i + 1 < len(filtered_sessions):
370
+ session = filtered_sessions[i + 1]
371
+ with st.container():
372
+ st.markdown(f"""
373
+ <div style="padding: 1rem; border-radius: 0.5rem; background-color: {session['background']}; margin-bottom: 1rem;">
374
+ <h3>{session['title']}</h3>
375
+ <p><strong>{session['duration']} minutes</strong> | {session['difficulty']} | {session['category']}</p>
376
+ <p>{session['description']}</p>
377
+ </div>
378
+ """, unsafe_allow_html=True)
379
+
380
+ if st.button("Start Meditation", key=f"start_{session['id']}"):
381
+ st.session_state.meditation_view = "session"
382
+ st.session_state.meditation_session = session['id']
383
+ st.experimental_rerun()
384
+
385
+ def meditation_session(session_id):
386
+ session = get_meditation_session(session_id)
387
+
388
+ if not session:
389
+ st.error("Meditation session not found")
390
+ if st.button("Back to Library"):
391
+ st.session_state.meditation_view = "library"
392
+ st.session_state.meditation_session = None
393
+ st.experimental_rerun()
394
+ return
395
+
396
+ st.subheader(session["title"])
397
+
398
+ # Back button
399
+ if st.button("← Back to Library"):
400
+ st.session_state.meditation_view = "library"
401
+ st.session_state.meditation_session = None
402
+ st.experimental_rerun()
403
+
404
+ # Session details
405
+ st.write(f"**Duration:** {session['duration']} minutes")
406
+ st.write(f"**Difficulty:** {session['difficulty']}")
407
+ st.write(f"**Category:** {session['category']}")
408
+ st.write(session["description"])
409
+
410
+ # Start meditation button
411
+ if "meditation_in_progress" not in st.session_state or not st.session_state.meditation_in_progress:
412
+ if st.button("Begin Meditation"):
413
+ st.session_state.meditation_in_progress = True
414
+ st.session_state.meditation_step = 0
415
+ st.session_state.meditation_start_time = time.time()
416
+ st.experimental_rerun()
417
+ else:
418
+ # Display meditation steps
419
+ progress = st.progress(0)
420
+ step_duration = session["duration"] * 60 / len(session["steps"]) # seconds per step
421
+
422
+ # Calculate elapsed time and current step
423
+ elapsed = time.time() - st.session_state.meditation_start_time
424
+ total_duration = session["duration"] * 60 # total seconds
425
+ progress_value = min(elapsed / total_duration, 1.0)
426
+ progress.progress(progress_value)
427
+
428
+ current_step = min(int(elapsed / step_duration), len(session["steps"]) - 1)
429
+
430
+ # Update step if needed
431
+ if current_step != st.session_state.meditation_step:
432
+ st.session_state.meditation_step = current_step
433
+ st.experimental_rerun()
434
+
435
+ # Display current step
436
+ st.markdown(f"""
437
+ <div style="padding: 2rem; border-radius: 0.5rem; background-color: {session['background']};
438
+ text-align: center; font-size: 1.5rem; margin: 2rem 0;">
439
+ {session['steps'][current_step]}
440
+ </div>
441
+ """, unsafe_allow_html=True)
442
+
443
+ # Time remaining
444
+ remaining = max(0, total_duration - elapsed)
445
+ mins = int(remaining // 60)
446
+ secs = int(remaining % 60)
447
+ st.write(f"Time remaining: {mins}:{secs:02d}")
448
+
449
+ # End meditation button
450
+ if st.button("End Meditation Early"):
451
+ # Record partial completion
452
+ if st.session_state.get("logged_in", False):
453
+ actual_duration = min(session["duration"], elapsed / 60)
454
+ record_meditation_completion(
455
+ st.session_state.username,
456
+ session_id,
457
+ actual_duration
458
+ )
459
+
460
+ st.session_state.meditation_in_progress = False
461
+ st.session_state.meditation_step = 0
462
+ st.experimental_rerun()
463
+
464
+ # Check if meditation is complete
465
+ if elapsed >= total_duration:
466
+ # Record completion
467
+ if st.session_state.get("logged_in", False):
468
+ record_meditation_completion(
469
+ st.session_state.username,
470
+ session_id,
471
+ session["duration"]
472
+ )
473
+
474
+ st.success("Meditation complete! Take a moment to notice how you feel.")
475
+
476
+ if st.button("Return to Library"):
477
+ st.session_state.meditation_in_progress = False
478
+ st.session_state.meditation_step = 0
479
+ st.session_state.meditation_view = "library"
480
+ st.experimental_rerun()
481
+
482
+ def meditation_stats():
483
+ if not st.session_state.get("logged_in", False):
484
+ st.info("Please log in to view your meditation statistics")
485
+ return
486
+
487
+ stats = get_user_meditation_stats(st.session_state.username)
488
+
489
+ if not stats:
490
+ st.write("No meditation data available yet. Start your first session!")
491
+ return
492
+
493
+ # Display stats in a nice UI
494
+ col1, col2, col3 = st.columns(3)
495
+
496
+ with col1:
497
+ st.metric("Total Sessions", stats["completed_sessions"])
498
+
499
+ with col2:
500
+ st.metric("Total Minutes", stats["total_minutes"])
501
+
502
+ with col3:
503
+ st.metric("Current Streak", f"{stats['streak']} days")
504
+
505
+ # Last meditation
506
+ if stats["last_completed"]:
507
+ st.write(f"Last meditation: {stats['last_completed']}")
508
+
509
+ # Achievements
510
+ if stats["completed_sessions"] > 0:
511
+ st.subheader("Achievements")
512
+
513
+ achievements = []
514
+
515
+ if stats["completed_sessions"] >= 1:
516
+ achievements.append("🌱 First Step - Complete your first meditation")
517
+
518
+ if stats["completed_sessions"] >= 5:
519
+ achievements.append("🌿 Growing Practice - Complete 5 meditations")
520
+
521
+ if stats["completed_sessions"] >= 10:
522
+ achievements.append("🌳 Established Practice - Complete 10 meditations")
523
+
524
+ if stats["streak"] >= 3:
525
+ achievements.append("🔥 Momentum - 3 day meditation streak")
526
+
527
+ if stats["streak"] >= 7:
528
+ achievements.append("⚡ Consistency - 7 day meditation streak")
529
+
530
+ if stats["total_minutes"] >= 60:
531
+ achievements.append("⏱️ Hour of Peace - Meditate for 60 minutes total")
532
+
533
+ for achievement in achievements:
534
+ st.markdown(f"**{achievement}**")
535
+
536
+ def meditation_page():
537
+ # Initialize session state variables if they don't exist
538
+ if "meditation_view" not in st.session_state:
539
+ st.session_state.meditation_view = "library"
540
+
541
+ if "meditation_session" not in st.session_state:
542
+ st.session_state.meditation_session = None
543
+
544
+ if "meditation_in_progress" not in st.session_state:
545
+ st.session_state.meditation_in_progress = False
546
+
547
+ if "meditation_step" not in st.session_state:
548
+ st.session_state.meditation_step = 0
549
+
550
+ # Main content area
551
+ st.markdown("<h1 style='text-align: center;'>Guided Meditation</h1>", unsafe_allow_html=True)
552
+
553
+ # Tabs for different sections
554
+ tab1, tab2 = st.tabs(["Meditation Library", "Your Progress"])
555
+
556
+ with tab1:
557
+ if st.session_state.meditation_view == "library":
558
+ meditation_library()
559
+ elif st.session_state.meditation_view == "session" and st.session_state.meditation_session:
560
+ meditation_session(st.session_state.meditation_session)
561
+
562
+ with tab2:
563
+ meditation_stats()
AfyaMindSpace/meditation_data.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"sessions": [{"id": "breathing", "title": "Deep Breathing Exercise", "description": "A simple breathing exercise to help calm your mind and reduce stress.", "duration": 5, "difficulty": "Beginner", "category": "Stress Relief", "steps": ["Find a comfortable position and close your eyes.", "Take a deep breath in through your nose for 4 seconds.", "Hold your breath for 2 seconds.", "Exhale slowly through your mouth for 6 seconds.", "Repeat this breathing pattern for the duration of the session."], "background": "#E6F7FF"}, {"id": "body_scan", "title": "Body Scan Meditation", "description": "A guided meditation to help you become aware of sensations throughout your body.", "duration": 10, "difficulty": "Intermediate", "category": "Mindfulness", "steps": ["Lie down or sit in a comfortable position and close your eyes.", "Begin by bringing awareness to your breath, noticing the natural rhythm.", "Slowly shift your attention to your feet, noticing any sensations.", "Gradually move your awareness up through your legs, torso, arms, and head.", "If you notice any tension, breathe into that area and allow it to relax.", "Complete the scan by bringing awareness to your body as a whole."], "background": "#F0E6FF"}, {"id": "gratitude", "title": "Gratitude Meditation", "description": "A meditation practice focused on cultivating gratitude and positive emotions.", "duration": 7, "difficulty": "Beginner", "category": "Emotional Wellbeing", "steps": ["Sit comfortably with your back straight and eyes closed.", "Take a few deep breaths to center yourself.", "Bring to mind something or someone you're grateful for.", "Notice the feelings of appreciation and warmth that arise.", "Acknowledge how this person or thing enriches your life.", "Expand your awareness to include more things you're grateful for.", "Conclude by setting an intention to notice moments of gratitude throughout your day."], "background": "#FFF0E6"}, {"id": "loving_kindness", "title": "Loving-Kindness Meditation", "description": "A practice to develop feelings of goodwill, kindness, and warmth towards others.", "duration": 12, "difficulty": "Intermediate", "category": "Compassion", "steps": ["Sit in a comfortable position with your eyes closed.", "Begin by focusing on your breath, allowing yourself to relax.", "Bring to mind someone you care about deeply.", "Silently repeat phrases like 'May you be happy. May you be healthy. May you be safe.'", "Next, direct these wishes toward yourself: 'May I be happy. May I be healthy. May I be safe.'", "Gradually extend these wishes to others: acquaintances, difficult people, and all beings.", "End by taking a few deep breaths and slowly opening your eyes."], "background": "#E6FFE6"}, {"id": "visualization", "title": "Peaceful Place Visualization", "description": "A guided visualization to help you relax by imagining a peaceful, safe place.", "duration": 8, "difficulty": "Beginner", "category": "Relaxation", "steps": ["Find a comfortable position and close your eyes.", "Take several deep breaths, allowing your body to relax.", "Imagine a place where you feel completely peaceful and safe.", "Notice the details: What do you see? What sounds do you hear?", "Experience the sensations: What do you feel? What scents are present?", "Allow yourself to fully immerse in this peaceful place.", "When ready, slowly bring your awareness back to the present moment."], "background": "#E6FFFF"}], "user_progress": {}}
AfyaMindSpace/requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ streamlit==1.41.1
2
+ pandas==2.0.0
3
+ altair==5.0.0
4
+ numpy==1.24.0
5
+ json5==0.9.14
AfyaMindSpace/user_data.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"users": {"Jnr": {"password_hash": "79db4572d62ee99cf63284fe62f9a60aae30322515511dd24cff728a8831c507", "email": "iammcqwory@gmail.com", "created_at": "2025-04-01 19:55:29", "last_login": "2025-04-01 20:33:14", "profile": {"display_name": "Jnr", "bio": "", "preferences": {"notifications": true, "privacy": "public"}}}}}