Skip to content

Commit

Permalink
Merge pull request #122 from ThatNinjaGuy/develop
Browse files Browse the repository at this point in the history
Enabled notifications to work based on user's notification settings #87 #88
  • Loading branch information
ThatNinjaGuy authored Oct 12, 2024
2 parents 02965e0 + 4cfa69e commit 2efbef7
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 116 deletions.
21 changes: 12 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,28 @@ This project is a comprehensive React Native application for managing a restaura
- [✨ Features](#-features)
- [📸 Screenshots](#-screenshots)
- [🚀 Installation](#-installation)
- [🔥 Firebase Setup](#-firebase-setup)
- [🏗️ Project Structure](#-project-structure)
- [📱 Usage](#-usage)
- [📦 Building the APK](#-building-the-apk)
- [🤝 Contributing](#-contributing)
- [📄 License](#-license)

## ✨ Features

- **Dashboard Overview**: Provides a summary of the day's revenue, orders, reservations, low inventory, and staff status.
- **Notifications**: Displays important notifications such as new orders, staff meetings, and low inventory alerts.
- **Quick Actions**: Allows quick navigation to different sections like Menu, Orders, Staffs, and Inventory.
- **Menu Management**: Add, update, and delete menu items.
- **Menu Management**: Add, update, and delete menu items with real-time updates.
- **Order Management**: View and manage orders, including order details and table management.
- **Inventory Management**: Add, update, and delete inventory items.
- **Table Management**: Efficiently manage table assignments and availability.
- **Inventory Management**: Add, update, and delete inventory items with low stock alerts.
- **Staff Management**: Manage staff schedules, roles, and performance.
- **Reservation System**: Handle customer reservations and table bookings.
- **Reporting and Analytics**: Generate insights on sales, popular dishes, and peak hours.
- **Multi-language Support**: Cater to diverse customer bases with multiple language options.
- **Customizable Themes**: Adapt the app's appearance to match your restaurant's branding.
- **Offline Support**: Works seamlessly offline and syncs data when the internet is available.
- **Firebase Firestore Integration**: Uses Firestore for real-time data storage and retrieval.
- **Batch Operations**: Efficiently add multiple items using batch write operations.
- **User-Friendly Interface**: Simple and intuitive UI for managing menu items.
- **User-Friendly Interface**: Simple and intuitive UI for managing all aspects of restaurant operations.
- **Role-Based Access Control**: Ensure proper access levels for different staff members.
- **Integration with POS Systems**: Seamlessly connect with popular Point of Sale systems.
- **Customer Feedback System**: Collect and manage customer reviews and ratings.

## 🎥 Demo

Expand Down
4 changes: 2 additions & 2 deletions components/Authentication/AuthProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ export const AuthProvider = ({ children }) => {
useEffect(() => {
notificationListener.current =
Notifications.addNotificationReceivedListener((notification) => {
console.log("Notification received:", notification);
console.log("Notification received");
});

responseListener.current =
Notifications.addNotificationResponseReceivedListener((response) => {
console.log("Notification response received:", response);
console.log("Notification response received");
});

return () => {
Expand Down
30 changes: 6 additions & 24 deletions components/Settings/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import { ThemedText } from "@/components/common/ThemedText";
import { Tooltip, Text } from "react-native-elements";
import { updateStaff } from "@/firebase/queries/staffs";
import LoadingScreen from "@/components/LoadingScreen/LoadingScreen";
import {
DEFAULT_NOTIFICATION_SETTINGS,
NOTIFICATION_SETTINGS_LABELS,
} from "@/constants/notificationControls";

const SettingsScreen = ({ userDetails, staffs, onCancel }) => {
const [name, setName] = useState(userDetails?.name || "");
Expand All @@ -29,10 +33,7 @@ const SettingsScreen = ({ userDetails, staffs, onCancel }) => {
userDetails?.preferredLanguage || appDefaultLanguage
);
const [notificationSettings, setNotificationSettings] = useState({
newOrders: false,
orderReady: false,
orderCompleted: false,
newGuests: false,
...DEFAULT_NOTIFICATION_SETTINGS,
...userDetails?.notificationSettings,
});
const [loading, setLoading] = useState(false);
Expand Down Expand Up @@ -67,25 +68,6 @@ const SettingsScreen = ({ userDetails, staffs, onCancel }) => {
onCancel();
};

const notificationSettingTypes = [
{
displayText: "New Order receivied",
key: "newOrders",
},
{
displayText: "Order Ready for pickup",
key: "orderReady",
},
{
displayText: "Order Complete",
key: "orderCompleted",
},
{
displayText: "New Guest arrived",
key: "newGuests",
},
];

if (loading) {
return <LoadingScreen />;
}
Expand Down Expand Up @@ -203,7 +185,7 @@ const SettingsScreen = ({ userDetails, staffs, onCancel }) => {
</TouchableOpacity>
{expandedNotificationsSection && (
<View style={styles.sectionContent}>
{notificationSettingTypes.map((item, index) => (
{NOTIFICATION_SETTINGS_LABELS.map((item, index) => (
<View key={index} style={styles.switchContainer}>
<ThemedText>{item.displayText}</ThemedText>
<Switch
Expand Down
31 changes: 31 additions & 0 deletions constants/notificationControls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export const NEW_ORDERS = "newOrders";
export const ORDER_READY = "orderReady";
export const ORDER_COMPLETED = "orderCompleted";
export const NEW_GUESTS = "newGuests";
export const UNKNOWN_CATEGORY = "unknownCategory";

export const DEFAULT_NOTIFICATION_SETTINGS = {
[NEW_ORDERS]: true,
[ORDER_READY]: true,
[ORDER_COMPLETED]: true,
[NEW_GUESTS]: false,
};

export const NOTIFICATION_SETTINGS_LABELS = [
{
displayText: "New Order receivied",
key: NEW_ORDERS,
},
{
displayText: "Order Ready for pickup",
key: ORDER_READY,
},
{
displayText: "Order Complete",
key: ORDER_COMPLETED,
},
// {
// displayText: "New Guest arrived",
// key: NEW_GUESTS,
// },
];
4 changes: 4 additions & 0 deletions constants/status/orders.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ export const COMPLETED_ORDERS = [ORDER_STATUS.COMPLETE];
export const CANCELLED_ORDERS = [ORDER_STATUS.CANCEL, ORDER_STATUS.CANCELLED];
export const ALL_KITCHEN_ORDERS = [ORDER_STATUS.ACTIVE, ORDER_STATUS.PENDING];
export const ALL_SERVER_ORDERS = [ORDER_STATUS.READY, ORDER_STATUS.CANCEL];
export const ALL_COMPLETE_ORDERS = [
ORDER_STATUS.COMPLETE,
ORDER_STATUS.CANCELLED,
];
24 changes: 18 additions & 6 deletions firebase/queries/staffs.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Platform } from "react-native";
import { db } from "@/firebase/firebaseConfig";
import { generateUniqueKey } from "@/utils/keyGenerator";
import { DEFAULT_NOTIFICATION_SETTINGS } from "@/constants/notificationControls";

export const staffsPath = "hotel-details/staff-details/staffs";
export const signUpRequestsPath = "hotel-details/staff-details/signup-requests";
Expand Down Expand Up @@ -39,6 +40,22 @@ export const fetchAllSignupRequests = async (setRequests, setLoading) => {
}
};

export const addSignUpRequest = async (userData) => {
try {
if (Platform.OS === "web") {
const { collection, addDoc } = await import("firebase/firestore");
await addDoc(collection(db, signUpRequestsPath), userData);
} else {
await db.collection(signUpRequestsPath).add(userData);
}
console.log("Sign-up request added successfully");
return true;
} catch (error) {
console.error("Error adding sign-up request:", error);
return false;
}
};

export const deleteSignupRequest = async (id) => {
try {
if (Platform.OS === "web") {
Expand Down Expand Up @@ -147,12 +164,7 @@ export const addToStaffs = async (
authId: authId,
mobile: mobile,
preferredLanguage: appDefaultLanguage,
notificationSettings: {
newOrders: true,
orderReady: true,
orderCompleted: true,
newGuests: false,
},
notificationSettings: DEFAULT_NOTIFICATION_SETTINGS,
createdAt: Date.now(),
};

Expand Down
26 changes: 13 additions & 13 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"expo-blur": "~13.0.2",
"expo-build-properties": "^0.12.5",
"expo-constants": "~16.0.2",
"expo-dev-client": "~4.0.27",
"expo-dev-client": "~4.0.28",
"expo-device": "~6.0.2",
"expo-file-system": "~17.0.1",
"expo-font": "~12.0.8",
Expand Down
39 changes: 19 additions & 20 deletions screens/ApproveSignUpRequestsScreen/ApproveSignUpRequestsScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
deleteSignupRequest,
addToStaffs,
} from "@/firebase/queries/staffs";
import { ThemedText } from "@/components/common/ThemedText";

const ApproveSignUpRequestsScreen = () => {
const { user } = useContext(AuthContext);
Expand All @@ -51,7 +52,6 @@ const ApproveSignUpRequestsScreen = () => {

// Create a secondary app for user creation
const secondaryApp = initializeApp(firebaseConfig, "Secondary");

useEffect(() => {
fetchAllSignupRequests(setRequests, setLoading);
}, []);
Expand Down Expand Up @@ -82,13 +82,16 @@ const ApproveSignUpRequestsScreen = () => {
}
};

const deleteRequest = async ({ id }) => {
const deleteRequest = async (id) => {
try {
setLoading(true);
deleteSignupRequest(id);
console.log("Document successfully deleted!");
} catch (error) {
console.error("Error removing document: ", error);
throw error;
} finally {
setLoading(false);
}
};

Expand All @@ -98,7 +101,7 @@ const ApproveSignUpRequestsScreen = () => {
setLoading(true);
request.authId = await handleSignUp(request);
addToStaffs(request, appDefaultLanguage);
deleteRequest(request);
deleteSignupRequest(request.id);
console.log("Approval requests updated");
Alert.alert(successText, requestApprovedSuccessText);
} catch (error) {
Expand All @@ -112,9 +115,17 @@ const ApproveSignUpRequestsScreen = () => {
const renderItem = ({ item }) => (
<View style={styles.requestItem}>
<View style={styles.requestInfo}>
<Text style={styles.requestName}>{item.name}</Text>
<Text style={styles.requestEmail}>{item.email}</Text>
<ThemedText type="subtitle">{item.name}</ThemedText>
<ThemedText type="default">{item.role}</ThemedText>
<ThemedText type="default">{item.email}</ThemedText>
</View>
<ThemedButton
type="danger"
style={(styles.approveGradient, styles.approveButton)}
onPress={() => deleteRequest(item.id)}
>
<Ionicons name="trash-outline" size={24} color="#000" />
</ThemedButton>
<ThemedButton
type="success"
style={(styles.approveGradient, styles.approveButton)}
Expand All @@ -131,7 +142,9 @@ const ApproveSignUpRequestsScreen = () => {

return (
<View style={styles.container}>
<Text style={styles.title}>{approveSignupRequestsText}</Text>
<ThemedText type="title" style={styles.title}>
{approveSignupRequestsText}
</ThemedText>
{requests.length === 0 ? (
<Text style={styles.noRequestsText}>{noPendingSignupRequestsText}</Text>
) : (
Expand All @@ -158,10 +171,6 @@ const styles = StyleSheet.create({
alignItems: "center",
},
title: {
fontSize: 28,
fontWeight: "bold",
color: "#333",
marginBottom: 20,
textAlign: "center",
},
listContainer: {
Expand All @@ -184,16 +193,6 @@ const styles = StyleSheet.create({
requestInfo: {
flex: 1,
},
requestName: {
fontSize: 18,
fontWeight: "600",
color: "#333",
},
requestEmail: {
fontSize: 14,
color: "#666",
marginTop: 4,
},
approveButton: {
marginLeft: 10,
},
Expand Down
Loading

0 comments on commit 2efbef7

Please sign in to comment.