From d292676b7399396332665039b2a3f6bcba7dbb45 Mon Sep 17 00:00:00 2001
From: Nick Sandstrom <32273437+nick4810@users.noreply.github.com>
Date: Mon, 2 Mar 2026 23:23:01 -0800
Subject: [PATCH] Component cleanup and refactoring
---
.../src/components/M3URefreshNotification.jsx | 24 +---------
.../src/components/NotificationCenter.jsx | 48 +++++++++++--------
frontend/src/components/Sidebar.jsx | 32 ++++++-------
3 files changed, 45 insertions(+), 59 deletions(-)
diff --git a/frontend/src/components/M3URefreshNotification.jsx b/frontend/src/components/M3URefreshNotification.jsx
index af7f9aa5..5b40cadb 100644
--- a/frontend/src/components/M3URefreshNotification.jsx
+++ b/frontend/src/components/M3URefreshNotification.jsx
@@ -48,7 +48,7 @@ export default function M3URefreshNotification() {
const refreshProgress = usePlaylistsStore((s) => s.refreshProgress);
const fetchStreams = useStreamsStore((s) => s.fetchStreams);
const fetchChannelGroups = useChannelsStore((s) => s.fetchChannelGroups);
- const fetchChannelIds = useChannelsStore((s) => s.fetchChannelIds);
+ const fetchChannels = useChannelsStore((s) => s.fetchChannels);
const fetchPlaylists = usePlaylistsStore((s) => s.fetchPlaylists);
const fetchEPGData = useEPGsStore((s) => s.fetchEPGData);
const fetchCategories = useVODStore((s) => s.fetchCategories);
@@ -151,28 +151,6 @@ export default function M3URefreshNotification() {
triggerPostCompletionFetches(data.action);
}
- if (taskProgress == 0) {
- message = `${message} starting...`;
- } else if (taskProgress == 100) {
- message = `${message} complete!`;
-
- // Only trigger additional fetches on successful completion
- if (data.action == 'parsing') {
- fetchStreams();
- API.requeryChannels();
- fetchChannelIds();
- } else if (data.action == 'processing_groups') {
- fetchStreams();
- fetchChannelGroups();
- fetchEPGData();
- fetchPlaylists();
- } else if (data.action == 'vod_refresh') {
- // VOD refresh completed, trigger VOD categories refresh
- fetchPlaylists(); // Refresh playlist data to show updated VOD info
- fetchCategories(); // Refresh VOD categories to make them visible
- }
- }
-
showNotification({
title: `M3U Processing: ${playlist.name}`,
message,
diff --git a/frontend/src/components/NotificationCenter.jsx b/frontend/src/components/NotificationCenter.jsx
index f7da56ad..b6bbdcfb 100644
--- a/frontend/src/components/NotificationCenter.jsx
+++ b/frontend/src/components/NotificationCenter.jsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState, useCallback } from 'react';
+import React, { useCallback, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import {
ActionIcon,
@@ -10,7 +10,9 @@ import {
Group,
Indicator,
Popover,
- ScrollArea,
+ PopoverDropdown,
+ PopoverTarget,
+ ScrollAreaAutosize,
Stack,
Text,
ThemeIcon,
@@ -18,22 +20,26 @@ import {
useMantineTheme,
} from '@mantine/core';
import {
+ AlertTriangle,
+ ArrowRight,
Bell,
Check,
CheckCheck,
Download,
ExternalLink,
- Info,
- Settings,
- AlertTriangle,
- Megaphone,
- X,
Eye,
EyeOff,
- ArrowRight,
+ Info,
+ Megaphone,
+ Settings,
+ X,
} from 'lucide-react';
import useNotificationsStore from '../store/notifications';
-import API from '../api';
+import {
+ dismissAllNotifications,
+ dismissNotification,
+ getNotifications,
+} from '../utils/components/NotificationCenterUtils.js';
// Get icon for notification type
const getNotificationIcon = (type) => {
@@ -139,7 +145,9 @@ const NotificationItem = ({ notification, onDismiss, onAction, onClose }) => {
color="gray"
size="sm"
onClick={handleDismiss}
- style={{ position: 'absolute', top: 8, right: 8 }}
+ pos='absolute'
+ top={8}
+ right={8}
>
@@ -149,7 +157,7 @@ const NotificationItem = ({ notification, onDismiss, onAction, onClose }) => {
{getNotificationIcon(notification.notification_type)}
-
+
{notification.title}
@@ -249,7 +257,7 @@ const NotificationCenter = ({ onSettingAction }) => {
// Fetch notifications on mount and periodically
const fetchNotifications = useCallback(async () => {
try {
- await API.getNotifications(showDismissed);
+ await getNotifications(showDismissed);
} catch (error) {
console.error('Failed to fetch notifications:', error);
}
@@ -265,7 +273,7 @@ const NotificationCenter = ({ onSettingAction }) => {
const handleDismiss = async (notificationId, actionTaken = null) => {
try {
- await API.dismissNotification(notificationId, actionTaken);
+ await dismissNotification(notificationId, actionTaken);
} catch (error) {
console.error('Failed to dismiss notification:', error);
}
@@ -273,7 +281,7 @@ const NotificationCenter = ({ onSettingAction }) => {
const handleDismissAll = async () => {
try {
- await API.dismissAllNotifications();
+ await dismissAllNotifications();
} catch (error) {
console.error('Failed to dismiss all notifications:', error);
}
@@ -302,7 +310,7 @@ const NotificationCenter = ({ onSettingAction }) => {
shadow="lg"
withArrow
>
-
+
{
-
+
-
+
{/* Header */}
@@ -367,7 +375,7 @@ const NotificationCenter = ({ onSettingAction }) => {
{/* Notification list */}
-
+
{displayedNotifications.length === 0 ? (
{
))}
)}
-
+
{/* Footer with info text */}
{!showDismissed &&
@@ -421,7 +429,7 @@ const NotificationCenter = ({ onSettingAction }) => {
>
)}
-
+
);
};
diff --git a/frontend/src/components/Sidebar.jsx b/frontend/src/components/Sidebar.jsx
index a90a8d96..67f721cd 100644
--- a/frontend/src/components/Sidebar.jsx
+++ b/frontend/src/components/Sidebar.jsx
@@ -84,18 +84,16 @@ function NavGroup({ label, icon, paths, location, collapsed }) {
.includes(location.pathname);
return (
-
- setOpen((o) => !o)}
className={`navlink ${parentActive ? 'navlink-parent-active' : ''} ${open ? 'navlink-collapsed' : ''}`}
- style={{ width: '100%' }}
>
{icon}
{!collapsed && (
-
+
-
+
{open ? : }
@@ -117,13 +115,13 @@ function NavGroup({ label, icon, paths, location, collapsed }) {
{open && (
-
+
{paths.map((child) => {
const active = location.pathname === child.path;
return (
{
p="xs"
mih="100vh"
display='flex'
+ br='1px solid #2A2A2E'
style={{
backgroundColor: '#1A1A1E',
- borderRight: '1px solid #2A2A2E',
flexDirection: 'column',
}}
>
@@ -297,9 +295,9 @@ const Sidebar = ({ collapsed, toggleDrawer, drawerWidth, miniDrawerWidth }) => {
{
mt='auto'
p={16}
display='flex'
+ bt='1px solid #2A2A2E'
style={{
alignItems: 'center',
gap: 10,
- borderTop: '1px solid #2A2A2E',
justifyContent: collapsed ? 'center' : 'flex-start',
}}
>
@@ -378,7 +376,8 @@ const Sidebar = ({ collapsed, toggleDrawer, drawerWidth, miniDrawerWidth }) => {
{!collapsed && authUser && (
@@ -404,7 +403,8 @@ const Sidebar = ({ collapsed, toggleDrawer, drawerWidth, miniDrawerWidth }) => {
{!collapsed && (
v{appVersion?.version || '0.0.0'}
@@ -415,9 +415,9 @@ const Sidebar = ({ collapsed, toggleDrawer, drawerWidth, miniDrawerWidth }) => {
)}
{collapsed && isAuthenticated && (