Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .idea/deploymentTargetSelector.xml

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

26 changes: 18 additions & 8 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
<!-- Permissions -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />


<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Expand Down Expand Up @@ -36,7 +35,7 @@
<!-- Google Maps API Key -->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyBkKnwju9dUU9hK4dWWFaSAogFlth0oDBw" />
android:value="YOUR_GOOGLE_MAPS_API_KEY" />

<!-- Main Activity -->
<activity
Expand All @@ -49,18 +48,30 @@
</intent-filter>
</activity>



<!-- orgwaitinglistActivity-->
<!-- Org Waiting List Activity -->
<activity
android:name=".view.waitinglist.OrgWaitingListActivity"
android:label="Waiting List"
android:exported="true"> <!-- Required for Android 12+ -->
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity android:name=".view.organizer.OrgNotificationsActivity"/>

<!-- Register the NotificationActionReceiver -->
<receiver android:name=".controller.NotificationActionReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.example.vortex_app.ACTION_ACCEPT"/>
<action android:name="com.example.vortex_app.ACTION_DECLINE"/>
<action android:name="com.example.vortex_app.ACTION_STAY"/>
<action android:name="com.example.vortex_app.ACTION_LEAVE"/>
</intent-filter>
</receiver>

<!-- QR Scanner Activities -->
<activity
android:name=".view.qrcode.QrScannerActivity"
Expand Down Expand Up @@ -104,7 +115,6 @@
<!-- Location Activities -->
<activity android:name=".view.location.LocationActivity" android:exported="false" />


<!-- Admin Activities -->
<activity android:name=".view.admin.AdminMainscreen" android:exported="false" />
<activity android:name=".view.admin.AdminFacilityScreen" android:exported="false" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,111 +3,80 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

import com.google.firebase.firestore.FirebaseFirestore;
import com.example.vortex_app.controller.adapter.NotificationActionHandler;

/**
* {@code NotificationActionReceiver} is a {@link BroadcastReceiver} that handles actions
* from notification buttons, such as accepting or declining an invitation, staying on or leaving a waiting list.
* It updates the invitation status in Firestore based on the user's response.
*
* <p>This receiver allows the app to perform actions in response to user interactions with notifications
* without needing to open an activity.
*/
public class NotificationActionReceiver extends BroadcastReceiver {
private FirebaseFirestore db;
// Define unique action strings
public static final String ACTION_ACCEPT = "com.example.vortex_app.ACTION_ACCEPT";
public static final String ACTION_DECLINE = "com.example.vortex_app.ACTION_DECLINE";
public static final String ACTION_STAY = "com.example.vortex_app.ACTION_STAY";
public static final String ACTION_LEAVE = "com.example.vortex_app.ACTION_LEAVE";


/**
* Called when the receiver receives a broadcasted intent. It determines the action taken
* by the user and calls the appropriate method to handle the action.
*
* @param context The {@link Context} in which the receiver is running.
* @param intent The {@link Intent} being received, containing the action and invitation ID.
*/
@Override
public void onReceive(Context context, Intent intent) {
db = FirebaseFirestore.getInstance(); // Initialize Firestore

String action = intent.getAction();
String invitationId = intent.getStringExtra("invitationId"); // Retrieve the invitation ID
String userID = intent.getStringExtra("userID");
String eventID = intent.getStringExtra("eventID");

Log.d("NotificationActionReceiver", "Received action: " + action + ", userID: " + userID + ", eventID: " + eventID);

if (userID == null || eventID == null) {
Log.e("NotificationActionReceiver", "Missing userID or eventID.");
return;
}

NotificationActionHandler handler = new NotificationActionHandler();

switch (action) {
case "ACTION_ACCEPT":
handleAccept(context, invitationId);
case ACTION_ACCEPT:
Log.d("NotificationActionReceiver", "Handling ACTION_ACCEPT");
handler.moveDocument(
"selected_but_not_confirmed",
"final",
userID,
eventID,
context,
"You have been enrolled!",
"Error enrolling in the event."
);
break;
case "ACTION_DECLINE":
handleDecline(context, invitationId);
case ACTION_DECLINE:
Log.d("NotificationActionReceiver", "Handling ACTION_DECLINE");
handler.moveDocument(
"selected_but_not_confirmed",
"waitlisted",
userID,
eventID,
context,
"You have declined the invitation.",
"Error declining the invitation."
);
break;
case "ACTION_STAY":
handleStay(context);
case ACTION_STAY:
Log.d("NotificationActionReceiver", "Handling ACTION_STAY");
Toast.makeText(context, "You remain on the waiting list.", Toast.LENGTH_SHORT).show();
Log.d("NotificationActionReceiver", "User chose to stay on the waiting list.");
break;
case "ACTION_LEAVE":
handleLeave(context, invitationId);
case ACTION_LEAVE:
Log.d("NotificationActionReceiver", "Handling ACTION_LEAVE");
handler.moveDocument(
"waitlisted",
"cancelled",
userID,
eventID,
context,
"You have left the waiting list.",
"Error leaving the waiting list."
);
break;
default:
Log.w("NotificationActionReceiver", "Unknown action received: " + action);
break;
}
}

/**
* Handles the "Accept" action for an invitation. Updates the invitation status in Firestore to "accepted".
*
* @param context The {@link Context} in which the receiver is running.
* @param invitationId The ID of the invitation to be updated.
*/
private void handleAccept(Context context, String invitationId) {
db.collection("invitations").document(invitationId)
.update("status", "accepted")
.addOnSuccessListener(aVoid -> {
Toast.makeText(context, "Invitation Accepted", Toast.LENGTH_SHORT).show();
})
.addOnFailureListener(e -> {
Toast.makeText(context, "Error accepting invitation", Toast.LENGTH_SHORT).show();
});
}

/**
* Handles the "Decline" action for an invitation. Updates the invitation status in Firestore to "declined".
*
* @param context The {@link Context} in which the receiver is running.
* @param invitationId The ID of the invitation to be updated.
*/
private void handleDecline(Context context, String invitationId) {
db.collection("invitations").document(invitationId)
.update("status", "declined")
.addOnSuccessListener(aVoid -> {
Toast.makeText(context, "Invitation Declined", Toast.LENGTH_SHORT).show();
})
.addOnFailureListener(e -> {
Toast.makeText(context, "Error declining invitation", Toast.LENGTH_SHORT).show();
});
}

/**
* Handles the "Stay" action, which keeps the user on the waiting list. No Firestore update is required;
* this method simply shows a confirmation message to the user.
*
* @param context The {@link Context} in which the receiver is running.
*/
private void handleStay(Context context) {
Toast.makeText(context, "You have chosen to stay on the waiting list.", Toast.LENGTH_SHORT).show();
}

/**
* Handles the "Leave" action for a waiting list. Updates the invitation status in Firestore to "left_waitlist".
*
* @param context The {@link Context} in which the receiver is running.
* @param invitationId The ID of the invitation to be updated.
*/
private void handleLeave(Context context, String invitationId) {
db.collection("invitations").document(invitationId)
.update("status", "left_waitlist")
.addOnSuccessListener(aVoid -> {
Toast.makeText(context, "You have left the waiting list", Toast.LENGTH_SHORT).show();
})
.addOnFailureListener(e -> {
Toast.makeText(context, "Error leaving the waiting list", Toast.LENGTH_SHORT).show();
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.example.vortex_app.controller.adapter;


import android.content.Context;
import android.util.Log;
import android.widget.Toast;

import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.WriteBatch;

public class NotificationActionHandler {

private FirebaseFirestore db;

public NotificationActionHandler() {
db = FirebaseFirestore.getInstance();
}

/**
* Moves a document from sourceCollection to targetCollection.
*
* @param sourceCollection The source Firestore collection.
* @param targetCollection The target Firestore collection.
* @param userID The user ID.
* @param eventID The event ID.
* @param context The context to show Toast messages.
* @param successMessage The message to show on success.
* @param failureMessage The message to show on failure.
*/
public void moveDocument(String sourceCollection, String targetCollection, String userID, String eventID, Context context, String successMessage, String failureMessage) {
db.collection(sourceCollection)
.whereEqualTo("userID", userID)
.whereEqualTo("eventID", eventID)
.get()
.addOnSuccessListener(querySnapshot -> {
if (!querySnapshot.isEmpty()) {
DocumentSnapshot doc = querySnapshot.getDocuments().get(0);
DocumentReference sourceRef = doc.getReference();
DocumentReference targetRef = db.collection(targetCollection).document();

WriteBatch batch = db.batch();
batch.set(targetRef, doc.getData());
batch.delete(sourceRef);

batch.commit()
.addOnSuccessListener(aVoid -> {
Toast.makeText(context, successMessage, Toast.LENGTH_SHORT).show();
Log.d("NotificationActionHandler", "User moved to '" + targetCollection + "'.");
})
.addOnFailureListener(e -> {
Toast.makeText(context, failureMessage, Toast.LENGTH_SHORT).show();
Log.e("NotificationActionHandler", "Transaction failed: " + e.getMessage());
});
} else {
Toast.makeText(context, "Document not found.", Toast.LENGTH_SHORT).show();
Log.e("NotificationActionHandler", "Document not found for userID: " + userID + ", eventID: " + eventID);
}
})
.addOnFailureListener(e -> {
Toast.makeText(context, "Error fetching document.", Toast.LENGTH_SHORT).show();
Log.e("NotificationActionHandler", "Error fetching document: ", e);
});
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

package com.example.vortex_app.controller.adapter;

import android.content.Context;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ public class NotificationModel {
private String status;
private String id; // Firestore document ID
private Date TimeStamp;
private String eventID;
private String userID;
private String Type;



/**
* Constructs a {@code NotificationModel} instance with the specified parameters.
Expand All @@ -27,6 +32,17 @@ public class NotificationModel {
* @param id The Firestore document ID associated with the notification.
* @param Timestamp The timestamp indicating when the notification was created or last updated.
*/
public NotificationModel(String title, String message, String status, String id, Date Timestamp, String eventID, String userID, String Type) {
this.title = title;
this.message = message;
this.status = status;
this.id = id;
this.TimeStamp = Timestamp;
this.eventID = eventID;
this.userID = userID;
this.Type = Type;
}

public NotificationModel(String title, String message, String status, String id, Date Timestamp) {
this.title = title;
this.message = message;
Expand All @@ -35,6 +51,7 @@ public NotificationModel(String title, String message, String status, String id,
this.TimeStamp = Timestamp;
}


/**
* Returns the title of the notification.
*
Expand Down Expand Up @@ -71,6 +88,9 @@ public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}
/**
* Returns the timestamp of the notification.
*
Expand All @@ -79,4 +99,17 @@ public String getId() {
public Date getTimeStamp() {
return TimeStamp;
}

public String getEventID() {return eventID;}


public String getUserID() {return userID;}

public String getType() {return Type;}

public void SetType(String type) {this.Type = Type;}

}



Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.vortex_app.view.notification;



import com.example.vortex_app.model.NotificationModel;

public interface NotificationClickListener {
void onNotificationClick(NotificationModel notification);
}
Loading