diff --git a/ui/package.json b/ui/package.json index 1e2f6105b..1250f1823 100644 --- a/ui/package.json +++ b/ui/package.json @@ -19,7 +19,7 @@ "@radix-ui/react-icons": "^1.3.0", "@raystack/apsara": "^0.51.0", "@raystack/frontier": "^0.72.4", - "@raystack/proton": "^0.1.0-2dbafa5913a214851fdc4f1beefbe27c4a6de55a", + "@raystack/proton": "^0.1.0-fba39927b8b974dc1cc1ae0f05f1390580ec6d58", "@stitches/react": "^1.2.8", "@tanstack/react-query": "^5.83.0", "@tanstack/react-table": "^8.9.3", diff --git a/ui/src/pages/users/details/security/block-user.tsx b/ui/src/pages/users/details/security/block-user.tsx index 35db0c3e3..27e09079f 100644 --- a/ui/src/pages/users/details/security/block-user.tsx +++ b/ui/src/pages/users/details/security/block-user.tsx @@ -73,7 +73,11 @@ export const BlockUserDialog = () => { + + )) + )} + + + + + ); +}; \ No newline at end of file diff --git a/ui/src/pages/users/details/security/sessions/revoke-session-confirm.tsx b/ui/src/pages/users/details/security/sessions/revoke-session-confirm.tsx new file mode 100644 index 000000000..9b2c078bc --- /dev/null +++ b/ui/src/pages/users/details/security/sessions/revoke-session-confirm.tsx @@ -0,0 +1,104 @@ +import { useState } from 'react'; +import { + Button, + Dialog, + Flex, + List +} from '@raystack/apsara'; +import { RevokeSessionFinalConfirm } from './revoke-session-final-confirm'; +import { formatDeviceDisplay } from './index'; +import styles from './sessions.module.css'; + +interface RevokeSessionConfirmProps { + isOpen: boolean; + onOpenChange: (open: boolean) => void; + sessionInfo?: { + browser: string; + operatingSystem: string; + ipAddress: string; + location: string; + lastActive: string; + }; + onRevokeConfirm: () => void; + isLoading?: boolean; +} + +export const RevokeSessionConfirm = ({ isOpen, onOpenChange, sessionInfo, onRevokeConfirm, isLoading = false }: RevokeSessionConfirmProps) => { + const [isFinalConfirmOpen, setIsFinalConfirmOpen] = useState(false); + + const handleRevoke = () => { + setIsFinalConfirmOpen(true); + }; + + const handleFinalConfirm = () => { + onRevokeConfirm(); + onOpenChange(false); + }; + + return ( + <> + + + + {sessionInfo ? formatDeviceDisplay(sessionInfo.browser, sessionInfo.operatingSystem) : "Unknown browser and OS"} + + + + + + + Device + {sessionInfo ? formatDeviceDisplay(sessionInfo.browser, sessionInfo.operatingSystem) : "Unknown"} + + + IP Address + {sessionInfo?.ipAddress || "Unknown"} + + + Last Location + {sessionInfo?.location || "Unknown"} + + + Last Active + {sessionInfo?.lastActive || "Unknown"} + + + + + + + + + + + + + + + + ); +}; \ No newline at end of file diff --git a/ui/src/pages/users/details/security/sessions/revoke-session-final-confirm.tsx b/ui/src/pages/users/details/security/sessions/revoke-session-final-confirm.tsx new file mode 100644 index 000000000..57162ba9d --- /dev/null +++ b/ui/src/pages/users/details/security/sessions/revoke-session-final-confirm.tsx @@ -0,0 +1,79 @@ +import { + Button, + toast, + Dialog, + Flex, + Text +} from '@raystack/apsara'; +import styles from './sessions.module.css'; + +interface RevokeSessionFinalConfirmProps { + isOpen: boolean; + onOpenChange: (isOpen: boolean) => void; + onConfirm: () => void; + isLoading?: boolean; +} + +export const RevokeSessionFinalConfirm = ({ + isOpen, + onOpenChange, + onConfirm, + isLoading = false +}: RevokeSessionFinalConfirmProps) => { + const handleConfirm = async () => { + try { + onConfirm(); + onOpenChange(false); + } catch (error: any) { + toast.error('Failed to revoke session', { + description: error.message || 'Something went wrong' + }); + } + }; + + return ( + + + + Revoke + + + + + + + Are you sure you want to revoke this session? This action cannot be undone. + + + + + + + + + + + + + ); +}; diff --git a/ui/src/pages/users/details/security/sessions/sessions.module.css b/ui/src/pages/users/details/security/sessions/sessions.module.css new file mode 100644 index 000000000..0f89e2863 --- /dev/null +++ b/ui/src/pages/users/details/security/sessions/sessions.module.css @@ -0,0 +1,48 @@ +.sessionsContainer { + border: 0.9px solid var(--rs-color-border-base-primary); + border-radius: var(--rs-radius-2); + padding-left: var(--rs-space-6); + padding-right: var(--rs-space-6); +} + +.sessionItem { + padding: var(--rs-space-7) 0 var(--rs-space-7) 0; + border-bottom: 0.9px solid var(--rs-color-border-base-primary); +} + +.sessionItem:last-child { + border-bottom: none; +} + +/* Revoke Session Confirm START */ + +.revokeSessionConfirmHeader { + border-bottom: none !important; +} + +.listItem { + border-bottom: 0.9px solid var(--rs-color-border-base-primary); + padding-top: var(--rs-space-5); + padding-bottom: var(--rs-space-5); +} + +.listItem:last-child { + border-bottom: none; +} + +.listRoot { + gap: 0; + padding-bottom: var(--rs-space-5); +} + +.revokeSessionConfirmBody { + padding: 0 var(--rs-space-7); + border-bottom: 0.9px solid var(--rs-color-border-base-primary); +} + +.revokeSessionFinalConfirmBody { + padding: 0 var(--rs-space-7) var(--rs-space-6) var(--rs-space-7); + border-bottom: 0.9px solid var(--rs-color-border-base-primary); +} + +/* Revoke Session Confirm END */ \ No newline at end of file