diff --git a/public/bg.png b/public/bg/bg.png similarity index 100% rename from public/bg.png rename to public/bg/bg.png diff --git a/public/user.png b/public/homePage/user.png similarity index 100% rename from public/user.png rename to public/homePage/user.png diff --git a/public/image1.png b/public/logo/image1.png similarity index 100% rename from public/image1.png rename to public/logo/image1.png diff --git a/public/close.svg b/public/submitCard/close.svg similarity index 100% rename from public/close.svg rename to public/submitCard/close.svg diff --git a/src/.env b/src/.env index f2b28fc6..e154a0ec 100644 --- a/src/.env +++ b/src/.env @@ -1 +1,7 @@ -PUBLIC_URL = "./public/" \ No newline at end of file +PUBLIC_URL = "./public/" +REACT_APP_FIREBASE_API_KEY = "AIzaSyCduh8Bd6T3lqaMxFxihVPZQSRH7_vPODY" +REACT_APP_FIREBASE_AUTH_DOMAIN = "dear-diary-emailusername-6a3d7.firebaseapp.com" +REACT_APP_FIREBASE_PROJECT_ID = "dear-diary-emailusername-6a3d7" +REACT_APP_FIREBASE_STORAGE_BUCKET = "dear-diary-emailusername-6a3d7.appspot.com" +REACT_APP_FIREBASE_MESSAGING_SENDER_ID = "107317734441" +REACT_APP_FIREBASE_APP_ID = "1:107317734441:web:2b5d34185dce4a01564038" \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 0dbb2c77..9d7f32e2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,7 @@ import './App.css'; -import AppRoutes from './utility/appRoutes'; +import AppRoutes from './components/appRoutes'; function App() { return ( diff --git a/src/utility/appRoutes.tsx b/src/components/appRoutes.tsx similarity index 64% rename from src/utility/appRoutes.tsx rename to src/components/appRoutes.tsx index 751c58e1..6a2c3260 100644 --- a/src/utility/appRoutes.tsx +++ b/src/components/appRoutes.tsx @@ -1,13 +1,14 @@ import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import SignInPage from "../containers/SignInPage/SignInPage"; import HomePage from "../containers/HomePage/HomePage"; +import { SIGN_IN_PATH, HOME_PATH } from "../utility/routeConstants"; const AppRoutes = () => { return ( - }/> - }/> + }/> + }/> diff --git a/src/components/header.tsx b/src/components/header.tsx index b48a2b18..ae9e71a4 100644 --- a/src/components/header.tsx +++ b/src/components/header.tsx @@ -34,7 +34,7 @@ const Header = () => {
- + Dear Diary diff --git a/src/utility/firebaseConfig.ts b/src/config/firebaseConfig.ts similarity index 85% rename from src/utility/firebaseConfig.ts rename to src/config/firebaseConfig.ts index 2aebc22b..8d3403be 100644 --- a/src/utility/firebaseConfig.ts +++ b/src/config/firebaseConfig.ts @@ -4,8 +4,8 @@ import { } from "firebase/firestore"; const firebaseConfig = { - apiKey: "AIzaSyCduh8Bd6T3lqaMxFxihVPZQSRH7_vPODY", - authDomain: "dear-diary-emailusername-6a3d7.firebaseapp.com", + apiKey: process.env.REACT_APP_API_KEY, + authDomain: process.env.REACT_APP_AUTH_DOMAIN, projectId: "dear-diary-emailusername-6a3d7", storageBucket: "dear-diary-emailusername-6a3d7.appspot.com", messagingSenderId: "107317734441", diff --git a/src/containers/HomePage/DiaryCard/DiaryCard.tsx b/src/containers/HomePage/DiaryCard/DiaryCard.tsx index 36cd6abe..95abf67c 100644 --- a/src/containers/HomePage/DiaryCard/DiaryCard.tsx +++ b/src/containers/HomePage/DiaryCard/DiaryCard.tsx @@ -16,6 +16,7 @@ interface DiaryCardProps { const StyledCard = styled(Card)` width: 271px; + min-height: 10px; height: auto; padding: 20px; border-radius: 6px; @@ -24,11 +25,12 @@ const StyledCard = styled(Card)` const StyledCardContent = styled(CardContent)` align-self: flex-start; + + `; const StyledBox = styled(Box)` display: flex; - height: auto; margin-bottom: 6px; align-items: flex-start; `; @@ -69,18 +71,20 @@ const StyledButton = styled(Button)` width: 271px; display: flex; padding: 20px; + padding-left: 0px; flex-direction: column; align-items: flex-start; border-radius: 6px; background-color: #ffffff; - box-shadow: 0 4px 18px 0pc rgba(75, 70, 92, 0.10); + box-shadow: 0 4px 18px 0pc rgba(75, 70, 92, 0.0); } `; const DiaryCard: React.FC = ({ title, description }) => { const [showMore, setShowMore] = useState(false); // state to track whether to show more or not - const truncatedDescription = showMore ? description : `${description.slice(0, 100)}...`; // truncate description if showMore is false + const truncatedDescription = showMore ? description : `${description.slice(0, 100)}`; // truncate description if showMore is false + const showMoreButton = description.length > 100; // only show showMore button if description is longer than 100 characters const handleToggleShowMore = () => { setShowMore(!showMore); @@ -88,7 +92,7 @@ const DiaryCard: React.FC = ({ title, description }) => { return ( - + {title} @@ -99,12 +103,15 @@ const DiaryCard: React.FC = ({ title, description }) => { {truncatedDescription} - - - - {showMore ? 'Hide' : 'Show More'} - - + + {showMoreButton && ( // conditionally render the button based on description length + + + {showMore ? 'Hide' : 'Show More'} + + + )} + ); }; diff --git a/src/containers/HomePage/HomePage.tsx b/src/containers/HomePage/HomePage.tsx index a56c9a0e..696bf4ea 100644 --- a/src/containers/HomePage/HomePage.tsx +++ b/src/containers/HomePage/HomePage.tsx @@ -18,7 +18,7 @@ import styled from 'styled-components'; import { useEffect } from 'react'; import { RootState, useAppDispatch } from '../../redux/store'; import { useSelector, useDispatch } from 'react-redux'; -import { diaryCardActions } from '../../redux/Diary/diarySlice'; +import { diaryCardActions } from '../../redux/diary/slice'; const StyledMainDiv = styled.div` @@ -27,7 +27,7 @@ const StyledMainDiv = styled.div` height: 100vh; width: 100%; position: relative; - background-image: url(${process.env.PUBLIC_URL}/bg.png); + background-image: url(/bg/bg.png); background-size: cover; background-repeat: no-repeat; overflow-x: hidden; @@ -141,6 +141,7 @@ const DiaryCardContainer = styled.div` margin-top: 20px; margin-left: 60px; margin-right: 60px; + margin-bottom: 10px; `; interface DiaryCardProps { @@ -154,30 +155,33 @@ const HomePage = () => { const [showSubmitCard, setShowSubmitCard] = useState(false); // state to track if submit card is open or not const [diaryEntries, setDiaryEntries] = useState([]); // state to track diary entries - const dispatch = useDispatch(); + const dispatch = useDispatch(); const location = useLocation(); // get location from react router dom const nickName = location.state.name || {}; // from that location get name - + + // checking the diary card list array useEffect(() => { console.log("Diary Card List:", diaryEntries); }, [diaryEntries]); - + + // fetching the diarycard according to the username useEffect(() => { console.log("fetching diary card list"); dispatch(diaryCardActions.fetchDiaryCardList(nickName)); }, [dispatch, nickName]); + // function to handle submit card const handleOnSubmitCard = (title: string, description: string) => { // create new diary card console.log('Handling submit card:', { title, description, username: nickName }); - dispatch(diaryCardActions.addDiaryCard({title, description, username: nickName})) + dispatch(diaryCardActions.addDiaryCard({ title, description, username: nickName })) // addding a new diary card to db // add new diary card to diary entries // setDiaryEntries([newDiaryCard, ...diaryEntries]); }; - + // function to handle submit button const handleSubmit = () => { setShowSubmitCard(true); @@ -194,6 +198,14 @@ const HomePage = () => { setDiaryEntries(entries); }, [entries]); + const [searchQuery, setSearchQuery] = useState(''); + + // Function to filter diary entries based on search query + const filteredDiaryEntries = diaryEntries.filter((entry) => { + const searchTerms = `${entry.title} ${entry.description} ${entry.username}`.toLowerCase(); + return searchTerms.includes(searchQuery.toLowerCase()); + }); + return ( @@ -221,7 +233,7 @@ const HomePage = () => { - User Icon + User Icon @@ -245,12 +257,15 @@ const HomePage = () => { variant="outlined" size="small" placeholder="Placeholder" + value={searchQuery} + onChange={(e) => setSearchQuery(e.target.value)} InputProps={{ startAdornment: ( ), + }} /> { {/* Rendering Diary Cards */} - {diaryEntries.map((diaryCard, index) => ( - + {filteredDiaryEntries.map((diaryCard, index) => ( + ))} diff --git a/src/containers/HomePage/SubmitCard/SubmitCard.tsx b/src/containers/HomePage/SubmitCard/SubmitCard.tsx index 96bde632..f910f713 100644 --- a/src/containers/HomePage/SubmitCard/SubmitCard.tsx +++ b/src/containers/HomePage/SubmitCard/SubmitCard.tsx @@ -43,7 +43,7 @@ const StyledCloseButton = styled(IconButton)` `; const StyledSpan = styled.span` - margin-bottom: 8px; + margin-bottom: 10px; margin-right: 330px; font-family: public sans; font-feature-settings: 'clig' off, 'liga' off; @@ -158,17 +158,18 @@ const SubmitCard: React.FC = ({ onClose, onsubmit }) => { Submit New - Close Icon + Close Icon
Title @@ -176,7 +177,8 @@ const SubmitCard: React.FC = ({ onClose, onsubmit }) => { Description { - + Dear Diary Sign In diff --git a/src/redux/User/signInSlice.ts b/src/redux/User/signInSlice.ts deleted file mode 100644 index afabd261..00000000 --- a/src/redux/User/signInSlice.ts +++ /dev/null @@ -1,19 +0,0 @@ -import {createSlice} from '@reduxjs/toolkit'; - -// Define a type for the slice state -export const signInSlice = createSlice({ - name: 'signIn', // a name used in action type - initialState: { - nickname: '', // nickname of the user as initial state - }, - reducers: { - setNickname: (state, action) => { - state.nickname = action.payload; // set nickname to the payload - }, - }, - - }); - -export const {setNickname} = signInSlice.actions; - -export default signInSlice.reducer; \ No newline at end of file diff --git a/src/redux/Diary/diarySaga.ts b/src/redux/diary/saga.ts similarity index 61% rename from src/redux/Diary/diarySaga.ts rename to src/redux/diary/saga.ts index 6afd5734..87bf13dd 100644 --- a/src/redux/Diary/diarySaga.ts +++ b/src/redux/diary/saga.ts @@ -2,27 +2,32 @@ import { take, call, put, takeEvery, all} from 'redux-saga/effects'; import { eventChannel } from 'redux-saga'; import { diaryCardActions -} from './diarySlice'; -import { db } from '../../utility/firebaseConfig'; +} from './slice'; +import { db } from '../../config/firebaseConfig'; import { collection, addDoc, query, onSnapshot, where } from "firebase/firestore"; import { PayloadAction } from '@reduxjs/toolkit'; + +// props for DiaryCard component interface DiaryCardProps { title: string; description: string; username: string; } +// create a channel to listen to changes in the database function snapshotChannel(db: any, username: string) { + // return an event channel that will subscribe to the database changes this will be used to real-time updates return eventChannel((emitter) => { - const ref = collection(db, "DiaryCards"); - const query1 = query(ref, where("username", "==", username)); + const ref = collection(db, "DiaryCards"); // reference to the collection "DiaryCards" + const query1 = query(ref, where("username", "==", username)); // query to get the documents with the username + // listen to the changes in the database const unsubscribe = onSnapshot(query1, (querySnapshot) => { - const updatedDiaryCards: DiaryCardProps[] = []; + const updatedDiaryCards: DiaryCardProps[] = []; // array to store the updated diary cards querySnapshot.forEach((doc) => { const entry = doc.data() as DiaryCardProps; - updatedDiaryCards.push(entry); + updatedDiaryCards.push(entry); // add the updated diary card to the array }); emitter(updatedDiaryCards); }); @@ -31,31 +36,32 @@ function snapshotChannel(db: any, username: string) { }); } - +// add a diary card to the database function* addDiaryCard(action: PayloadAction): Generator { try { - console.log('Adding diary card', action.payload) + // console.log('Adding diary card', action.payload) const { title, description, username } = action.payload; const diaryCard: DiaryCardProps = { title, description, username }; - yield call(addDoc, collection(db, "DiaryCards"), diaryCard); + yield call(addDoc, collection(db, "DiaryCards"), diaryCard); // add the diary card to the database } catch (err) { console.log('Adding card error', err); alert(err); } } +// fetch the diary card list from the database according to the username function* fetchDiaryCardList(action: PayloadAction): Generator { try { const username = action.payload; - const channel = yield call(snapshotChannel, db, username); + const channel = yield call(snapshotChannel, db, username); // create a channel to listen to changes in the database while (true) { - const diaryCardList: DiaryCardProps[] = yield take(channel); - console.log('Diary card list', diaryCardList); - yield put(diaryCardActions.setDiaryCardList(diaryCardList)); + const diaryCardList: DiaryCardProps[] = yield take(channel); // get the updated diary card list + // console.log('Diary card list', diaryCardList); + yield put(diaryCardActions.setDiaryCardList(diaryCardList)); // update the diary card list in the redux store } } catch (err) { console.log('Fetching diary card list error', err); @@ -63,8 +69,10 @@ function* fetchDiaryCardList(action: PayloadAction): Generator { @@ -72,5 +80,5 @@ function* fetchDiaryCardListSaga(): Generator { } export default function* diaryCardSaga() { - yield all([addDiaryCardSaga(), fetchDiaryCardListSaga()]); + yield all([addDiaryCardSaga(), fetchDiaryCardListSaga()]); // run the sagas in parallel }; \ No newline at end of file diff --git a/src/redux/Diary/diarySlice.ts b/src/redux/diary/slice.ts similarity index 58% rename from src/redux/Diary/diarySlice.ts rename to src/redux/diary/slice.ts index cc6c79a1..5d49ef7f 100644 --- a/src/redux/Diary/diarySlice.ts +++ b/src/redux/diary/slice.ts @@ -6,6 +6,7 @@ interface DiaryCardProps { username: string; } + interface DiaryCardState { diaryCardList: DiaryCardProps[]; } @@ -19,14 +20,14 @@ export const diaryCardSlice = createSlice({ initialState, reducers: { addDiaryCard: (state, action: PayloadAction) => { - console.log('Adding diary card:', action.payload); - state.diaryCardList.push(action.payload); - console.log('Diary card list:', state.diaryCardList); + // console.log('Adding diary card:', action.payload); + state.diaryCardList.push(action.payload); // add the diary card to the diary card list + // console.log('Diary card list:', state.diaryCardList); }, setDiaryCardList: (state, action: PayloadAction) => { - state.diaryCardList = action.payload; + state.diaryCardList = action.payload; // set the diary card list to the updated diary card list }, - fetchDiaryCardList: () => {}, + fetchDiaryCardList: () => {}, // fetch the diary card list from the database }, }); diff --git a/src/redux/store.ts b/src/redux/store.ts index 0cc7dba3..7320bf2b 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -2,9 +2,8 @@ import {configureStore, Tuple } from '@reduxjs/toolkit'; // import logger from 'redux-logger'; import createSagaMiddleware from 'redux-saga'; -import {diaryCardReducer} from './Diary/diarySlice'; -import signInSliceReducer from './User/signInSlice'; -import diaryCardSaga from './Diary/diarySaga'; +import {diaryCardReducer} from './diary/slice'; +import diaryCardSaga from './diary/saga'; import { useDispatch } from 'react-redux'; diff --git a/src/utility/routeConstants.ts b/src/utility/routeConstants.ts new file mode 100644 index 00000000..e99d4c19 --- /dev/null +++ b/src/utility/routeConstants.ts @@ -0,0 +1,4 @@ +// Purpose: To store the route constants for the application. + +export const SIGN_IN_PATH = '/'; +export const HOME_PATH = '/home'; \ No newline at end of file