From 166b4f01b64ba561192a51900119dfd313a3775d Mon Sep 17 00:00:00 2001 From: Conner Bush Date: Thu, 8 Dec 2022 08:23:01 -0600 Subject: [PATCH] updates for 2022 season --- .vscode/settings.json | 8 +- App.tsx | 27 ++-- README.md | 40 +++--- app.json | 23 +++- components/ChaperoneGroupCard.tsx | 12 +- components/ChaperoneListCard.tsx | 10 +- context/assets.context.tsx | 47 +++++++ context/volunteer.context.tsx | 6 +- functions/index.js | 207 +++++++++++++++--------------- functions/package.json | 9 +- package.json | 2 + screens/Account.tsx | 10 +- screens/ChaperoneList.tsx | 12 +- screens/Rules.tsx | 7 +- screens/ScanDriversLicense.tsx | 16 +-- screens/Shopping.tsx | 7 +- screens/SignIn.tsx | 5 +- services/firestore.service.js | 2 +- 18 files changed, 268 insertions(+), 182 deletions(-) create mode 100644 context/assets.context.tsx diff --git a/.vscode/settings.json b/.vscode/settings.json index 81b6714..e262491 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "typescript.format.semicolons": "remove", - "prettier.semi": false, + "prettier.semi": true, "editor.wordWrap": "wordWrapColumn", "prettier.singleQuote": false, "typescript.preferences.quoteStyle": "auto", @@ -8,8 +8,6 @@ "editor.wordWrapColumn": 80, "typescript.format.insertSpaceAfterCommaDelimiter": true, "prettier.trailingComma": "es5", - "cSpell.words": [ - "Ionicons", - "mailchimp" - ] + "cSpell.words": ["Ionicons", "mailchimp"], + "javascript.format.semicolons": "insert" } diff --git a/App.tsx b/App.tsx index e194f86..8b4f1e0 100644 --- a/App.tsx +++ b/App.tsx @@ -9,6 +9,7 @@ import { useFonts } from "expo-font" import StylesProvider from "./context/styles.context" import VolunteerProvider from "./context/volunteer.context" import { GestureHandlerRootView } from "react-native-gesture-handler" +import AssetsProvider from "./context/assets.context" export default function App() { const isLoadingComplete = useCachedResources() @@ -22,18 +23,20 @@ export default function App() { if (isLoadingComplete && fontsLoaded) { return ( - - - - - - - - - - - - + + + + + + + + + + + + + + ) } else { return null diff --git a/README.md b/README.md index e2696f3..110fb26 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ ![c4k-horizontal](https://user-images.githubusercontent.com/68450309/155401405-cd59fd70-dc84-4438-96ed-1264ac21f321.png) - For over 35 years, Christmas 4 Kids has given the joy of Christmas to thousands of Middle Tennessee children that might not otherwise experience it. Each December, local businesses, volunteers, celebrities, recording artists, and their bus drivers set aside two days from their busy schedules for these special children. +For over 35 years, Christmas 4 Kids has given the joy of Christmas to thousands of Middle Tennessee children that might not otherwise experience it. Each December, local businesses, volunteers, celebrities, recording artists, and their bus drivers set aside two days from their busy schedules for these special children. ## The Biggest Christmas Party In Town - The entire year’s efforts come together when the buses pick up over 400 children and bring them to a Christmas Party held in their honor. Santa and Mrs. Claus host the party, which provides lunch (donated by Garth Brooks), live music, dancing and a lot of fun!! After the party, the children get back on the buses for a parade, led by the Nashville Trolley carrying Santa and Mrs. Claus, that stretches nearly five miles and features more than 70 Tour Buses, ending at Super Walmart in Hendersonville. Each child is met by his or her own chaperone, and they’re given $150.00 to buy anything they want. Plus, Christmas 4 Kids gives every child a brand new winter coat. +The entire year’s efforts come together when the buses pick up over 400 children and bring them to a Christmas Party held in their honor. Santa and Mrs. Claus host the party, which provides lunch (donated by Garth Brooks), live music, dancing and a lot of fun!! After the party, the children get back on the buses for a parade, led by the Nashville Trolley carrying Santa and Mrs. Claus, that stretches nearly five miles and features more than 70 Tour Buses, ending at Super Walmart in Hendersonville. Each child is met by his or her own chaperone, and they’re given $150.00 to buy anything they want. Plus, Christmas 4 Kids gives every child a brand new winter coat. ## Volunteer! @@ -20,12 +20,12 @@ C4K is made possible by generous donors just like you! Your donations put smiles This app was built to aid volunteers on the day of the C4K event. The app checks volunteers in by scanning their driver's license, saving organizers' time by not manually checking in each volunteer. The app also has use information such as event rules, event schedule, organizers' contact information, and a store map. -[Play Store Link](https://play.google.com/store/apps/details?id=com.c4k.shoppingeventmanager&hl=en_US&gl=US) --- [App Store Link](https://apps.apple.com/ng/app/christmas-4-kids/id1491062275) +[Play Store Link](https://play.google.com/store/apps/details?id=com.c4k.shoppingeventmanager&hl=en_US&gl=US) --- [App Store Link](https://apps.apple.com/ng/app/christmas-4-kids/id1491062275) - ### Tech Stack + ``` • React Native • Expo @@ -33,15 +33,23 @@ This app was built to aid volunteers on the day of the C4K event. The app checks • FireBase • Twilio ``` + ## How to install and run the app locally ### 1. Clone the repo + • `git clone https://github.com/Christmas-4-Kids/c4k.git` + ### 2. Change directory to C4K + • `cd C4K` + ### 3. Install dependencies + • `yarn` + ### 4. Start app + • `yarn start` Expo Developer Tools opens on `localhost:19002` @@ -49,7 +57,9 @@ Expo Developer Tools opens on `localhost:19002` --- ### [Download](https://developer.android.com/studio/?gclid=Cj0KCQiA09eQBhCxARIsAAYRiykJEPi1qfKv5Xmd1nPFXcQKFUy7_-LOP91bMxP7p8-ykpcuf6UPIG8aAlJoEALw_wcB&gclsrc=aw.ds) and [Install](https://developer.android.com/studio/install) Android Studio to run and [emulate and Android device](https://developer.android.com/studio/run/emulator) -or + +or + ### [Download](https://apps.apple.com/us/app/xcode/id497799835?mt=12) and install Xcode to emulate an IOS device --- @@ -79,12 +89,12 @@ Below are the important steps. For full documentation please see the [official F // Uncomment to run firebase functions locally // firebase.functions().useEmulator("localhost", 5001); ``` - - --- - - ## Roadmap - -- [ ] Convert map to be url based + +--- + +## Roadmap + +- [x] Convert map to be url based - [ ] Allow the app to work without being logged in (Countdown, socials, Store, events) - [ ] Add registration to app - [ ] Collect data on user activity @@ -99,10 +109,10 @@ Below are the important steps. For full documentation please see the [official F - [ ] Feature to share your experience the day after - [ ] Tooltips on how to use the app - [ ] Storage DL data and image tied to Volunteer - - ## Contributing - - Feel free to open an issue or contact a [contributer](https://github.com/orgs/Christmas-4-Kids/people) to get involved with development + +## Contributing + +Feel free to open an issue or contact a [contributer](https://github.com/orgs/Christmas-4-Kids/people) to get involved with development ## Building & Publishing to the app stores diff --git a/app.json b/app.json index 722bb1a..23dc5e5 100644 --- a/app.json +++ b/app.json @@ -2,7 +2,8 @@ "expo": { "name": "c4k", "slug": "c4k", - "version": "2.4.3", + "version": "2.5.0", + "sdkVersion": "45.0.0", "orientation": "portrait", "icon": "./assets/images/icon.png", "scheme": "myapp", @@ -26,7 +27,25 @@ "backgroundColor": "#112430" }, "package": "com.c4k.shoppingeventmanager", - "versionCode": 10 + "versionCode": 13, + "permissions": [ + "CAMERA", + "VIBRATE", + "READ_PHONE_STATE", + "FOREGROUND_SERVICE", + "WAKE_LOCK", + "com.anddoes.launcher.permission.UPDATE_COUNT", + "com.android.launcher.permission.INSTALL_SHORTCUT", + "com.google.android.c2dm.permission.RECEIVE", + "com.google.android.gms.permission.ACTIVITY_RECOGNITION", + "com.google.android.providers.gsf.permission.READ_GSERVICES", + "com.htc.launcher.permission.READ_SETTINGS", + "com.htc.launcher.permission.UPDATE_SHORTCUT", + "com.majeur.launcher.permission.UPDATE_BADGE", + "com.sec.android.provider.badge.permission.READ", + "com.sec.android.provider.badge.permission.WRITE", + "com.sonyericsson.home.permission.BROADCAST_BADGE" + ] }, "web": { "favicon": "./assets/images/favicon.png" diff --git a/components/ChaperoneGroupCard.tsx b/components/ChaperoneGroupCard.tsx index ca0d3a9..e010b47 100644 --- a/components/ChaperoneGroupCard.tsx +++ b/components/ChaperoneGroupCard.tsx @@ -74,14 +74,14 @@ export const ChaperoneGroupCard = () => { const ChaperoneListItem = ({ name, phone, chaperoneList, setChaperoneList }) => { const { styles } = useStyles() - const pressCall = () => { + const pressCall = async () => { const url = `tel://${phone}` - Linking.openURL(url) + await Linking.openURL(url) } - const removeContact = phone => { - setChaperoneList(chaperoneList.filter(chaperone => chaperone.phone !== phone)) - AsyncStorage.setItem("chaperoneList", JSON.stringify(chaperoneList.filter(chaperone => chaperone.phone !== phone))) + const removeContact = (phone) => { + setChaperoneList(chaperoneList.filter((chaperone) => chaperone.phone !== phone)) + AsyncStorage.setItem("chaperoneList", JSON.stringify(chaperoneList.filter((chaperone) => chaperone.phone !== phone))) } return ( @@ -96,7 +96,7 @@ const ChaperoneListItem = ({ name, phone, chaperoneList, setChaperoneList }) => {name} - pressCall()} /> + await pressCall()} /> ) } diff --git a/components/ChaperoneListCard.tsx b/components/ChaperoneListCard.tsx index ad4a8b2..d40a44e 100644 --- a/components/ChaperoneListCard.tsx +++ b/components/ChaperoneListCard.tsx @@ -9,15 +9,15 @@ import { C4kText } from "./C4kText" const getVolunteerType = (volunteerType: string) => { switch (volunteerType) { - case "2021_ADMIN": + case "2022_ADMIN": return "Organizer" - case "2021_ALL_DAY_CHAPERONE": + case "2022_ALL_DAY_CHAPERONE": return "All Day Chaperone" - case "2021_EVENING_CHAPERONE": + case "2022_EVENING_CHAPERONE": return "Evening Chaperone" - case "2021_LEBANON_CHAPERONE": + case "2022_LEBANON_CHAPERONE": return "Lebanon Chaperone" - case "2021_DRIVER": + case "2022_DRIVER": return "Driver" default: return "Unknown" diff --git a/context/assets.context.tsx b/context/assets.context.tsx new file mode 100644 index 0000000..7fe4ef0 --- /dev/null +++ b/context/assets.context.tsx @@ -0,0 +1,47 @@ +import React, { useEffect, useState } from "react" +import { collection, onSnapshot, orderBy, query } from "firebase/firestore" +import { db } from "../services/firestore.service" + +type AssetsContext = { + assets: Map +} + +const AssetsContext = React.createContext({ + assets: new Map(), +}) + +export default function AssetProvider({ children }: { children: any }) { + const [assets, setAssets] = useState(new Map()) + + useEffect(() => { + const unsub = onSnapshot(query(collection(db, "assetUrls"), orderBy("name")), (querySnapshot) => { + const tempAssets = new Map() + querySnapshot.forEach((doc) => { + const asset = doc.data() + tempAssets.set(asset.name, asset.url) + }) + setAssets(tempAssets) + }) + return () => { + unsub() + } + }, []) + + return ( + + {children} + + ) +} + +export const useAssets = () => { + const context = React.useContext(AssetsContext) + if (context === undefined) { + throw new Error("useAssets must be used inside a AssetProvider") + } + return context +} diff --git a/context/volunteer.context.tsx b/context/volunteer.context.tsx index 5ade083..e2805a6 100644 --- a/context/volunteer.context.tsx +++ b/context/volunteer.context.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from "react" -import { collection, onSnapshot, orderBy, query } from "firebase/firestore" +import { collection, onSnapshot, orderBy, query, where } from "firebase/firestore" import { db } from "../services/firestore.service" export interface Address { @@ -75,9 +75,9 @@ export default function VolunteerProvider({ children }: { children: any }) { const [volunteers, setVolunteers] = useState([]) useEffect(() => { - const unsub = onSnapshot(query(collection(db, "volunteers"), orderBy("lastNameLower")), querySnapshot => { + const unsub = onSnapshot(query(collection(db, "volunteers"), where("volunteerYear", "==", "2022"), orderBy("lastNameLower")), (querySnapshot) => { const tempVolunteers = [] - querySnapshot.forEach(doc => { + querySnapshot.forEach((doc) => { tempVolunteers.push(createVolunteer(doc.data())) }) setVolunteers(tempVolunteers) diff --git a/functions/index.js b/functions/index.js index 32b441a..88f38ab 100644 --- a/functions/index.js +++ b/functions/index.js @@ -1,183 +1,190 @@ -const functions = require("firebase-functions") -const admin = require("firebase-admin") -const mailchimp = require("@mailchimp/mailchimp_marketing") -const twilio = require("twilio") -const Firestore = require("@google-cloud/firestore") -const PROJECTID = "c4k-events" +const functions = require("firebase-functions"); +const admin = require("firebase-admin"); +const mailchimp = require("@mailchimp/mailchimp_marketing"); +const twilio = require("twilio"); +const Firestore = require("@google-cloud/firestore"); +const PROJECTID = "c4k-events"; const firestore = new Firestore({ projectId: PROJECTID, timestampsInSnapshots: true, -}) +}); -admin.initializeApp(functions.config().firebase) +admin.initializeApp(functions.config().firebase); // mailchimp constants -const mailchimpServer = functions.config().mailchimp.server -const mailchimpApiKey = functions.config().mailchimp.key -const allDayChaperonesListId = functions.config().mailchimp.alldaychaperoneslistid -const driversListId = functions.config().mailchimp.driverslistid -const eveningChaperonesListId = functions.config().mailchimp.eveningchaperoneslistid -const lebanonChaperonesListId = functions.config().mailchimp.lebanonchaperoneslistid +const mailchimpServer = functions.config().mailchimp.server; +const mailchimpApiKey = functions.config().mailchimp.key; +const allDayChaperonesListId = functions.config().mailchimp.alldaychaperoneslistid; +const driversListId = functions.config().mailchimp.driverslistid; +const eveningChaperonesListId = functions.config().mailchimp.eveningchaperoneslistid; +const lebanonChaperonesListId = functions.config().mailchimp.lebanonchaperoneslistid; mailchimp.setConfig({ apiKey: mailchimpApiKey, server: mailchimpServer, -}) -const memberListIds = [allDayChaperonesListId, driversListId, eveningChaperonesListId, lebanonChaperonesListId] +}); +const memberListIds = [allDayChaperonesListId, driversListId, eveningChaperonesListId, lebanonChaperonesListId]; // twilio constants -const accountSid = functions.config().twilio.sid -const authToken = functions.config().twilio.token -const serviceSid = functions.config().twilio.servicesid -const twilioClient = new twilio(accountSid, authToken) +const accountSid = functions.config().twilio.sid; +const authToken = functions.config().twilio.token; +const serviceSid = functions.config().twilio.servicesid; +const twilioClient = new twilio(accountSid, authToken); // TWILIO: send user their verification code exports.verifyNumber = functions.https.onCall(async (phoneNumber, context) => { twilioClient.verify .services(serviceSid) .verifications.create({ to: phoneNumber, channel: "sms" }) - .then(verification => { - return verification + .then((verification) => { + return verification; }) -}) + .catch((err) => { + console.log(err); + }); +}); // TWILIO: verify user's code exports.verifyCode = functions.https.onCall(async (data, context) => { return twilioClient.verify .services(serviceSid) .verificationChecks.create({ to: data.phoneNumber, code: data.code }) - .then(data => { - return data.status + .then((data) => { + return data.status; }) -}) + .catch((err) => { + console.log(err); + }); +}); exports.checkIfRegistered = functions.https.onCall(async (email, context) => { - const response = await mailchimp.searchMembers.search(email) - let mailchimpMember = response?.exact_matches?.members.find(member => memberListIds.includes(member.list_id)) + const response = await mailchimp.searchMembers.search(email); + let mailchimpMember = response?.exact_matches?.members.find((member) => memberListIds.includes(member.list_id)); if (email.toLowerCase() === "c4kchaperones@gmail.com") { - return response?.exact_matches?.members[0] + return response?.exact_matches?.members[0]; } - return mailchimpMember -}) + return mailchimpMember; +}); exports.createMailchimpUserInFirestore = functions.region("us-central1").https.onCall(async (mailchimpMember, context) => { - const volunteer = createVolunteer(mailchimpMember) - let documentRef = admin.firestore().doc("volunteers/" + mailchimpMember.id) + const volunteer = createVolunteer(mailchimpMember); + let documentRef = admin.firestore().doc("volunteers/" + mailchimpMember.id); return documentRef .set(volunteer) - .then(res => { - return { user: volunteer } + .then((res) => { + return { user: volunteer }; }) - .catch(err => { - return { error: `Failed to create document: ${err}` } - }) -}) + .catch((err) => { + return { error: `Failed to create document: ${err}` }; + }); +}); exports.fetchRules = functions.https.onCall(async () => { - let rules = [] + let rules = []; await firestore .collection("rules") .get() - .then(querySnapshot => { - querySnapshot.forEach(doc => { + .then((querySnapshot) => { + querySnapshot.forEach((doc) => { // doc.data() is never undefined for query doc snapshots - rules.push(doc.data()) - }) - }) - return rules -}) + rules.push(doc.data()); + }); + }); + return rules; +}); exports.updateVolunteerCheckedIn = functions.https.onCall(async ({ checkedIn, refId }) => { await firestore.collection("volunteers").doc(refId).update({ checkedIn: checkedIn, - }) -}) + }); +}); exports.syncMailchimpVolunteers = functions.https.onCall(async () => { - const mailchimpVolunteers = new Map() - const mapMailchimpVolunteers = volunteers => { + const mailchimpVolunteers = new Map(); + const mapMailchimpVolunteers = (volunteers) => { for (const volunteer of volunteers) { - mailchimpVolunteers.set(volunteer.id, volunteer) + mailchimpVolunteers.set(volunteer.id, volunteer); } - } + }; // get all mailchimp users for all 4 list ids - const opts = { count: 1000 } - const { members: allDayList } = await mailchimp.lists.getListMembersInfo(allDayChaperonesListId, opts) - mapMailchimpVolunteers(allDayList) - const { members: eveningList } = await mailchimp.lists.getListMembersInfo(eveningChaperonesListId, opts) - mapMailchimpVolunteers(eveningList) - const { members: lebanonList } = await mailchimp.lists.getListMembersInfo(lebanonChaperonesListId, opts) - mapMailchimpVolunteers(lebanonList) - const { members: driversList } = await mailchimp.lists.getListMembersInfo(driversListId, opts) - mapMailchimpVolunteers(driversList) + const opts = { count: 1000 }; + const { members: allDayList } = await mailchimp.lists.getListMembersInfo(allDayChaperonesListId, opts); + mapMailchimpVolunteers(allDayList); + const { members: eveningList } = await mailchimp.lists.getListMembersInfo(eveningChaperonesListId, opts); + mapMailchimpVolunteers(eveningList); + const { members: lebanonList } = await mailchimp.lists.getListMembersInfo(lebanonChaperonesListId, opts); + mapMailchimpVolunteers(lebanonList); + const { members: driversList } = await mailchimp.lists.getListMembersInfo(driversListId, opts); + mapMailchimpVolunteers(driversList); // get all volunteers in firebase - let firebaseVolunteers = new Map() + let firebaseVolunteers = new Map(); await firestore .collection("volunteers") .get() - .then(querySnapshot => { - querySnapshot.forEach(doc => { + .then((querySnapshot) => { + querySnapshot.forEach((doc) => { // doc.data() is never undefined for query doc snapshots - const volunteer = doc.data() - firebaseVolunteers.set(volunteer.id, volunteer) - }) - }) + const volunteer = doc.data(); + firebaseVolunteers.set(volunteer.id, volunteer); + }); + }); // if mailchimp user is not in list of volunteers then create user - let membersInMailchimpNotInFirebase = [] + let membersInMailchimpNotInFirebase = []; for (const [key, value] of mailchimpVolunteers) { - const firebaseVolunteer = firebaseVolunteers.get(key) + const firebaseVolunteer = firebaseVolunteers.get(key); if (!firebaseVolunteer) { - membersInMailchimpNotInFirebase.push(value) + membersInMailchimpNotInFirebase.push(value); } } for (const member of membersInMailchimpNotInFirebase) { - const volunteer = createVolunteer(member) - let documentRef = admin.firestore().doc("volunteers/" + member.id) - documentRef.set(volunteer).catch(err => { - return { error: `Failed to create document: ${err}` } - }) + const volunteer = createVolunteer(member); + let documentRef = admin.firestore().doc("volunteers/" + member.id); + documentRef.set(volunteer).catch((err) => { + return { error: `Failed to create document: ${err}` }; + }); } -}) +}); //retrieve schedule from firestore exports.fetchSchedule = functions.https.onCall(async () => { - let events = [] + let events = []; await firestore .collection("schedule") .get() - .then(querySnapshot => { - querySnapshot.forEach(doc => { - events.push(doc.data()) - }) - }) - return events -}) - -const getVolunteerType = mailchimpMember => { - const listId = mailchimpMember.list_id + .then((querySnapshot) => { + querySnapshot.forEach((doc) => { + events.push(doc.data()); + }); + }); + return events; +}); + +const getVolunteerType = (mailchimpMember) => { + const listId = mailchimpMember.list_id; if (listId === allDayChaperonesListId) { - return "2021_ALL_DAY_CHAPERONE" + return "2022_ALL_DAY_CHAPERONE"; } else if (listId === eveningChaperonesListId) { - return "2021_EVENING_CHAPERONE" + return "2022_EVENING_CHAPERONE"; } else if (listId === lebanonChaperonesListId) { - return "2021_LEBANON_CHAPERONE" + return "2022_LEBANON_CHAPERONE"; } else if (listId === driversListId) { - return "2021_DRIVER" + return "2022_DRIVER"; } else { if (mailchimpMember.email_address.toLowerCase() === "c4kchaperones@gmail.com") { - return "2021_ADMIN" + return "2022_ADMIN"; } - return "2021_INVALID" + return "2022_INVALID"; } -} +}; -const createVolunteer = mailchimpMember => { +const createVolunteer = (mailchimpMember) => { const volunteer = { checkedIn: false, volunteerType: getVolunteerType(mailchimpMember), + volunteerYear: "2022", driversLicense: "", email: mailchimpMember.email_address, emailLower: mailchimpMember.email_address.toLowerCase(), @@ -191,6 +198,6 @@ const createVolunteer = mailchimpMember => { verified: false, medical: mailchimpMember.merge_fields.MEDICAL ?? "", mailchimpMemberInfo: mailchimpMember, - } - return volunteer -} + }; + return volunteer; +}; diff --git a/functions/package.json b/functions/package.json index 8b9357a..4213c54 100644 --- a/functions/package.json +++ b/functions/package.json @@ -13,13 +13,14 @@ }, "main": "index.js", "dependencies": { - "@mailchimp/mailchimp_marketing": "^3.0.69", - "firebase-admin": "^9.8.0", - "firebase-functions": "^3.14.1", + "@mailchimp/mailchimp_marketing": "^3.0.80", + "firebase-admin": "^11.3.0", + "firebase-functions": "^4.1.0", "twilio": "^3.69.0" }, "devDependencies": { - "firebase-functions-test": "^0.2.0" + "@types/mailchimp__mailchimp_marketing": "^3.0.6", + "firebase-functions-test": "^3.0.0" }, "private": true } diff --git a/package.json b/package.json index b2b292a..b80e0f0 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "expo": "^45.0.0", "expo-asset": "~8.5.0", "expo-barcode-scanner": "~11.3.0", + "expo-build-properties": "~0.2.0", "expo-cli": "^6.0.8", "expo-constants": "~13.1.1", "expo-device": "~4.2.0", @@ -29,6 +30,7 @@ "expo-linking": "~3.1.0", "expo-splash-screen": "~0.15.1", "expo-status-bar": "~1.3.0", + "expo-updates": "~0.13.4", "expo-web-browser": "~10.2.1", "firebase": "9.4.1", "firebase-functions": "^3.15.7", diff --git a/screens/Account.tsx b/screens/Account.tsx index 2a04988..fc2598f 100644 --- a/screens/Account.tsx +++ b/screens/Account.tsx @@ -9,13 +9,13 @@ import { C4kText } from "../components/C4kText" const getVolunteerType = (volunteerType: string) => { switch (volunteerType) { - case "2021_ADMIN": + case "2022_ADMIN": return "Organizer" - case "2021_ALL_DAY_CHAPERONE": - case "2021_EVENING_CHAPERONE": - case "2021_LEBANON_CHAPERONE": + case "2022_ALL_DAY_CHAPERONE": + case "2022_EVENING_CHAPERONE": + case "2022_LEBANON_CHAPERONE": return "Chaperone" - case "2021_DRIVER": + case "2022_DRIVER": return "Driver" default: return "Unknown" diff --git a/screens/ChaperoneList.tsx b/screens/ChaperoneList.tsx index 6284864..fb63114 100644 --- a/screens/ChaperoneList.tsx +++ b/screens/ChaperoneList.tsx @@ -35,19 +35,19 @@ export const ChaperoneList = ({ navigation }) => { if (!useChaperoneFilters) return true if (searchFilters.allDay) { - volunteerTypesToFilter.push("2021_ALL_DAY_CHAPERONE") + volunteerTypesToFilter.push("2022_ALL_DAY_CHAPERONE") } if (searchFilters.evening) { - volunteerTypesToFilter.push("2021_EVENING_CHAPERONE") + volunteerTypesToFilter.push("2022_EVENING_CHAPERONE") } if (searchFilters.lebanon) { - volunteerTypesToFilter.push("2021_LEBANON_CHAPERONE") + volunteerTypesToFilter.push("2022_LEBANON_CHAPERONE") } if (searchFilters.admin) { - volunteerTypesToFilter.push("2021_ADMIN") + volunteerTypesToFilter.push("2022_ADMIN") } if (searchFilters.driver) { - volunteerTypesToFilter.push("2021_DRIVER") + volunteerTypesToFilter.push("2022_DRIVER") } return volunteerTypesToFilter.includes(volunteerType) } @@ -82,7 +82,7 @@ export const ChaperoneList = ({ navigation }) => { } useEffect(() => { - const newFilteredVolunteers = volunteers.filter(v => { + const newFilteredVolunteers = volunteers.filter((v) => { const useSearch = searchName.length >= 2 if (useSearch) { return ( diff --git a/screens/Rules.tsx b/screens/Rules.tsx index 25d4525..c9c8c62 100644 --- a/screens/Rules.tsx +++ b/screens/Rules.tsx @@ -3,7 +3,6 @@ import { View, Text } from "react-native" import { fetchRules } from "../services/firestore.service" import { Loading } from "./Loading" import { useUser } from "../context/user.context" -import StickyScreenWrapper from "./StickyScreenWrapper" import RulesGroup from "../components/RulesGroup" import ScreenWrapper from "./ScreenWrapper" import { Card } from "../components/Card" @@ -18,16 +17,16 @@ export const Rules = () => { const volunteerType = user.volunteerType.slice(5) //removes 2021_ prefix useEffect(() => { - fetchRules().then(data => { + fetchRules().then((data) => { setRules((data as any).data) }) }, []) useEffect(() => { - const uniqueGroups = [...new Set(rules.filter(rule => rule.volunteerTypes?.includes(volunteerType)).map(rule => rule.group))] + const uniqueGroups = [...new Set(rules.filter((rule) => rule.volunteerTypes?.includes(volunteerType)).map((rule) => rule.group))] const gRules = [] for (const group of uniqueGroups) { - const orderedGroupRulesByGroup = rules.filter(rule => rule.group === group).sort((first, last) => first.order - last.order) + const orderedGroupRulesByGroup = rules.filter((rule) => rule.group === group).sort((first, last) => first.order - last.order) gRules.push({ group, rules: orderedGroupRulesByGroup }) } // sorts the groups themselves diff --git a/screens/ScanDriversLicense.tsx b/screens/ScanDriversLicense.tsx index 6a209bc..0ab3bca 100644 --- a/screens/ScanDriversLicense.tsx +++ b/screens/ScanDriversLicense.tsx @@ -114,15 +114,15 @@ const pdf417Map: Map = new Map([ const getVolunteerType = (volunteerType: string) => { switch (volunteerType) { - case "2021_ADMIN": + case "2022_ADMIN": return "Organizer" - case "2021_ALL_DAY_CHAPERONE": + case "2022_ALL_DAY_CHAPERONE": return "All Day Chaperone" - case "2021_EVENING_CHAPERONE": + case "2022_EVENING_CHAPERONE": return "Evening Chaperone" - case "2021_LEBANON_CHAPERONE": + case "2022_LEBANON_CHAPERONE": return "Lebanon Chaperone" - case "2021_DRIVER": + case "2022_DRIVER": return "Driver" default: return "Unknown" @@ -144,8 +144,8 @@ export const ScanDriversLicense = ({ navigation }) => { }, []) useEffect(() => { - const volunteerMatchesIds = volunteerMatches.map(v => v.mailchimpMemberId) - setVolunteerMatches(volunteers.filter(v => volunteerMatchesIds.includes(v.mailchimpMemberId))) + const volunteerMatchesIds = volunteerMatches.map((v) => v.mailchimpMemberId) + setVolunteerMatches(volunteers.filter((v) => volunteerMatchesIds.includes(v.mailchimpMemberId))) }, [volunteers]) const handleBarCodeScanned = ({ type, data }) => { @@ -205,7 +205,7 @@ export const ScanDriversLicense = ({ navigation }) => { No Matches Found ) : ( - volunteerMatches.map(volunteer => ( + volunteerMatches.map((volunteer) => ( diff --git a/screens/Shopping.tsx b/screens/Shopping.tsx index 248717a..e706bf5 100644 --- a/screens/Shopping.tsx +++ b/screens/Shopping.tsx @@ -1,14 +1,13 @@ import React from "react" import ImageViewer from "react-native-image-zoom-viewer" import ScreenWrapper from "./ScreenWrapper" +import { useAssets } from "../context/assets.context" export const Shopping = () => { + const { assets } = useAssets() const images = [ { - url: "", - props: { - source: require("../assets/images/map.png"), - }, + url: assets.get("map"), }, ] return ( diff --git a/screens/SignIn.tsx b/screens/SignIn.tsx index 87072a2..f1b2f8c 100644 --- a/screens/SignIn.tsx +++ b/screens/SignIn.tsx @@ -70,6 +70,7 @@ export const SignIn = () => { let mailchimpUser try { const { data } = await checkIfRegistered(email.trim()) + console.log(data) mailchimpUser = data } catch (err) { return registrationError("Oops! Looks like something went wrong! We'll work on fixing it real soon.", { @@ -109,14 +110,14 @@ export const SignIn = () => { phoneNumber: `+1${phoneNumber}`, code: verificationCode, }) - .then(result => { + .then((result) => { if (result.data === "approved") { saveUser({ ...user, verified: true }) } else { setErrorMessage("Invalid verification code") } }) - .catch(err => { + .catch((err) => { console.log(`err`, err) }) .finally(() => { diff --git a/services/firestore.service.js b/services/firestore.service.js index 186a471..f6ee085 100644 --- a/services/firestore.service.js +++ b/services/firestore.service.js @@ -20,7 +20,7 @@ const app = initializeApp({ const functions = getFunctions(app) // Uncomment to run firebase functions locally -// connectFunctionsEmulator(functions, "localhost", 5001) +//connectFunctionsEmulator(functions, "localhost", 5001) // firebase functions export const checkIfRegistered = httpsCallable(functions, "checkIfRegistered")