Notifikasi terhubung ke DB

Add:
- components/Notification/
- hooks/use-notification-store.tsx.back

Fix:
- app.config.js
- app/(application)/(user)/_layout.tsx
- app/(application)/(user)/home.tsx
- app/(application)/(user)/test-notifications.tsx
- app/(application)/_layout.tsx
- app/_layout.tsx
- components/_Icon/IconComponent.tsx
- components/_Icon/IconPlus.tsx
- components/_ShareComponent/NotificationInitializer.tsx
- context/AuthContext.tsx
- hooks/use-notification-store.tsx
- ios/HIPMIBadungConnect/Info.plist
- screens/Home/HeaderBell.tsx
- service/api-device-token.ts
- service/api-notifications.ts

### No Issue
This commit is contained in:
2025-12-19 17:54:49 +08:00
parent a01a9bd93f
commit 1503707eed
16 changed files with 352 additions and 97 deletions

View File

@@ -8,7 +8,14 @@ import { Platform } from "react-native";
import * as Device from "expo-device";
import * as Application from "expo-application";
import { apiDeviceRegisterToken } from "@/service/api-device-token";
import messaging from "@react-native-firebase/messaging";
import messaging, {
isSupported,
requestPermission,
getToken,
AuthorizationStatus,
} from "@react-native-firebase/messaging";
// ✅ Modular imports (sesuai v22+)
export default function NotificationInitializer() {
// Setup handler notifikasi
@@ -24,48 +31,40 @@ export default function NotificationInitializer() {
const registerDeviceToken = async () => {
try {
// 1. Minta izin & ambil FCM token
if (!messaging().isSupported()) return;
const authStatus = await messaging().requestPermission();
if (authStatus === messaging.AuthorizationStatus.AUTHORIZED) {
const token = await messaging().getToken();
console.log("✅ FCM Token:", token);
if (!token) {
logout();
return;
}
} else {
console.warn("Izin notifikasi ditolak");
// ✅ Dapatkan instance messaging
const messagingInstance = messaging();
// ✅ Gunakan instance sebagai argumen
const supported = await isSupported(messagingInstance);
if (!supported) {
console.log("‼️ FCM tidak didukung");
return;
}
const fcmToken = await messaging().getToken();
if (!fcmToken) {
console.warn("Gagal mendapatkan FCM token");
};
const authStatus = await requestPermission(messagingInstance);
if (authStatus !== AuthorizationStatus.AUTHORIZED) {
console.warn("Izin telah ditolak");
return;
}
// 2. Ambil info device
const fcmToken = await getToken(messagingInstance);
if (!fcmToken) {
logout();
return;
}
console.log("✅ FCM Token:", fcmToken);
const platform = Platform.OS; // "ios" | "android"
const model = Device.modelName || "unknown";
const appVersion = (Application.nativeApplicationVersion || "unknown") + "-" + (Application.nativeBuildVersion || "unknown");
const deviceId = Device.osInternalBuildId || Device.modelName + "-" + Date.now();
const appVersion =
(Application.nativeApplicationVersion || "unknown") +
"-" +
(Application.nativeBuildVersion || "unknown");
const deviceId =
Device.osInternalBuildId || Device.modelName + "-" + Date.now();
// console.log(
// "📱 Device info:",
// JSON.stringify(
// {
// fcmToken,
// platform,
// deviceId,
// model,
// appVersion,
// },
// null,
// 2
// )
// );
// 3. Kirim ke backend
// Kirim ke backend
await apiDeviceRegisterToken({
data: {
fcmToken,
@@ -102,7 +101,7 @@ export default function NotificationInitializer() {
}
console.log("📥 Menambahkan ke store:", { title, body, safeData });
addNotification({ title, body, data: safeData });
addNotification({ title, body, data: safeData , type: "notification", });
console.log("✅ Notifikasi ditambahkan ke state");
};

View File

@@ -98,13 +98,14 @@ export const IconView = ({
);
};
export const IconDot = ({ size, color }: { size?: number; color?: string }) => {
export const IconDot = ({ size, color, onPress }: { size?: number; color?: string , onPress?: () => void}) => {
return (
<>
<Ionicons
name="ellipsis-vertical"
size={size || ICON_SIZE_MEDIUM}
color={color || MainColor.darkblue}
onPress={onPress}
/>
</>
);

View File

@@ -4,12 +4,21 @@ import { Octicons } from "@expo/vector-icons";
export { IconPlus };
function IconPlus({ color, size }: { color?: string; size?: number }) {
function IconPlus({
color,
size,
onPress,
}: {
color?: string;
size?: number;
onPress?: () => void;
}) {
return (
<Octicons
name="plus-circle"
size={size || ICON_SIZE_MEDIUM}
color={color || MainColor.white}
onPress={onPress}
/>
);
}