feat: add last activity date time#57
Conversation
There was a problem hiding this comment.
Pull request overview
Adds tracking of a user's last sign-in timestamp. The backend records lastLogin on the UserEntity (new column via Flyway migration), updates LoginRequest to also carry a client timezone, formats the timestamp into a string in UserResponse/UserResponseWithToken via a new TimeAgoUtil.formatLastSeen, and the frontend stores the value in auth context and renders "Last seen …" in the sidebar footer.
Changes:
- New
lastLogincolumn/field + Flyway migration; populated on successful sign-in. LoginRequestgains atimezonefield (annotated@NotBlank) used to formatlastLoginserver-side.- Frontend types,
AuthProvider, andSidebarupdated to send browser timezone and display the last-seen timestamp.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| server/src/main/resources/db/migration/V202605171000__add_user_last_login.sql | Adds last_login column to users table. |
| server/src/main/java/br/com/tasknoteapp/server/entity/UserEntity.java | New lastLogin field + accessors. |
| server/src/main/java/br/com/tasknoteapp/server/request/LoginRequest.java | Adds required timezone field (@NotBlank) and updates constructor. |
| server/src/main/java/br/com/tasknoteapp/server/util/TimeAgoUtil.java | Adds formatLastSeen using ZoneId; defaults to America/Sao_Paulo. |
| server/src/main/java/br/com/tasknoteapp/server/response/UserResponse.java | Adds lastLogin (String) and timezone parameter to factory. |
| server/src/main/java/br/com/tasknoteapp/server/response/UserResponseWithToken.java | Same as above plus token. |
| server/src/main/java/br/com/tasknoteapp/server/service/AuthService.java | Sets lastLogin on sign-in; threads timezone through response factories (null in several paths). |
| server/src/test/.../AuthServiceTest.java, AuthenticationControllerTest.java, UserControllerTest.java, UserSessionControllerTest.java, UserSessionServiceTest.java | Updated to match new constructor signatures and JSON payloads. |
| client/src/types/UserResponse.ts, SigninResponse.ts | Add lastLogin field. |
| client/src/context/AuthProvider.tsx | Sends browser timezone on sign-in; stores lastLogin on the user. |
| client/src/components/Sidebar/index.tsx | Renders "Last seen {user.lastLogin}" in the footer. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const utcString = user.lastLogin.endsWith('Z') ? user.lastLogin : `${user.lastLogin}Z`; | ||
| const fmtted = new Date(utcString).toLocaleString(navigator.language, { | ||
| timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone, | ||
| day: '2-digit', | ||
| month: '2-digit', | ||
| year: 'numeric', | ||
| hour: '2-digit', | ||
| minute: '2-digit' | ||
| }); | ||
| setLastSeen(fmtted); |
| </small> | ||
| {lastSeen && ( | ||
| <div> | ||
| <small>{`Last seen ${lastSeen}`}</small> |
| private UserEntity cloneUser(UserEntity user, LocalDateTime lastLogin) { | ||
| UserEntity u = new UserEntity(); | ||
| u.setId(user.getId()); | ||
| u.setEmail(user.getEmail()); | ||
| u.setPassword(user.getPassword()); | ||
| u.setAdmin(user.getAdmin()); | ||
| u.setCreatedAt(user.getCreatedAt()); | ||
| u.setInactivatedAt(user.getInactivatedAt()); | ||
| u.setName(user.getName()); | ||
| u.setEmailConfirmedAt(user.getEmailConfirmedAt()); | ||
| u.setEmailUuid(user.getEmailUuid()); | ||
| u.setResetPasswordExpiration(user.getResetPasswordExpiration()); | ||
| u.setResetToken(user.getResetToken()); | ||
| u.setLang(user.getLang()); | ||
| u.setLastPasswordChange(user.getLastPasswordChange()); | ||
| u.setLastLogin(lastLogin); | ||
| return u; | ||
| } |
|
@copilot apply changes based on the comments in this thread |
Agent-Logs-Url: https://github.com/RMCampos/tasknote/sessions/04a13c25-87ea-44cc-ac53-cfefd16e0262 Co-authored-by: RMCampos <2219519+RMCampos@users.noreply.github.com>
Implemented the requested thread updates in commit Screenshot: Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
This pull request adds support for tracking and displaying the user's last login time throughout the application. It introduces a new
lastLoginfield to the user entity, updates the database schema, ensures the backend populates this field on login, and exposes it via API responses. The frontend is updated to display the last login time in the sidebar footer. Below are the key changes:Backend: User Entity, API, and Database
lastLoginfield to theUserEntityclass, including getter and setter methods, and updated the database schema to persist this value (last_logincolumn). [1] [2] [3]lastLoginfield to the current time on successful user sign-in.UserResponseandUserResponseWithTokenrecords to include thelastLoginfield, and updated their factory methods to populate this value. TheUserResponseWithTokenuses a formatted string for display. (Ff158ef4L11R12, [1] [2] [3]lastLoginfield in user response objects. [1] [2] [3] [4] [5] [6] [7] [8]Frontend: Types, Context, and UI
lastLoginto the user-related TypeScript types (UserResponse,SignInResponse) and updated the authentication context to store and provide this value. [1] [2] [3]Sidebarcomponent to display the user's last login time in the footer area.