website refactor
This commit is contained in:
@@ -12,9 +12,8 @@ import {
|
||||
Vote
|
||||
} from 'lucide-react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
|
||||
const notificationIcons: Record<string, typeof Bell> = {
|
||||
@@ -92,9 +91,9 @@ export function NotificationCenter({ onNavigate }: NotificationCenterProps) {
|
||||
};
|
||||
|
||||
return (
|
||||
<Box position="relative" ref={panelRef}>
|
||||
<Stack position="relative" ref={panelRef}>
|
||||
{/* Bell button */}
|
||||
<Box
|
||||
<Stack
|
||||
as="button"
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
p={2}
|
||||
@@ -108,7 +107,7 @@ export function NotificationCenter({ onNavigate }: NotificationCenterProps) {
|
||||
>
|
||||
<Icon icon={Bell} size={5} />
|
||||
{unreadCount > 0 && (
|
||||
<Box
|
||||
<Stack
|
||||
position="absolute"
|
||||
top="-0.5"
|
||||
right="-0.5"
|
||||
@@ -125,13 +124,13 @@ export function NotificationCenter({ onNavigate }: NotificationCenterProps) {
|
||||
style={{ fontSize: '10px', fontWeight: 'bold' }}
|
||||
>
|
||||
{unreadCount > 99 ? '99+' : unreadCount}
|
||||
</Box>
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
{/* Notification panel */}
|
||||
{isOpen && (
|
||||
<Box
|
||||
<Stack
|
||||
position="absolute"
|
||||
right="0"
|
||||
top="full"
|
||||
@@ -146,20 +145,20 @@ export function NotificationCenter({ onNavigate }: NotificationCenterProps) {
|
||||
zIndex={50}
|
||||
>
|
||||
{/* Header */}
|
||||
<Box display="flex" alignItems="center" justifyContent="between" px={4} py={3} borderBottom borderColor="border-charcoal-outline">
|
||||
<Box display="flex" alignItems="center" gap={2}>
|
||||
<Stack display="flex" alignItems="center" justifyContent="between" px={4} py={3} borderBottom borderColor="border-charcoal-outline">
|
||||
<Stack display="flex" alignItems="center" gap={2}>
|
||||
<Icon icon={Bell} size={4} color="text-primary-blue" />
|
||||
<Text weight="semibold" color="text-white">Notifications</Text>
|
||||
{unreadCount > 0 && (
|
||||
<Box px={2} py={0.5} bg="bg-red-500/20" rounded="full">
|
||||
<Stack px={2} py={0.5} bg="bg-red-500/20" rounded="full">
|
||||
<Text size="xs" weight="medium" color="text-red-400">
|
||||
{unreadCount} new
|
||||
</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
</Stack>
|
||||
{unreadCount > 0 && (
|
||||
<Box
|
||||
<Stack
|
||||
as="button"
|
||||
onClick={markAllAsRead}
|
||||
display="flex"
|
||||
@@ -171,22 +170,22 @@ export function NotificationCenter({ onNavigate }: NotificationCenterProps) {
|
||||
>
|
||||
<Icon icon={CheckCheck} size={3.5} color="text-gray-400" />
|
||||
<Text size="xs" color="text-gray-400">Mark all read</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
{/* Notifications list */}
|
||||
<Box maxHeight="400px" overflow="auto">
|
||||
<Stack maxHeight="400px" overflow="auto">
|
||||
{notifications.length === 0 ? (
|
||||
<Box py={12} textAlign="center">
|
||||
<Box w="12" h="12" mx="auto" mb={3} rounded="full" bg="bg-iron-gray/50" display="flex" alignItems="center" justifyContent="center">
|
||||
<Stack py={12} textAlign="center">
|
||||
<Stack w="12" h="12" mx="auto" mb={3} rounded="full" bg="bg-iron-gray/50" display="flex" alignItems="center" justifyContent="center">
|
||||
<Icon icon={Bell} size={6} color="text-gray-500" />
|
||||
</Box>
|
||||
</Stack>
|
||||
<Text size="sm" color="text-gray-400" block>No notifications yet</Text>
|
||||
<Text size="xs" color="text-gray-500" block mt={1}>
|
||||
You'll be notified about protests, races, and more
|
||||
</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
) : (
|
||||
<Stack gap={0}
|
||||
// eslint-disable-next-line gridpilot-rules/component-classification
|
||||
@@ -197,7 +196,7 @@ export function NotificationCenter({ onNavigate }: NotificationCenterProps) {
|
||||
const colorClass = notificationColors[notification.type] || 'text-gray-400 bg-gray-400/10';
|
||||
|
||||
return (
|
||||
<Box
|
||||
<Stack
|
||||
key={notification.id}
|
||||
as="button"
|
||||
onClick={() => handleNotificationClick(notification)}
|
||||
@@ -209,26 +208,26 @@ export function NotificationCenter({ onNavigate }: NotificationCenterProps) {
|
||||
hoverBg="bg-iron-gray/30"
|
||||
bg={!notification.read ? 'bg-primary-blue/5' : undefined}
|
||||
>
|
||||
<Box display="flex" gap={3}>
|
||||
<Box p={2} rounded="lg" flexShrink={0}
|
||||
<Stack display="flex" gap={3}>
|
||||
<Stack p={2} rounded="lg" flexShrink={0}
|
||||
// eslint-disable-next-line gridpilot-rules/component-classification
|
||||
className={colorClass}
|
||||
>
|
||||
<Icon icon={NotificationIcon} size={4} />
|
||||
</Box>
|
||||
<Box flexGrow={1} minWidth="0">
|
||||
<Box display="flex" alignItems="start" justifyContent="between" gap={2}>
|
||||
</Stack>
|
||||
<Stack flexGrow={1} minWidth="0">
|
||||
<Stack display="flex" alignItems="start" justifyContent="between" gap={2}>
|
||||
<Text size="sm" weight="medium" truncate color={!notification.read ? 'text-white' : 'text-gray-300'} block>
|
||||
{notification.title}
|
||||
</Text>
|
||||
{!notification.read && (
|
||||
<Box w="2" h="2" bg="bg-primary-blue" rounded="full" flexShrink={0} mt={1.5} />
|
||||
<Stack w="2" h="2" bg="bg-primary-blue" rounded="full" flexShrink={0} mt={1.5} />
|
||||
)}
|
||||
</Box>
|
||||
</Stack>
|
||||
<Text size="xs" color="text-gray-500" lineClamp={2} mt={0.5} block>
|
||||
{notification.message}
|
||||
</Text>
|
||||
<Box display="flex" alignItems="center" gap={2} mt={1.5}>
|
||||
<Stack display="flex" alignItems="center" gap={2} mt={1.5}>
|
||||
<Text color="text-gray-600"
|
||||
// eslint-disable-next-line gridpilot-rules/component-classification
|
||||
style={{ fontSize: '10px' }}
|
||||
@@ -236,7 +235,7 @@ export function NotificationCenter({ onNavigate }: NotificationCenterProps) {
|
||||
{formatTime(notification.createdAt)}
|
||||
</Text>
|
||||
{notification.actionUrl && (
|
||||
<Box display="flex" alignItems="center" gap={0.5}>
|
||||
<Stack display="flex" alignItems="center" gap={0.5}>
|
||||
<Icon icon={ExternalLink} size={2.5} color="text-primary-blue" />
|
||||
<Text color="text-primary-blue"
|
||||
// eslint-disable-next-line gridpilot-rules/component-classification
|
||||
@@ -244,31 +243,31 @@ export function NotificationCenter({ onNavigate }: NotificationCenterProps) {
|
||||
>
|
||||
View
|
||||
</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
{/* Footer */}
|
||||
{notifications.length > 0 && (
|
||||
<Box px={4} py={2} borderTop borderColor="border-charcoal-outline" bg="bg-iron-gray/20">
|
||||
<Stack px={4} py={2} borderTop borderColor="border-charcoal-outline" bg="bg-iron-gray/20">
|
||||
<Text color="text-gray-500" textAlign="center" block
|
||||
// eslint-disable-next-line gridpilot-rules/component-classification
|
||||
style={{ fontSize: '10px' }}
|
||||
>
|
||||
Showing {notifications.length} notification{notifications.length !== 1 ? 's' : ''}
|
||||
</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import { v4 as uuid } from 'uuid';
|
||||
import { ModalNotification } from './ModalNotification';
|
||||
import { ToastNotification } from './ToastNotification';
|
||||
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
|
||||
import type { Notification, NotificationAction, NotificationVariant } from './notificationTypes';
|
||||
@@ -136,7 +135,7 @@ export function NotificationProvider({ children }: NotificationProviderProps) {
|
||||
{children}
|
||||
|
||||
{/* Toast notifications container */}
|
||||
<Box position="fixed" top="20" right="4" zIndex={50}>
|
||||
<Stack position="fixed" top="20" right="4" zIndex={50}>
|
||||
<Stack gap={3}>
|
||||
{toastNotifications.map((notification) => (
|
||||
<ToastNotification
|
||||
@@ -147,7 +146,7 @@ export function NotificationProvider({ children }: NotificationProviderProps) {
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
{/* Modal notification */}
|
||||
{modalNotification && (
|
||||
|
||||
Reference in New Issue
Block a user