Skip to content
This repository has been archived by the owner on Nov 23, 2024. It is now read-only.

Commit

Permalink
added News page
Browse files Browse the repository at this point in the history
  • Loading branch information
craigm26 committed Dec 22, 2023
1 parent c601942 commit 0dbd699
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 34 deletions.
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ android {
applicationId "app.bikebusapp"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 90
versionCode 91
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
Expand Down
4 changes: 2 additions & 2 deletions ios/App/App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 90;
CURRENT_PROJECT_VERSION = 91;
DEVELOPMENT_TEAM = WYGG3JXWMG;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
Expand All @@ -395,7 +395,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 90;
CURRENT_PROJECT_VERSION = 91;
DEVELOPMENT_TEAM = WYGG3JXWMG;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
Expand Down
10 changes: 10 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import BulletinBoards from './pages/BulletinBoards';
import PrivacyPolicy from './pages/PrivacyPolicy';
import DeleteAccount from './components/DeleteAccount';
import SetLanguage from './components/SetLanguage';
import News from './pages/News';


import { ReactComponent as ClipboardIcon } from './assets/fontawesome/svgs/regular/clipboard-list.svg';
Expand Down Expand Up @@ -230,6 +231,12 @@ const App: React.FC = () => {
<IonContent>
<IonList>
<IonMenuToggle auto-hide="false">
<IonItem button routerLink="/Welcome" routerDirection="none">
<IonLabel>{t('Home')}</IonLabel>
</IonItem>
<IonItem button routerLink="/News" routerDirection="none">
<IonLabel>{t('News')}</IonLabel>
</IonItem>
<IonItem button routerLink="/BulletinBoards" routerDirection="none">
<IonLabel>{t('Bulletin Boards')}</IonLabel>
</IonItem>
Expand Down Expand Up @@ -411,6 +418,9 @@ const App: React.FC = () => {
<Route exact path="/Account">
<Account />
</Route>
<Route exact path="/News">
<News />
</Route>
<Route exact path="/SetUsername">
<SetUsername />
</Route>
Expand Down
143 changes: 143 additions & 0 deletions src/pages/News.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import {
IonContent,
IonPage,
IonHeader,
IonToolbar,
IonTitle,
IonButton,
IonInput,
IonItem,
IonLabel,
IonList,
IonInfiniteScroll,
IonInfiniteScrollContent,
} from '@ionic/react';
import { InputChangeEventDetail } from '@ionic/core';
import React, { useState, useEffect, useContext } from 'react';
import { AuthContext } from '../AuthContext';
import { db } from '../firebaseConfig';
import { collection, query, orderBy, startAfter, getDocs, addDoc, Timestamp, limit, DocumentData, QueryDocumentSnapshot } from 'firebase/firestore';

const News: React.FC = () => {
const { user } = useContext(AuthContext);
const [articles, setArticles] = useState<DocumentData[]>([]);
const [newArticleTitle, setNewArticleTitle] = useState<string>('');
const [newArticleContent, setNewArticleContent] = useState<string>('');
const [lastVisible, setLastVisible] = useState<QueryDocumentSnapshot<DocumentData> | null>(null);
const [isInfiniteDisabled, setIsInfiniteDisabled] = useState(false);

const fetchArticles = async (lastVisibleDoc: QueryDocumentSnapshot<DocumentData> | null) => {
const newsCollection = collection(db, 'newsArticles');
let articlesQuery;

if (lastVisibleDoc) {
articlesQuery = query(newsCollection, orderBy('timestamp', 'desc'), startAfter(lastVisibleDoc), limit(10));
} else {
articlesQuery = query(newsCollection, orderBy('timestamp', 'desc'), limit(10));
}

const snapshot = await getDocs(articlesQuery);
const fetchedArticles = snapshot.docs.map(doc => doc.data());
const lastDoc = snapshot.docs[snapshot.docs.length - 1];

setArticles(prev => [...prev, ...fetchedArticles]);
setLastVisible(lastDoc);

if (snapshot.docs.length < 10) {
setIsInfiniteDisabled(true);
}
};

useEffect(() => {
fetchArticles(null);
}, []);

const submitUserNews = async () => {
if (!newArticleTitle?.trim() || !newArticleContent?.trim()) return;

const userNews = {
title: newArticleTitle,
content: newArticleContent,
author: user?.email || 'Anonymous',
timestamp: Timestamp.now()
};

const userNewsCollection = collection(db, 'userNews');
await addDoc(userNewsCollection, userNews);
};

const handleTitleChange = (event: CustomEvent<InputChangeEventDetail>) => {
setNewArticleTitle(event.detail.value || '');
};

const handleContentChange = (event: CustomEvent<InputChangeEventDetail>) => {
setNewArticleContent(event.detail.value || '');
};

const loadMoreArticles = (event: CustomEvent<void>) => {
fetchArticles(lastVisible).then(() => {
const infiniteScroll = event.target as HTMLIonInfiniteScrollElement;
if (infiniteScroll) {
infiniteScroll.complete();
}
}
);
}

return (
<IonPage className="ion-flex-offset-app">
<IonHeader>
<IonToolbar>
<IonTitle>News</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonList>
{articles.map((article, index) => (
<IonItem key={index}>
<IonLabel>
<h2>{article.title}</h2>
<p>{article.contentSnippet || article.content}</p>
</IonLabel>
</IonItem>
))}
</IonList>
{user && (
<>
<IonItem>
<IonLabel position="stacked">Title</IonLabel>
<IonInput
value={newArticleTitle}
onIonChange={handleTitleChange}
/>
</IonItem>
<IonItem>
<IonLabel position="stacked">Content</IonLabel>
<IonInput
value={newArticleContent}
onIonChange={handleContentChange}
/>
</IonItem>
<IonButton
expand="block"
onClick={submitUserNews}
>
Submit
</IonButton>
</>
)}
<IonInfiniteScroll
onIonInfinite={loadMoreArticles}
threshold="100px"
disabled={isInfiniteDisabled}
>
<IonInfiniteScrollContent
loadingText="Loading more articles...">
</IonInfiniteScrollContent>
</IonInfiniteScroll>
</IonContent>
</IonPage>
);
};

export default News;
34 changes: 3 additions & 31 deletions src/pages/Template.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,16 @@
import {
IonContent,
IonHeader,
IonPage,
IonToolbar,
} from '@ionic/react';
import { useEffect, useState, useContext } from 'react';
import './Help.css';
import useAuth from '../useAuth'; // Import useAuth hook
import { doc, getDoc } from 'firebase/firestore';
import { db } from '../firebaseConfig';
import { HeaderContext } from '../components/HeaderContext';
import { useState, useContext } from 'react';
import { AuthContext } from '../AuthContext';


const Template: React.FC = () => {
const { user } = useAuth(); // Use the useAuth hook to get the user object
const [accountType, setaccountType] = useState<string>('');
const headerContext = useContext(HeaderContext);
const { user } = useContext(AuthContext);

useEffect(() => {
if (headerContext) {
headerContext.setShowHeader(true); // Hide the header for false, Show the header for true (default)
}
}, [headerContext]);



useEffect(() => {
if (user) {
const userRef = doc(db, 'users', user.uid);
getDoc(userRef).then((docSnapshot) => {
if (docSnapshot.exists()) {
const userData = docSnapshot.data();
if (userData && userData.accountType) {
setaccountType(userData.accountType);
}
}
});
}
}, [user]);

return (
<IonPage className="ion-flex-offset-app">
<IonContent fullscreen>
Expand Down

0 comments on commit 0dbd699

Please sign in to comment.