30 Day Progress
diff --git a/src/data/questions.js b/src/data/questions.js
index aaeb2b2..b479719 100644
--- a/src/data/questions.js
+++ b/src/data/questions.js
@@ -1,12 +1,185 @@
-// src/data/questions.js
-
export const questions = [
- "Write down three realistic, small acts of self-care I can commit to this week.",
- "What feelings or thoughts am I having about my professional identity right now?",
- "How can I ask my partner or support system for help with a specific task today or tomorrow?",
- // ... (27 more questions)
- "How has my definition of success changed since becoming a mother?",
- "Describe one or two small, loving moments you shared with your child(ren) today.",
+ {
+ day: 1,
+ theme: 'Setting Boundaries',
+ question:
+ 'Define what a truly successful, balanced week looks like for me, including personal time.',
+ },
+
+ {
+ day: 2,
+ theme: 'Self-Introspection',
+ question:
+ 'What feelings or thoughts am I having about my professional identity right now?',
+ },
+ {
+ day: 3,
+ theme: 'Celebrating Wins',
+ question:
+ 'Name one or two things I am proud of myself for accomplishing today, no matter how small.',
+ },
+ {
+ day: 4,
+ theme: 'Self-Introspection',
+ question:
+ 'Describe how my energy level feels right now, without judgment. What would I tell a friend who was feeling exactly the way I feel today?',
+ },
+ {
+ day: 5,
+ theme: 'Self-Advocacy',
+ question:
+ 'How can I ask my partner or support system for help with a specific task today or tomorrow?',
+ },
+ {
+ day: 6,
+ theme: 'Self-Introspection',
+ question:
+ "Write a 'thank you' note to your body for everything it has done.",
+ },
+ {
+ day: 7,
+ theme: 'Celebrating Wins',
+ question:
+ 'What is a small way I can reconnect with my partner or a loved one this weekend?',
+ },
+ {
+ day: 8,
+ theme: 'Self-Introspection',
+ question:
+ 'What is one thing I deeply miss from my life before the baby, and how can I integrate a tiny piece of it now?',
+ },
+ {
+ day: 9,
+ theme: 'Self-Introspection',
+ question:
+ 'List all my current work-related tasks and mark which ones bring me energy versus draining it. If I could delegate one task right now, which one would it be and why?',
+ },
+ {
+ day: 10,
+ theme: 'Setting Boundaries',
+ question:
+ 'Write a script for a conversation where I clearly and respectfully decline a new commitment.',
+ },
+ {
+ day: 11,
+ theme: 'Setting Boundaries',
+ question:
+ 'Write down three realistic, small acts of self-care I can commit to this week.',
+ },
+ {
+ day: 12,
+ theme: 'Self-Introspection',
+ question:
+ 'How am I currently using my lunch breaks and how could I use them to truly disconnect?',
+ },
+ {
+ day: 13,
+ theme: 'Setting Boundaries',
+ question:
+ 'What boundary do I need to establish with my work device (e.g., no email after 7 PM)?',
+ },
+ {
+ day: 14,
+ theme: 'Setting Boundaries',
+ question:
+ "What is the 'good enough' standard for my current projects, and where am I over-delivering unnecessarily?",
+ },
+ {
+ day: 15,
+ theme: 'Self-Advocacy',
+ question:
+ 'Name one specific way my company or manager could better support my well-being.',
+ },
+ {
+ day: 16,
+ theme: 'Self-Introspection',
+ question:
+ 'How does my body feel right now? Am I holding tension anywhere (shoulders, jaw, etc.)?',
+ },
+ {
+ day: 17,
+ theme: 'Self-Introspection',
+ question:
+ 'Write a letter to my future self outlining the signs of burnout to watch for.',
+ },
+ {
+ day: 18,
+ theme: 'Setting Boundaries',
+ question:
+ 'What are two things I could let go of or automate that would save me an hour of time weekly?',
+ },
+ {
+ day: 19,
+ theme: 'Self-Introspection',
+ question:
+ 'If I took a mental health day tomorrow, what three activities would I do?',
+ },
+ {
+ day: 20,
+ theme: 'Self-Introspection',
+ question:
+ 'What is my current definition of leadership, and how am I embodying it daily?',
+ },
+ {
+ day: 21,
+ theme: 'Self-Introspection',
+ question:
+ 'Describe a recent situation where I had to make a difficult decision; what was the guiding principle?',
+ },
+ {
+ day: 22,
+ theme: 'Self-Advocacy',
+ question:
+ 'What is one skill I need to delegate or train my team on so I can focus on strategy?',
+ },
+ {
+ day: 23,
+ theme: 'Self-Introspection',
+ question:
+ 'Who in my network or industry do I admire as a leader, and what specific traits do they possess?',
+ },
+ {
+ day: 24,
+ theme: 'Self-Introspection',
+ question:
+ 'What is the most significant legacy I want to build in my current role?',
+ },
+ {
+ day: 25,
+ theme: 'Gender Bias',
+ question:
+ 'How am I actively creating a more inclusive and equitable environment for my junior colleagues?',
+ },
+ {
+ day: 26,
+ theme: 'Self-Advocacy',
+ question:
+ 'What is one area of my company or industry where I feel my expertise is untapped?',
+ },
+ {
+ day: 27,
+ theme: 'Self-Introspection',
+ question:
+ 'How am I actively seeking and implementing critical feedback on my leadership style?',
+ },
+ {
+ day: 28,
+ theme: 'Self-Advocacy',
+ question:
+ 'How does my current compensation reflect my value and impact? What are three ways I can advocate for myself and my team more effectively in the next quarter?',
+ },
+ {
+ day: 29,
+ theme: 'Self-Advocacy',
+ question:
+ 'What is the single most important lesson I want to teach my mentees this year? Why?',
+ },
+ {
+ day: 30,
+ theme: 'Celebrating Wins',
+ question:
+ "If I was starting a new company today, what is the first cultural value I would establish? How am I intentionally celebrating successes—both mine and my team's—this week?",
+ },
];
export const total_days = 30;
diff --git a/src/main.jsx b/src/main.jsx
index c3ad357..94be4f4 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -14,6 +14,7 @@ import Journal from './pages/journal';
import Logout from './pages/Logout';
import Challenges from './pages/Challenges';
import Profile from './pages/Profile';
+import ForumResponses from './pages/ForumResponses';
import App from './App';
const router = createBrowserRouter([
@@ -32,13 +33,11 @@ const router = createBrowserRouter([
{ path: 'logout', element:
},
{ path: 'profile', element:
},
{ path: 'error', element:
},
+ { path: '*', element:
},
{ path: 'challenges', element:
},
+ { path: '/community/responses/:day', element:
},
],
},
- {
- path: '*',
- element:
,
- },
]);
createRoot(document.getElementById('root')).render(
diff --git a/src/pages/Community.jsx b/src/pages/Community.jsx
index 592f72d..0158ed5 100644
--- a/src/pages/Community.jsx
+++ b/src/pages/Community.jsx
@@ -1,9 +1,52 @@
-function Community() {
+// react
+import { Link } from 'react-router-dom';
+
+// data
+import { questions } from '../data/questions';
+
+//icon
+import { FaArrowRight } from 'react-icons/fa6';
+
+const Community = () => {
return (
-
-
Community Page! 🎉
-
+
+
+
+ Community Forum
+
+
+ View how other women in tech responded to journal prompts.
+
+
+
+ {questions.map((q) => (
+
+
+
+ Theme: {q.theme}
+
+
+ {q.question}
+
+
+
+
+
+
+
+
+ ))}
+
+
+
);
-}
+};
-export default Community;
+export default Community;
\ No newline at end of file
diff --git a/src/pages/ForumResponses.jsx b/src/pages/ForumResponses.jsx
new file mode 100644
index 0000000..72919e1
--- /dev/null
+++ b/src/pages/ForumResponses.jsx
@@ -0,0 +1,133 @@
+// react
+import { useEffect, useState } from 'react';
+import { useParams, useNavigate } from 'react-router-dom';
+import { Link } from 'react-router-dom';
+
+// firebase
+import { db } from '../firebase';
+import { collection, getDocs } from 'firebase/firestore';
+
+// data
+import { questions } from '../data/questions';
+
+// icons
+import { FaArrowRight, FaArrowLeft } from 'react-icons/fa6';
+
+const getResponsesForDay = async (day) => {
+ if (!day) return [];
+
+ const dayKey = `day${day}`;
+ const journalRef = collection(db, 'journals');
+
+ try {
+ const querySnapshot = await getDocs(journalRef);
+ const responses = [];
+
+ querySnapshot.forEach((doc) => {
+ const entry = doc.data().entries?.[dayKey];
+
+ if (
+ entry &&
+ typeof entry === 'object' &&
+ entry.comment &&
+ !entry.optOut
+ ) {
+ responses.push(entry.comment);
+ }
+ });
+
+ return responses;
+ } catch (error) {
+ console.error('Error retrieving community data from Firestore:', error);
+ return [];
+ }
+};
+
+const ForumResponses = () => {
+ const { day: dayParam } = useParams();
+ const navigate = useNavigate();
+ const day = parseInt(dayParam);
+
+ const [questionData, setQuestionData] = useState(null);
+ const [responses, setResponses] = useState([]);
+
+ const journalLink = `/journal`;
+
+ useEffect(() => {
+ const fetchResponses = async () => {
+ if (day && day >= 1 && day <= questions.length) {
+ const qData = questions[day - 1];
+ setQuestionData(qData);
+
+ const communityResponses = await getResponsesForDay(day);
+ setResponses(communityResponses);
+ } else {
+ navigate('/community');
+ }
+ };
+
+ fetchResponses();
+ }, [day, navigate]);
+
+ if (!questionData) {
+ return Loading...
;
+ }
+
+ const { question } = questionData;
+ const backLink = `/community`;
+
+ return (
+
+
+
+
+
Back to Forum
+
+
+
+ Community Responses for Day {day}
+
+
+ Prompt: {question}
+
+
+
+ {responses.length > 0 ? (
+ responses.map((response, index) => (
+
+
+ Anonymous
+
+
+
+ {response}
+
+
+ ))
+ ) : (
+
+ Be the first to share your response from your journal.
+
+
+
+
+ )}
+
+
+
+ );
+};
+
+export default ForumResponses;
\ No newline at end of file
diff --git a/src/pages/journal.jsx b/src/pages/journal.jsx
index 0806b2d..9579a00 100644
--- a/src/pages/journal.jsx
+++ b/src/pages/journal.jsx
@@ -1,5 +1,11 @@
//react
import { useState, useEffect, useCallback } from 'react';
+import { useLocation, useNavigate } from 'react-router-dom';
+
+// firebase
+import { db, auth } from '../firebase';
+import { doc, setDoc, onSnapshot } from 'firebase/firestore';
+import { onAuthStateChanged } from 'firebase/auth';
//components
import ProgressBar from '../components/ProgressBar';
@@ -7,48 +13,106 @@ import DailyTrackerBar from '../components/DailyTrackerBar';
import DailySummary from '../components/DailySummary';
//data
-import { questions, total_days, local_storage_key } from '../data/questions';
-
-const getInitialData = () => {
- try {
- const storedData = localStorage.getItem(local_storage_key);
- return storedData
- ? JSON.parse(storedData)
- : { effectiveDays: 0, entries: {} };
- } catch (error) {
- console.error('Error retrieving data from localStorage:', error);
- return { effectiveDays: 0, entries: {} };
- }
-};
+import { questions, total_days } from '../data/questions';
const Journal = () => {
- const [progressData, setProgressData] = useState(getInitialData);
+ const location = useLocation();
+ const navigate = useNavigate();
+
+ // State for user authentication
+ const [userId, setUserId] = useState(null);
+ const [loading, setLoading] = useState(true);
+
+ const [progressData, setProgressData] = useState({
+ effectiveDays: 0,
+ entries: {},
+ });
const [isDaySummaryOpen, setIsDaySummaryOpen] = useState(false);
const [selectedDay, setSelectedDay] = useState(null);
const nextDayToComplete = progressData.effectiveDays + 1;
- // Update localStorage
+ // Check authentication state
useEffect(() => {
- localStorage.setItem(local_storage_key, JSON.stringify(progressData));
- }, [progressData]);
+ const unsubscribe = onAuthStateChanged(auth, (user) => {
+ if (user) {
+ setUserId(user.uid);
+ setLoading(false);
+ } else {
+ navigate('/login');
+ }
+ });
+
+ return () => unsubscribe();
+ }, [navigate]);
- // Open the Day Summary for a specific day
- const openSummaryForDay = (day) => {
+ useEffect(() => {
+ if (!userId) return;
+
+ // Create document reference using the authenticated user's ID
+ const JOURNAL_DOC_REF = doc(db, 'journals', userId);
+
+ const unsubscribe = onSnapshot(
+ JOURNAL_DOC_REF,
+ (docSnap) => {
+ if (docSnap.exists()) {
+ const data = docSnap.data();
+ setProgressData({
+ effectiveDays: data.effectiveDays || 0,
+ entries: data.entries || {},
+ });
+ } else {
+
+ setDoc(
+ JOURNAL_DOC_REF,
+ { effectiveDays: 0, entries: {} },
+ { merge: true }
+ ).catch((error) =>
+ console.error('Error creating initial document:', error)
+ );
+ }
+ },
+ (error) => {
+ console.error('Error listening to journal data:', error);
+ }
+ );
+
+ return () => unsubscribe();
+ }, [userId]);
+
+ // Open the DailySummary for a specific day
+ const openSummaryForDay = useCallback((day) => {
setSelectedDay(day);
setIsDaySummaryOpen(true);
- };
- const handleArrowClick = () => {
- if (nextDayToComplete <= total_days) {
- openSummaryForDay(nextDayToComplete);
+ }, []);
+
+ // Handle navigation from ForumResponses
+ useEffect(() => {
+ if (location.state && location.state.openDaySummary) {
+ openSummaryForDay(location.state.openDaySummary);
}
- };
+ }, [location.state, openSummaryForDay]);
+
+ const handleArrowClick = useCallback(() => {
+ openSummaryForDay(nextDayToComplete);
+ }, [openSummaryForDay, nextDayToComplete]);
+
+ const handleSaveComment = useCallback((day, comment, isOptedOut) => {
+ if (!userId) return;
+
+ // Create document reference using the authenticated user's ID
+ const JOURNAL_DOC_REF = doc(db, 'journals', userId);
- const handleSaveComment = useCallback((day, comment) => {
setProgressData((prevData) => {
const dayKey = `day${day}`;
const trimmedComment = comment.trim();
- const hasPreviousComment = !!prevData.entries[dayKey];
+
+ const previousEntry = prevData.entries[dayKey];
+
+ const hasPreviousComment = !!(
+ previousEntry &&
+ (previousEntry.comment || typeof previousEntry === 'string')
+ );
const hasNewComment = trimmedComment.length > 0;
let newEffectiveDays = prevData.effectiveDays;
@@ -59,44 +123,72 @@ const Journal = () => {
newEffectiveDays -= 1;
}
+ const entryData =
+ trimmedComment.length > 0
+ ? { comment: trimmedComment, optOut: isOptedOut }
+ : null;
+
const newEntries = {
...prevData.entries,
- [dayKey]: trimmedComment,
+ [dayKey]: entryData,
+ };
+
+ const finalEffectiveDays = Math.max(
+ 0,
+ Math.min(newEffectiveDays, total_days)
+ );
+
+ const dataToSave = {
+ effectiveDays: finalEffectiveDays,
+ entries: newEntries,
};
- newEffectiveDays = Math.max(0, Math.min(newEffectiveDays, total_days));
+ // Save to Firestore
+ setDoc(JOURNAL_DOC_REF, dataToSave, { merge: true }).catch((error) =>
+ console.error('Error saving journal entry:', error)
+ );
return {
- effectiveDays: newEffectiveDays,
+ effectiveDays: finalEffectiveDays,
entries: newEntries,
};
});
- }, []);
+ }, [userId]);
- const daysArray = Array.from({ length: total_days }, (_, i) => i + 1);
+
+ if (loading) {
+ return Loading...
;
+ }
return (
-
+
-
+
Journal Entry
+
-
- View saved journal entries or start a new journal entry.
-
-
- {/* Daily Bars */}
-
- {daysArray.map((day) => {
- const dayKey = `day${day}`;
- const isCompleted = !!progressData.entries[dayKey];
+
+
+ {questions.map((q) => {
+ const day = q.day;
+ const entry = progressData.entries[`day${day}`];
+
+ const isCompleted = !!(entry && entry.comment);
+
+ // DailyTrackerBar
const isDisabled = day > nextDayToComplete;
+ // DailySummary
+ const initialCommentData =
+ typeof entry === 'string'
+ ? { comment: entry, optOut: false }
+ : entry;
+
return (
{
isOpen={isDaySummaryOpen}
onClose={() => setIsDaySummaryOpen(false)}
day={selectedDay}
- question={questions[selectedDay - 1]}
- initialComment={progressData.entries[`day${selectedDay}`]}
+ question={questions[selectedDay - 1].question}
+ initialComment={initialCommentData}
onSave={handleSaveComment}
/>
) : (
@@ -134,4 +226,4 @@ const Journal = () => {
);
};
-export default Journal;
+export default Journal;
\ No newline at end of file