Skip to content

Commit

Permalink
Merge pull request #430 from TAMUSHPE/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
JasonIsAzn authored Aug 17, 2024
2 parents 6bf3666 + 70e5cf3 commit aaf4081
Show file tree
Hide file tree
Showing 23 changed files with 260 additions and 121 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@
</p>

<p align="center">
Your Famila, Our Mission.
<a href="https://apps.apple.com/us/app/tamu-shpe/id6451004230">
<img alt="Download on the App Store" src="https://developer.apple.com/assets/elements/badges/download-on-the-app-store.svg" height="50">
</a>
&nbsp;
<a href="https://play.google.com/store/apps/details?id=com.tamu.shpe&pcampaignid=web_share">
<img alt="Get it on Google Play" src="https://upload.wikimedia.org/wikipedia/commons/7/78/Google_Play_Store_badge_EN.svg" height="50">
</a>
</p>

## Introduction

The TAMU SHPE mobile application, designed for the Texas A&M University Chapter of the Society of Hispanic Professional Engineers, is a tool aimed at enhancing member interaction and engagement. This application brings together a host of features, each developed to streamline organizational processes and encourage community involvement.
Expand Down
12 changes: 7 additions & 5 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"expo": {
"name": "TAMU SHPE",
"slug": "TAMU-SHPE",
"version": "1.0.2",
"version": "1.0.3",
"owner": "tamu-shpe",
"orientation": "portrait",
"icon": "./assets/icon.png",
Expand Down Expand Up @@ -34,9 +34,11 @@
}
],
[
"expo-barcode-scanner",
"expo-camera",
{
"cameraPermission": "TAMU SHPE needs to access the camera to scan QR codes."
"cameraPermission": "TAMU SHPE needs access to your camera to scan QRCode",
"microphonePermission": "Allow TAMUSHPE to access your microphone",
"recordAudioAndroid": false
}
]
],
Expand All @@ -57,8 +59,8 @@
},
"ios": {
"bundleIdentifier": "com.tamu.shpe",
"buildNumber": "1",
"userInterfaceStyle": "automatic"
"userInterfaceStyle": "automatic",
"buildNumber": "2"
},
"extra": {
"eas": {
Expand Down
12 changes: 9 additions & 3 deletions functions/src/committees.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as functions from 'firebase-functions';
import { db } from "./firebaseConfig"
import { db } from "./firebaseConfig";

export const updateCommitteeCount = functions.https.onCall(async (data, context) => {
async function updateCommitteeCounts() {
const committeesCount: CommitteeCounts = {};

const usersRef = db.collection('users');
Expand All @@ -24,10 +24,16 @@ export const updateCommitteeCount = functions.https.onCall(async (data, context)

console.log('Committee counts updated:', committeesCount);
return { message: 'Committee counts updated successfully', committeesCount };
}

export const updateCommitteeCount = functions.https.onCall(async (data, context) => {
return updateCommitteeCounts();
});

export const scheduleCommitteeCount = functions.pubsub.schedule('every 24 hours').onRun(async (context) => {
return updateCommitteeCounts();
});

interface CommitteeCounts {
[key: string]: number;
}

2 changes: 1 addition & 1 deletion functions/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { notifyUpcomingEvents, sendNotificationOfficeHours, sendNotificationMemberSHPE, sendNotificationCommitteeRequest, sendNotificationResumeConfirm } from "./pushNotification";
export { updateUserPoints, updateAllUserPoints, scheduledUpdateAllPoints } from "./pointSheet";
export { updateCommitteeCount } from "./committees";
export { updateCommitteeCount, scheduleCommitteeCount } from "./committees";
// export { resetOfficeScheduler } from "./officeReset";
export { resetOfficeOnCall } from "./officeReset";
export { zipResume } from "./resume";
Expand Down
11 changes: 6 additions & 5 deletions functions/src/types/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,19 +406,20 @@ export type UserEventData = {
eventLog?: SHPEEventLog,
}

export const getStatusMessage = (status: EventLogStatus): string => {
export const getStatusMessage = (status: EventLogStatus, mode?: "sign-in" | "sign-out"): string => {
const statusMessages = {
[EventLogStatus.SUCCESS]: "Successfully signed in/out.",
[EventLogStatus.SUCCESS]: `Successfully ${mode === "sign-in" ? "signed in" : "signed out"}.`,
[EventLogStatus.EVENT_OVER]: "The event is already over.",
[EventLogStatus.EVENT_ONGOING]: "The event is ongoing.",
[EventLogStatus.EVENT_NOT_STARTED]: "The event has not started yet.",
[EventLogStatus.EVENT_NOT_FOUND]: "The event was not found.",
[EventLogStatus.ALREADY_LOGGED]: "You have already signed in/out.",
[EventLogStatus.NOT_A_STUDENT]: "Only student can sign in/out of events..",
[EventLogStatus.ALREADY_LOGGED]: `You have already ${mode === "sign-in" ? "signed in" : "signed out"}.`,
[EventLogStatus.NOT_A_STUDENT]: "Only students can sign in/out of events.",
[EventLogStatus.EVENT_NOT_STARTED]: "The event has not started yet.",
[EventLogStatus.OUT_OF_RANGE]: "You are not close enough to the event to sign in/out.",
[EventLogStatus.ERROR]: "An internal error occurred. Please try again.",
};

return statusMessages[status] || "An unknown error occurred.";
};


4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "shpe-app",
"version": "1.0.2",
"version": "1.0.3",
"scripts": {
"start": "npx expo start --dev-client",
"test": "jest --coverage=true --verbose --bail --config ./jest.config.ts",
Expand Down Expand Up @@ -33,8 +33,8 @@
"expo": "~51.0.7",
"expo-application": "~5.9.1",
"expo-auth-session": "~5.5.2",
"expo-barcode-scanner": "~13.0.1",
"expo-build-properties": "~0.12.1",
"expo-camera": "~15.0.14",
"expo-clipboard": "~6.0.3",
"expo-constants": "~16.0.1",
"expo-crypto": "~13.0.2",
Expand Down
101 changes: 92 additions & 9 deletions shpe-app-web/app/(main)/tools/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ import { useRouter } from "next/navigation";
import Header from "@/components/Header";
import { onAuthStateChanged } from "firebase/auth";
import { auth } from "@/config/firebaseConfig";
import { getFunctions, httpsCallable } from "firebase/functions";
import { doc, onSnapshot } from "firebase/firestore";
import { db } from "@/config/firebaseConfig";

const Tools = () => {
const router = useRouter();
const [loading, setLoading] = useState(true);
const [isGenerated, setIsGenerated] = useState(false);
const [resumeDownloadInfo, setResumeDownloadInfo] = useState<ResumeDownloadInfo | null>(null);

useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
Expand All @@ -22,19 +27,97 @@ const Tools = () => {
return () => unsubscribe();
}, [router]);

if (loading) {
return (
<div className="flex w-full h-screen items-center justify-center">
<object type="image/svg+xml" data="spinner.svg" className="animate-spin -ml-1 mr-3 h-14 w-14 text-white"></object>
</div>
);
}
useEffect(() => {
const statusRef = doc(db, 'resumes/status');
const dataRef = doc(db, 'resumes/data');

const unsubscribeStatus = onSnapshot(statusRef, (docSnapshot) => {
if (docSnapshot.exists()) {
const statusData = docSnapshot.data();
setIsGenerated(statusData.isGenerated);
} else {
setIsGenerated(false);
}
});

const unsubscribeData = onSnapshot(dataRef, (docSnapshot) => {
if (docSnapshot.exists()) {
const downloadInfo = {
url: docSnapshot.data().url,
createdAt: docSnapshot.data().createdAt.toDate(),
expiresAt: docSnapshot.data().expiresAt.toDate(),
};
setResumeDownloadInfo(downloadInfo);
} else {
setResumeDownloadInfo(null);
}
});

return () => {
unsubscribeStatus();
unsubscribeData();
};
}, []);

const zipResumes = async () => {
setIsGenerated(false);
const functions = getFunctions();
const zipResumesFunction = httpsCallable(functions, 'zipResume');
try {
await zipResumesFunction();
} catch (error) {
console.error('Error:', error);
}
};

const handleDownloadResume = () => {
if (resumeDownloadInfo && resumeDownloadInfo.url) {
const link = document.createElement('a');
link.href = resumeDownloadInfo.url;
link.setAttribute('download', `resume_${new Date().toISOString()}.zip`);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
};

const isExpired = (expiresAt: Date) => {
const now = new Date();
return now > expiresAt;
};

return (
<div className="w-full h-full">
<Header title="Dashboard" iconPath="calendar-solid-gray.svg" />
<Header title="Tools" iconPath="screwdriver-sold.svg" />

<div className="mt-8 flex flex-col items-center">
<button
onClick={zipResumes}
className="bg-blue-500 text-white py-2 px-4 rounded mb-4"
>
Update Resume Download Link
</button>

{isGenerated && resumeDownloadInfo && !isExpired(resumeDownloadInfo.expiresAt) ? (
<button
onClick={handleDownloadResume}
className="bg-[#500000] text-white py-2 px-4 rounded"
>
Open Link to Download Resume
</button>
) : (
<p className="text-gray-500 mt-4">Link is being generated.</p>
)}
</div>
</div>
);
}

export default Tools;
interface ResumeDownloadInfo {
url: string;
createdAt: Date;
expiresAt: Date;
}


export default Tools;
25 changes: 0 additions & 25 deletions shpe-app-web/app/(main)/users/page.tsx

This file was deleted.

22 changes: 3 additions & 19 deletions shpe-app-web/app/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ const Navbar = () => {
</div>

{path == '/dashboard' ?
<Image src="Polygon1.svg" alt="Dashboard" width={25} height={20}
style={{ position: 'absolute', top: 9, right: -2, zIndex: 0 }} />
: ''
<Image src="Polygon1.svg" alt="Dashboard" width={25} height={20}
style={{ position: 'absolute', top: 9, right: -2, zIndex: 0 }} />
: ''
}
</Link>

Expand Down Expand Up @@ -98,22 +98,6 @@ const Navbar = () => {

</Link>

<Link href={'/users'} className={`pr-5 pl-5 hover:shadow-inner-strong relative w-full h-[45px] pt-2 ${path == '/users' ? 'bg-[#794141]' : 'bg-[#500000]'}`} >
<div className="flex flex-row ">
<Image src="user-solid.svg" alt="Dashboard" width={20} height={20} />
<div className=" pl-3 "> Users </div>
</div>

{

path == '/users' ?
<Image src="Polygon1.svg" alt="Dashboard" width={25} height={20}
style={{ position: 'absolute', top: 9, right: -2, zIndex: 0 }} />
: ''

}
</Link>

<Link href={'/tools'} className={`pr-5 pl-5 hover:shadow-inner-strong relative w-full h-[45px] pt-2 ${path == '/tools' ? 'bg-[#794141]' : 'bg-[#500000]'}`} >
<div className="flex flex-row ">
<Image src="screwdriver-sold.svg" alt="Dashboard" width={20} height={20} />
Expand Down
11 changes: 6 additions & 5 deletions shpe-app-web/app/types/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,19 +409,20 @@ export type UserEventData = {
eventLog?: SHPEEventLog,
}

export const getStatusMessage = (status: EventLogStatus): string => {
export const getStatusMessage = (status: EventLogStatus, mode?: "sign-in" | "sign-out"): string => {
const statusMessages = {
[EventLogStatus.SUCCESS]: "Successfully signed in/out.",
[EventLogStatus.SUCCESS]: `Successfully ${mode === "sign-in" ? "signed in" : "signed out"}.`,
[EventLogStatus.EVENT_OVER]: "The event is already over.",
[EventLogStatus.EVENT_ONGOING]: "The event is ongoing.",
[EventLogStatus.EVENT_NOT_STARTED]: "The event has not started yet.",
[EventLogStatus.EVENT_NOT_FOUND]: "The event was not found.",
[EventLogStatus.ALREADY_LOGGED]: "You have already signed in/out.",
[EventLogStatus.NOT_A_STUDENT]: "Only student can sign in/out of events..",
[EventLogStatus.ALREADY_LOGGED]: `You have already ${mode === "sign-in" ? "signed in" : "signed out"}.`,
[EventLogStatus.NOT_A_STUDENT]: "Only students can sign in/out of events.",
[EventLogStatus.EVENT_NOT_STARTED]: "The event has not started yet.",
[EventLogStatus.OUT_OF_RANGE]: "You are not close enough to the event to sign in/out.",
[EventLogStatus.ERROR]: "An internal error occurred. Please try again.",
};

return statusMessages[status] || "An unknown error occurred.";
};


4 changes: 3 additions & 1 deletion src/api/firebaseUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1291,7 +1291,9 @@ export const getMyEvents = async (committees: string[], interests: string[], max
querySnapshots.forEach(querySnapshot => {
querySnapshot.forEach(doc => {
if (!allEvents.has(doc.id)) {
allEvents.set(doc.id, doc.data());
const eventData = doc.data();
eventData.id = doc.id;
allEvents.set(doc.id, eventData);
}
});
});
Expand Down
11 changes: 7 additions & 4 deletions src/components/MOTMCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import React, { useCallback, useContext, useEffect, useState } from 'react'
import { MemberCardProp } from '../types/navigation'
import { Images } from '../../assets'
import { PublicUserInfo } from '../types/user'
import { getMOTM } from '../api/firebaseUtils'
import { getMOTM, getPublicUserData } from '../api/firebaseUtils'
import { useFocusEffect } from '@react-navigation/core'
import { UserContext } from '../context/UserContext'
import { truncateStringWithEllipsis } from '../helpers/stringUtils'
import { auth } from '../config/firebaseConfig'

const MOTMCard: React.FC<MemberCardProp> = ({ navigation }) => {
const userContext = useContext(UserContext);
const { userInfo, setUserInfo } = userContext!;
const { userInfo } = userContext!;

const fixDarkMode = userInfo?.private?.privateInfo?.settings?.darkMode;
const useSystemDefault = userInfo?.private?.privateInfo?.settings?.useSystemDefault;
Expand All @@ -35,7 +35,10 @@ const MOTMCard: React.FC<MemberCardProp> = ({ navigation }) => {
const fetchMOTM = async () => {
try {
const fetchedMOTM = await getMOTM();
setMOTM(fetchedMOTM);
if (fetchedMOTM?.uid) {
const motmData = await getPublicUserData(fetchedMOTM.uid);
setMOTM(motmData);
}
} catch (error) {
console.error('Error fetching member of the month:', error);
}
Expand Down Expand Up @@ -83,7 +86,7 @@ const MOTMCard: React.FC<MemberCardProp> = ({ navigation }) => {
}}
>
<Image
className="flex w-32 h-32 rounded-l-lg"
className="flex w-32 rounded-l-lg"
defaultSource={Images.DEFAULT_USER_PICTURE}
source={MOTM?.photoURL ? { uri: MOTM?.photoURL as string } : Images.DEFAULT_USER_PICTURE}
/>
Expand Down
Loading

0 comments on commit aaf4081

Please sign in to comment.