Files
Brandon Cohen 48aa68511b fix: improved web push management (#3421)
refactor: organized placement of new button + added comments

fix: added api routes for push registration

fix: modified get request to confirm key identity

fix: added back notification types to always show

feat: added a manageable device list

refactor: modified device list to make it mobile friendly

fix: correct typo for enabling notifications
2025-10-08 00:03:49 -04:00

108 lines
4.0 KiB
TypeScript

import ConfirmButton from '@app/components/Common/ConfirmButton';
import globalMessages from '@app/i18n/globalMessages';
import {
ComputerDesktopIcon,
DevicePhoneMobileIcon,
TrashIcon,
} from '@heroicons/react/24/solid';
import { defineMessages, useIntl } from 'react-intl';
import { UAParser } from 'ua-parser-js';
interface DeviceItemProps {
disablePushNotifications: (p256dh: string) => void;
device: {
endpoint: string;
p256dh: string;
auth: string;
userAgent: string;
createdAt: Date;
};
}
const messages = defineMessages({
operatingsystem: 'Operating System',
browser: 'Browser',
engine: 'Engine',
deletesubscription: 'Delete Subscription',
});
const DeviceItem = ({ disablePushNotifications, device }: DeviceItemProps) => {
const intl = useIntl();
return (
<div className="relative flex w-full flex-col justify-between overflow-hidden rounded-xl bg-gray-800 py-4 text-gray-400 shadow-md ring-1 ring-gray-700 xl:h-28 xl:flex-row">
<div className="relative flex w-full flex-col justify-between overflow-hidden sm:flex-row">
<div className="relative z-10 flex w-full items-center overflow-hidden pl-4 pr-4 sm:pr-0 xl:w-7/12 2xl:w-2/3">
<div className="relative h-auto w-12 flex-shrink-0 scale-100 transform-gpu overflow-hidden rounded-md transition duration-300 hover:scale-105">
{UAParser(device.userAgent).device.type === 'mobile' ? (
<DevicePhoneMobileIcon />
) : (
<ComputerDesktopIcon />
)}
</div>
<div className="flex flex-col justify-center overflow-hidden pl-2 xl:pl-4">
<div className="pt-0.5 text-xs font-medium text-white sm:pt-1">
{device.createdAt
? intl.formatDate(device.createdAt, {
year: 'numeric',
month: 'long',
day: 'numeric',
})
: 'Unknown'}
</div>
<div className="mr-2 min-w-0 truncate text-lg font-bold text-white hover:underline xl:text-xl">
{device.userAgent
? UAParser(device.userAgent).device.model
: 'Unknown'}
</div>
</div>
</div>
<div className="z-10 mt-4 ml-4 flex w-full flex-col justify-center overflow-hidden pr-4 text-sm sm:ml-2 sm:mt-0 xl:flex-1 xl:pr-0">
<div className="card-field">
<span className="card-field-name">
{intl.formatMessage(messages.operatingsystem)}
</span>
<span className="flex truncate text-sm text-gray-300">
{device.userAgent
? UAParser(device.userAgent).os.name
: 'Unknown'}
</span>
</div>
<div className="card-field">
<span className="card-field-name">
{intl.formatMessage(messages.browser)}
</span>
<span className="flex truncate text-sm text-gray-300">
{device.userAgent
? UAParser(device.userAgent).browser.name
: 'Unknown'}
</span>
</div>
<div className="card-field">
<span className="card-field-name">
{intl.formatMessage(messages.engine)}
</span>
<span className="flex truncate text-sm text-gray-300">
{device.userAgent
? UAParser(device.userAgent).engine.name
: 'Unknown'}
</span>
</div>
</div>
</div>
<div className="z-10 mt-4 flex w-full flex-col justify-center space-y-2 pl-4 pr-4 xl:mt-0 xl:w-96 xl:items-end xl:pl-0">
<ConfirmButton
onClick={() => disablePushNotifications(device.p256dh)}
confirmText={intl.formatMessage(globalMessages.areyousure)}
className="w-full"
>
<TrashIcon />
<span>{intl.formatMessage(messages.deletesubscription)}</span>
</ConfirmButton>
</div>
</div>
);
};
export default DeviceItem;