1
- import { faInfoCircle } from '@fortawesome/free-solid-svg-icons' ;
1
+ import { faCheck , faInfoCircle , faX } from '@fortawesome/free-solid-svg-icons' ;
2
2
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' ;
3
3
import {
4
4
Button ,
@@ -12,28 +12,20 @@ import {
12
12
Typography ,
13
13
} from '@mui/material' ;
14
14
import { FC } from 'react' ;
15
-
16
- /**
17
- * Dummy data for the log in sessions table.
18
- * Can be deleted once table is linked to backend.
19
- */
20
- const sampleSessions = [
21
- {
22
- created : 'Jul 9, 2024 at 9:05am ' ,
23
- expires : '10d 18h 42m ' ,
24
- browser : 'Chrome 125.0.0.0 ' ,
25
- operatingSystem : 'Mac OS X 10.15.7 ' ,
26
- ipAddress : '192.184.174.53' ,
27
- } ,
28
- ] ;
15
+ import { getTokens , revokeToken } from '../../common/api/authService' ;
16
+ import { Loader } from '../../common/components' ;
17
+ import { useAppSelector } from '../../common/hooks' ;
18
+ import { useLogout } from '../login/LogIn' ;
29
19
30
20
/**
31
21
* Content for the Log In Sessions tab in the Account page
32
22
*/
33
23
export const LogInSessions : FC = ( ) => {
34
- const currentSessions = sampleSessions ;
35
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
- const otherSessions : any [ ] = [ ] ;
24
+ const token = useAppSelector ( ( { auth } ) => auth . token ?? '' ) ;
25
+ const tokenSessions = getTokens . useQuery ( token , { skip : ! token } ) ;
26
+
27
+ const currentToken = tokenSessions . data ?. current ;
28
+ const otherTokens = tokenSessions . data ?. tokens ;
37
29
38
30
return (
39
31
< Stack
@@ -43,7 +35,7 @@ export const LogInSessions: FC = () => {
43
35
aria-labelledby = "sessions-tab"
44
36
>
45
37
< Stack direction = "row" justifyContent = "space-between" >
46
- < Typography variant = "h2" > My Current Log In Sessions </ Typography >
38
+ < Typography variant = "h2" > Current Log In Session </ Typography >
47
39
< Tooltip
48
40
title = {
49
41
< Stack spacing = { 1 } >
@@ -74,24 +66,28 @@ export const LogInSessions: FC = () => {
74
66
</ TableRow >
75
67
</ TableHead >
76
68
< TableBody >
77
- { currentSessions . map ( ( session , i ) => (
78
- < TableRow key = { `${ session } -${ i } ` } >
79
- < TableCell > { session . created } </ TableCell >
80
- < TableCell > { session . expires } </ TableCell >
81
- < TableCell > { session . browser } </ TableCell >
82
- < TableCell > { session . operatingSystem } </ TableCell >
83
- < TableCell > { session . ipAddress } </ TableCell >
84
- < TableCell >
85
- < Button variant = "contained" color = "error" >
86
- Log out
87
- </ Button >
88
- </ TableCell >
89
- </ TableRow >
90
- ) ) }
69
+ < TableRow >
70
+ < TableCell >
71
+ { new Date ( currentToken ?. created ?? 0 ) . toLocaleString ( ) }
72
+ </ TableCell >
73
+ < TableCell >
74
+ { new Date ( currentToken ?. expires ?? 0 ) . toLocaleString ( ) }
75
+ </ TableCell >
76
+ < TableCell >
77
+ { currentToken ?. agent } { currentToken ?. agentver }
78
+ </ TableCell >
79
+ < TableCell >
80
+ { currentToken ?. os } { currentToken ?. osver }
81
+ </ TableCell >
82
+ < TableCell > { currentToken ?. ip } </ TableCell >
83
+ < TableCell >
84
+ < LogOutButton tokenId = { currentToken ?. id } />
85
+ </ TableCell >
86
+ </ TableRow >
91
87
</ TableBody >
92
88
</ Table >
93
89
< Typography variant = "h2" > Other Log In Sessions</ Typography >
94
- { otherSessions && otherSessions . length > 0 && (
90
+ { otherTokens && otherTokens . length > 0 && (
95
91
< Table >
96
92
< TableHead >
97
93
< TableRow >
@@ -104,26 +100,62 @@ export const LogInSessions: FC = () => {
104
100
</ TableRow >
105
101
</ TableHead >
106
102
< TableBody >
107
- { otherSessions . map ( ( session , i ) => (
108
- < TableRow key = { `${ session } -${ i } ` } >
109
- < TableCell > { session . created } </ TableCell >
110
- < TableCell > { session . expires } </ TableCell >
111
- < TableCell > { session . browser } </ TableCell >
112
- < TableCell > { session . operatingSystem } </ TableCell >
113
- < TableCell > { session . ipAddress } </ TableCell >
103
+ { otherTokens . map ( ( otherToken , i ) => (
104
+ < TableRow key = { `${ otherToken . id } -${ i } ` } >
105
+ < TableCell >
106
+ { new Date ( otherToken . created ?? 0 ) . toLocaleString ( ) }
107
+ </ TableCell >
108
+ < TableCell >
109
+ { new Date ( otherToken . expires ?? 0 ) . toLocaleString ( ) }
110
+ </ TableCell >
111
+ < TableCell >
112
+ { otherToken . agent } { otherToken . agentver }
113
+ </ TableCell >
114
+ < TableCell >
115
+ { otherToken . os } { otherToken . osver }
116
+ </ TableCell >
117
+ < TableCell > { otherToken . ip } </ TableCell >
114
118
< TableCell >
115
- < Button variant = "contained" color = "error" >
116
- Log out
117
- </ Button >
119
+ < LogOutButton tokenId = { otherToken . id } />
118
120
</ TableCell >
119
121
</ TableRow >
120
122
) ) }
121
123
</ TableBody >
122
124
</ Table >
123
125
) }
124
- { ( ! otherSessions || otherSessions . length === 0 ) && (
126
+ { ( ! otherTokens || otherTokens . length === 0 ) && (
125
127
< i > No additional active log in sessions.</ i >
126
128
) }
127
129
</ Stack >
128
130
) ;
129
131
} ;
132
+
133
+ const LogOutButton = ( { tokenId } : { tokenId ?: string } ) => {
134
+ const logout = useLogout ( ) ;
135
+ const currentTokenId = useAppSelector ( ( { auth } ) => auth . tokenInfo ?. id ) ;
136
+ const [ tirggerRevoke , revoke ] = revokeToken . useMutation ( ) ;
137
+ return (
138
+ < Button
139
+ variant = "contained"
140
+ color = "error"
141
+ onClick = { ( ) => {
142
+ if ( currentTokenId === tokenId ) {
143
+ logout ( ) ;
144
+ } else if ( tokenId ) {
145
+ tirggerRevoke ( tokenId ) ;
146
+ }
147
+ } }
148
+ endIcon = {
149
+ revoke . isLoading ? (
150
+ < Loader loading = { true } type = "spinner" />
151
+ ) : revoke . isSuccess ? (
152
+ < FontAwesomeIcon icon = { faCheck } />
153
+ ) : revoke . isError ? (
154
+ < FontAwesomeIcon icon = { faX } />
155
+ ) : undefined
156
+ }
157
+ >
158
+ Log out
159
+ </ Button >
160
+ ) ;
161
+ } ;
0 commit comments