diff --git a/.github/workflows/cd-develop.yml b/.github/workflows/cd-develop.yml index 44e7d3f1..f1bafbda 100644 --- a/.github/workflows/cd-develop.yml +++ b/.github/workflows/cd-develop.yml @@ -189,7 +189,7 @@ jobs: run: | curl -H "Content-Type: application/json" \ -X POST \ - -d "{\"content\": \"✅ EC2 배포 성공! (브랜치: main)\"}" \ + -d "{\"content\": \"✅ EC2 배포 성공!\"}" \ ${{ secrets.DISCORD_WEBHOOK_URL }} # ❌ 배포 실패 알림 (Discord) diff --git a/src/main/java/com/wayble/server/ServerApplication.java b/src/main/java/com/wayble/server/ServerApplication.java index 46a78de8..9f0a50f6 100644 --- a/src/main/java/com/wayble/server/ServerApplication.java +++ b/src/main/java/com/wayble/server/ServerApplication.java @@ -15,7 +15,7 @@ ) @EnableJpaAuditing @EnableScheduling -@EnableElasticsearchRepositories(basePackages = "com.wayble.server.explore.repository") +@EnableElasticsearchRepositories(basePackages = {"com.wayble.server.explore.repository", "com.wayble.server.logging.repository"}) @EnableConfigurationProperties(TMapProperties.class) @EntityScan(basePackages = "com.wayble.server") public class ServerApplication { diff --git a/src/main/java/com/wayble/server/admin/controller/AdminController.java b/src/main/java/com/wayble/server/admin/controller/AdminController.java index 0548850f..1e6bd28c 100644 --- a/src/main/java/com/wayble/server/admin/controller/AdminController.java +++ b/src/main/java/com/wayble/server/admin/controller/AdminController.java @@ -1,9 +1,11 @@ package com.wayble.server.admin.controller; +import com.wayble.server.admin.dto.DailyStatsDto; import com.wayble.server.admin.dto.SystemStatusDto; import com.wayble.server.admin.service.AdminSystemService; import com.wayble.server.admin.service.AdminUserService; import com.wayble.server.admin.service.AdminWaybleZoneService; +import com.wayble.server.common.response.CommonResponse; import jakarta.servlet.http.HttpSession; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -14,6 +16,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; @Slf4j @Controller @@ -74,13 +77,17 @@ public String adminDashboard(HttpSession session, Model model) { adminSystemService.isFileStorageHealthy() ); - // 통계 데이터 조회 + // 일일 통계 데이터 조회 + DailyStatsDto dailyStats = adminSystemService.getDailyStats(); + + // 기존 통계 데이터 조회 (원래대로 복구) long totalUserCount = adminUserService.getTotalUserCount(); long totalDeletedUserCount = adminUserService.getTotalDeletedUserCount(); long totalWaybleZoneCount = adminWaybleZoneService.getTotalWaybleZoneCounts(); model.addAttribute("adminUsername", session.getAttribute("adminUsername")); model.addAttribute("systemStatus", systemStatus); + model.addAttribute("dailyStats", dailyStats); model.addAttribute("totalUserCount", totalUserCount); model.addAttribute("totalDeletedUserCount", totalDeletedUserCount); model.addAttribute("totalWaybleZoneCount", totalWaybleZoneCount); @@ -93,4 +100,16 @@ public String adminLogout(HttpSession session) { log.info("관리자 로그아웃"); return "redirect:/admin"; } + + @GetMapping("/api/daily-stats") + @ResponseBody + public CommonResponse getDailyStats(HttpSession session) { + // 로그인 확인 (API용) + if (session.getAttribute("adminLoggedIn") == null) { + return CommonResponse.error(401, "관리자 인증이 필요합니다."); + } + + DailyStatsDto dailyStats = adminSystemService.getDailyStats(); + return CommonResponse.success(dailyStats); + } } \ No newline at end of file diff --git a/src/main/java/com/wayble/server/admin/dto/DailyStatsDto.java b/src/main/java/com/wayble/server/admin/dto/DailyStatsDto.java new file mode 100644 index 00000000..10b22164 --- /dev/null +++ b/src/main/java/com/wayble/server/admin/dto/DailyStatsDto.java @@ -0,0 +1,15 @@ +package com.wayble.server.admin.dto; + +import lombok.Builder; + +import java.time.LocalDate; + +@Builder +public record DailyStatsDto( + LocalDate date, + long dailyRegistrationCount, + long dailyActiveUserCount, + long totalUserCount, + long totalWaybleZoneCount +) { +} \ No newline at end of file diff --git a/src/main/java/com/wayble/server/admin/service/AdminSystemService.java b/src/main/java/com/wayble/server/admin/service/AdminSystemService.java index 5d7bee4b..75c6961d 100644 --- a/src/main/java/com/wayble/server/admin/service/AdminSystemService.java +++ b/src/main/java/com/wayble/server/admin/service/AdminSystemService.java @@ -2,12 +2,15 @@ import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch.cluster.HealthResponse; +import com.wayble.server.admin.dto.DailyStatsDto; +import com.wayble.server.logging.service.UserActionLogService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.sql.DataSource; import java.sql.Connection; +import java.time.LocalDate; @Slf4j @Service @@ -16,6 +19,9 @@ public class AdminSystemService { private final ElasticsearchClient elasticsearchClient; private final DataSource dataSource; + private final UserActionLogService userActionLogService; + private final AdminUserService adminUserService; + private final AdminWaybleZoneService adminWaybleZoneService; public boolean isElasticsearchHealthy() { try { @@ -46,4 +52,42 @@ public boolean isFileStorageHealthy() { // 파일 스토리지 상태 체크 (예: S3 연결 확인 등) return true; } + + public DailyStatsDto getDailyStats() { + try { + LocalDate today = LocalDate.now(); + + // 일일 가입자 수 + long dailyRegistrationCount = userActionLogService.getTodayUserRegistrationCount(); + + // 일일 활성 유저 수 (방문자) + long dailyActiveUserCount = userActionLogService.getTodayActiveUserCount(); + + // 전체 유저 수 + long totalUserCount = adminUserService.getTotalUserCount(); + + // 전체 웨이블존 수 + long totalWaybleZoneCount = adminWaybleZoneService.getTotalWaybleZoneCounts(); + + return DailyStatsDto.builder() + .date(today) + .dailyRegistrationCount(dailyRegistrationCount) + .dailyActiveUserCount(dailyActiveUserCount) + .totalUserCount(totalUserCount) + .totalWaybleZoneCount(totalWaybleZoneCount) + .build(); + + } catch (Exception e) { + log.error("Failed to get daily stats", e); + + // 에러 발생시 기본값 반환 + return DailyStatsDto.builder() + .date(LocalDate.now()) + .dailyRegistrationCount(0) + .dailyActiveUserCount(0) + .totalUserCount(0) + .totalWaybleZoneCount(0) + .build(); + } + } } \ No newline at end of file diff --git a/src/main/java/com/wayble/server/admin/service/AdminUserService.java b/src/main/java/com/wayble/server/admin/service/AdminUserService.java index 1c79ee71..8de4b416 100644 --- a/src/main/java/com/wayble/server/admin/service/AdminUserService.java +++ b/src/main/java/com/wayble/server/admin/service/AdminUserService.java @@ -165,8 +165,8 @@ private AdminUserThumbnailDto convertToThumbnailDto(Object[] row) { String email = (String) row[2]; LocalDate birthDate = row[3] != null ? ((Date) row[3]).toLocalDate() : null; Gender gender = row[4] != null ? Gender.valueOf((String) row[4]) : null; - LoginType loginType = LoginType.valueOf((String) row[5]); - UserType userType = UserType.valueOf((String) row[6]); + LoginType loginType = row[5] != null ? LoginType.valueOf((String) row[5]) : null; + UserType userType = row[6] != null ? UserType.valueOf((String) row[6]) : null; String disabilityType = (String) row[7]; String mobilityAid = (String) row[8]; @@ -181,8 +181,8 @@ private AdminUserDetailDto convertToDetailDto(Object[] row, long reviewCount, lo String email = (String) row[3]; LocalDate birthDate = row[4] != null ? ((Date) row[4]).toLocalDate() : null; Gender gender = row[5] != null ? Gender.valueOf((String) row[5]) : null; - LoginType loginType = LoginType.valueOf((String) row[6]); - UserType userType = UserType.valueOf((String) row[7]); + LoginType loginType = row[6] != null ? LoginType.valueOf((String) row[6]) : null; + UserType userType = row[7] != null ? UserType.valueOf((String) row[7]) : null; String profileImageUrl = (String) row[8]; String disabilityType = (String) row[9]; String mobilityAid = (String) row[10]; @@ -203,8 +203,8 @@ private AdminUserDetailDto convertToDetailDtoWithStats(Object[] row, long review String email = (String) row[3]; LocalDate birthDate = row[4] != null ? ((Date) row[4]).toLocalDate() : null; Gender gender = row[5] != null ? Gender.valueOf((String) row[5]) : null; - LoginType loginType = LoginType.valueOf((String) row[6]); - UserType userType = UserType.valueOf((String) row[7]); + LoginType loginType = row[6] != null ? LoginType.valueOf((String) row[6]) : null; + UserType userType = row[7] != null ? UserType.valueOf((String) row[7]) : null; String profileImageUrl = (String) row[8]; String disabilityType = (String) row[9]; String mobilityAid = (String) row[10]; diff --git a/src/main/java/com/wayble/server/auth/service/AuthService.java b/src/main/java/com/wayble/server/auth/service/AuthService.java index a8143ab5..1e9cab95 100644 --- a/src/main/java/com/wayble/server/auth/service/AuthService.java +++ b/src/main/java/com/wayble/server/auth/service/AuthService.java @@ -2,6 +2,7 @@ import com.wayble.server.common.config.security.jwt.JwtTokenProvider; import com.wayble.server.common.exception.ApplicationException; +import com.wayble.server.logging.service.UserActionLogService; import com.wayble.server.user.dto.UserLoginRequestDto; import com.wayble.server.auth.dto.TokenResponseDto; import com.wayble.server.auth.entity.RefreshToken; @@ -22,6 +23,7 @@ public class AuthService { private final RefreshTokenRepository refreshTokenRepository; private final PasswordEncoder encoder; private final JwtTokenProvider jwtProvider; + private final UserActionLogService userActionLogService; public TokenResponseDto login(UserLoginRequestDto req) { User user = userRepository.findByEmailAndLoginType(req.email(), req.loginType()) @@ -42,6 +44,12 @@ public TokenResponseDto login(UserLoginRequestDto req) { .build(); refreshTokenRepository.save(entity); + // 첫 로그인시에도 활성 유저 로그 저장 (비동기, 하루 1회만) + userActionLogService.logTokenRefresh( + user.getId(), + user.getUserType() != null ? user.getUserType().name() : null + ); + return new TokenResponseDto(accessToken, refreshToken); } @@ -73,6 +81,13 @@ public TokenResponseDto reissue(String refreshToken) { refreshTokenRepository.save(saved); String newAccessToken = jwtProvider.generateToken(userId, user.getUserType() != null ? user.getUserType().name() : null); + + // 토큰 갱신 로그 저장 (비동기, 하루 1회만) + userActionLogService.logTokenRefresh( + userId, + user.getUserType() != null ? user.getUserType().name() : null + ); + return new TokenResponseDto(newAccessToken, newRefreshToken); } diff --git a/src/main/java/com/wayble/server/auth/service/KakaoLoginService.java b/src/main/java/com/wayble/server/auth/service/KakaoLoginService.java index 4d032a7c..8a3620c7 100644 --- a/src/main/java/com/wayble/server/auth/service/KakaoLoginService.java +++ b/src/main/java/com/wayble/server/auth/service/KakaoLoginService.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.wayble.server.common.config.security.jwt.JwtTokenProvider; import com.wayble.server.common.exception.ApplicationException; +import com.wayble.server.logging.service.UserActionLogService; import com.wayble.server.user.dto.KakaoLoginRequestDto; import com.wayble.server.user.dto.KakaoLoginResponseDto; import com.wayble.server.user.dto.KakaoUserInfoDto; @@ -26,6 +27,7 @@ public class KakaoLoginService { private final JwtTokenProvider jwtProvider; private final ObjectMapper objectMapper; private final WebClient webClient; + private final UserActionLogService userActionLogService; private static final String KAKAO_USERINFO_URL = "https://kapi.kakao.com/v2/user/me"; @@ -66,6 +68,21 @@ public KakaoLoginResponseDto kakaoLogin(KakaoLoginRequestDto request) { ); String refreshToken = jwtProvider.generateRefreshToken(user.getId()); + // 로그 저장 (비동기) + if (isNewUser) { + // 신규 가입 로그 + userActionLogService.logUserRegister( + user.getId(), + LoginType.KAKAO.name(), + user.getUserType() != null ? user.getUserType().name() : null + ); + } + + // 모든 카카오 로그인시 활성 유저 로그 저장 (하루 1회만) + userActionLogService.logTokenRefresh( + user.getId(), + user.getUserType() != null ? user.getUserType().name() : null + ); return KakaoLoginResponseDto.builder() .accessToken(accessToken) diff --git a/src/main/java/com/wayble/server/logging/config/LoggingAsyncConfig.java b/src/main/java/com/wayble/server/logging/config/LoggingAsyncConfig.java new file mode 100644 index 00000000..4f195ee9 --- /dev/null +++ b/src/main/java/com/wayble/server/logging/config/LoggingAsyncConfig.java @@ -0,0 +1,26 @@ +package com.wayble.server.logging.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; + +@Configuration +@EnableAsync +public class LoggingAsyncConfig { + + @Bean("loggingTaskExecutor") + public Executor loggingTaskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(2); + executor.setMaxPoolSize(4); + executor.setQueueCapacity(100); + executor.setThreadNamePrefix("logging-"); + executor.setWaitForTasksToCompleteOnShutdown(true); + executor.setAwaitTerminationSeconds(30); + executor.initialize(); + return executor; + } +} \ No newline at end of file diff --git a/src/main/java/com/wayble/server/logging/entity/UserActionLog.java b/src/main/java/com/wayble/server/logging/entity/UserActionLog.java new file mode 100644 index 00000000..a4a1305e --- /dev/null +++ b/src/main/java/com/wayble/server/logging/entity/UserActionLog.java @@ -0,0 +1,46 @@ +package com.wayble.server.logging.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; + +import java.time.LocalDateTime; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Document(indexName = "user_action_logs") +public class UserActionLog { + + @Id + private String id; + + @Field(type = FieldType.Long) + private Long userId; + + @Field(type = FieldType.Keyword) + private String action; + + @Field(type = FieldType.Text) + private String userAgent; + + @Field(type = FieldType.Date) + private LocalDateTime timestamp; + + @Field(type = FieldType.Keyword) + private String loginType; + + @Field(type = FieldType.Keyword) + private String userType; + + public enum ActionType { + USER_REGISTER, + USER_TOKEN_REFRESH + } +} \ No newline at end of file diff --git a/src/main/java/com/wayble/server/logging/repository/UserActionLogRepository.java b/src/main/java/com/wayble/server/logging/repository/UserActionLogRepository.java new file mode 100644 index 00000000..8845d793 --- /dev/null +++ b/src/main/java/com/wayble/server/logging/repository/UserActionLogRepository.java @@ -0,0 +1,22 @@ +package com.wayble.server.logging.repository; + +import com.wayble.server.logging.entity.UserActionLog; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; +import org.springframework.stereotype.Repository; + +import java.time.LocalDateTime; +import java.util.List; + +@Repository +public interface UserActionLogRepository extends ElasticsearchRepository { + + List findByActionAndTimestampBetween(String action, LocalDateTime start, LocalDateTime end); + + List findByUserIdAndActionAndTimestampBetween(Long userId, String action, LocalDateTime start, LocalDateTime end); + + long countByActionAndTimestampBetween(String action, LocalDateTime start, LocalDateTime end); + + long countByUserIdAndActionAndTimestampBetween(Long userId, String action, LocalDateTime start, LocalDateTime end); + + long countDistinctUserIdByActionAndTimestampBetween(String action, LocalDateTime start, LocalDateTime end); +} \ No newline at end of file diff --git a/src/main/java/com/wayble/server/logging/service/UserActionLogService.java b/src/main/java/com/wayble/server/logging/service/UserActionLogService.java new file mode 100644 index 00000000..d2de609a --- /dev/null +++ b/src/main/java/com/wayble/server/logging/service/UserActionLogService.java @@ -0,0 +1,105 @@ +package com.wayble.server.logging.service; + +import com.wayble.server.logging.entity.UserActionLog; +import com.wayble.server.logging.repository.UserActionLogRepository; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.time.LocalDateTime; +import java.util.concurrent.CompletableFuture; + +@Slf4j +@Service +@RequiredArgsConstructor +public class UserActionLogService { + + private final UserActionLogRepository userActionLogRepository; + + @Async("loggingTaskExecutor") + public CompletableFuture logUserRegister(Long userId, String loginType, String userType) { + try { + HttpServletRequest request = getCurrentRequest(); + + UserActionLog userActionLog = UserActionLog.builder() + .userId(userId) + .action(UserActionLog.ActionType.USER_REGISTER.name()) + .userAgent(request != null ? request.getHeader("User-Agent") : null) + .timestamp(LocalDateTime.now()) + .loginType(loginType) + .userType(userType) + .build(); + + userActionLogRepository.save(userActionLog); + log.info("User register log saved: userId={}, loginType={}, userType={}", userId, loginType, userType); + } catch (Exception e) { + log.error("Failed to save user register log: userId={}", userId, e); + } + return CompletableFuture.completedFuture(null); + } + + + public long getTodayUserRegistrationCount() { + LocalDateTime startOfDay = LocalDateTime.now().toLocalDate().atStartOfDay(); + LocalDateTime endOfDay = startOfDay.plusDays(1); + + return userActionLogRepository.countByActionAndTimestampBetween( + UserActionLog.ActionType.USER_REGISTER.name(), startOfDay, endOfDay); + } + + @Async("loggingTaskExecutor") + public CompletableFuture logTokenRefresh(Long userId, String userType) { + try { + HttpServletRequest request = getCurrentRequest(); + + // 하루에 한 번만 로그 저장하도록 체크 + LocalDateTime startOfDay = LocalDateTime.now().toLocalDate().atStartOfDay(); + LocalDateTime endOfDay = startOfDay.plusDays(1); + + long existingCount = userActionLogRepository.countByUserIdAndActionAndTimestampBetween( + userId, UserActionLog.ActionType.USER_TOKEN_REFRESH.name(), startOfDay, endOfDay); + + if (existingCount == 0) { + UserActionLog userActionLog = UserActionLog.builder() + .userId(userId) + .action(UserActionLog.ActionType.USER_TOKEN_REFRESH.name()) + .userAgent(request != null ? request.getHeader("User-Agent") : null) + .timestamp(LocalDateTime.now()) + .loginType(null) // 토큰 갱신시에는 loginType 불필요 + .userType(userType) + .build(); + + userActionLogRepository.save(userActionLog); + log.info("User token refresh log saved: userId={}, userType={}", userId, userType); + } else { + log.debug("Token refresh already logged today for userId: {}", userId); + } + } catch (Exception e) { + log.error("Failed to save user token refresh log: userId={}", userId, e); + } + return CompletableFuture.completedFuture(null); + } + + public long getTodayActiveUserCount() { + LocalDateTime startOfDay = LocalDateTime.now().toLocalDate().atStartOfDay(); + LocalDateTime endOfDay = startOfDay.plusDays(1); + + return userActionLogRepository.countDistinctUserIdByActionAndTimestampBetween( + UserActionLog.ActionType.USER_TOKEN_REFRESH.name(), startOfDay, endOfDay); + } + + private HttpServletRequest getCurrentRequest() { + try { + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + return attributes != null ? attributes.getRequest() : null; + } catch (Exception e) { + log.debug("Failed to get current request", e); + return null; + } + } + +} \ No newline at end of file diff --git a/src/main/java/com/wayble/server/user/service/UserService.java b/src/main/java/com/wayble/server/user/service/UserService.java index 320985ae..3c3580da 100644 --- a/src/main/java/com/wayble/server/user/service/UserService.java +++ b/src/main/java/com/wayble/server/user/service/UserService.java @@ -1,6 +1,7 @@ package com.wayble.server.user.service; import com.wayble.server.common.exception.ApplicationException; +import com.wayble.server.logging.service.UserActionLogService; import com.wayble.server.user.dto.UserRegisterRequestDto; import com.wayble.server.user.entity.User; import com.wayble.server.user.exception.UserErrorCase; @@ -15,6 +16,7 @@ public class UserService { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; + private final UserActionLogService userActionLogService; // 회원가입 public void signup(UserRegisterRequestDto req) { @@ -26,7 +28,14 @@ public void signup(UserRegisterRequestDto req) { passwordEncoder.encode(req.password()), req.loginType() ); - userRepository.save(user); + User savedUser = userRepository.save(user); + + // 회원가입 로그 저장 (비동기) + userActionLogService.logUserRegister( + savedUser.getId(), + req.loginType().name(), + null + ); } public void makeException() { diff --git a/src/main/resources/templates/admin/dashboard.html b/src/main/resources/templates/admin/dashboard.html index 4acb70af..57302794 100644 --- a/src/main/resources/templates/admin/dashboard.html +++ b/src/main/resources/templates/admin/dashboard.html @@ -58,7 +58,7 @@

대시보드

-
+
@@ -106,7 +106,7 @@

대시보드

-
+
@@ -115,12 +115,34 @@

대시보드

오늘 방문자
-
892명
+
0명
+ + +
+
+
+
+
+ + + +
+
+
+
+
오늘 가입자
+
0명
+
+
+
+
+
+
diff --git a/src/main/resources/templates/admin/user/user-detail.html b/src/main/resources/templates/admin/user/user-detail.html index cc03e71a..56b5ac2a 100644 --- a/src/main/resources/templates/admin/user/user-detail.html +++ b/src/main/resources/templates/admin/user/user-detail.html @@ -67,12 +67,12 @@

+ th:classappend="${user.userType != null and user.userType.name() == 'GENERAL'} ? 'bg-blue-100 text-blue-800' : (${user.userType != null and user.userType.name() == 'DISABLED'} ? 'bg-purple-100 text-purple-800' : 'bg-gray-100 text-gray-800')" + th:text="${user.userType != null ? user.userType.name() : '미설정'}"> + th:classappend="${user.loginType != null and user.loginType.name() == 'WAYBLE'} ? 'bg-gray-100 text-gray-800' : 'bg-yellow-100 text-yellow-800'" + th:text="${user.loginType != null ? user.loginType.name() : '미설정'}">

@@ -113,11 +113,11 @@

기본 정보

로그인 타입
-
+
사용자 타입
-
+
프로필 이미지
diff --git a/src/main/resources/templates/admin/user/users.html b/src/main/resources/templates/admin/user/users.html index ab1a6e9c..c7a1aa6d 100644 --- a/src/main/resources/templates/admin/user/users.html +++ b/src/main/resources/templates/admin/user/users.html @@ -99,12 +99,12 @@

사용자 목록

+ th:classappend="${user.userType != null and user.userType.name() == 'GENERAL'} ? 'bg-blue-100 text-blue-800' : (${user.userType != null and user.userType.name() == 'DISABLED'} ? 'bg-purple-100 text-purple-800' : 'bg-gray-100 text-gray-800')" + th:text="${user.userType != null ? user.userType.name() : '미설정'}"> + th:classappend="${user.loginType != null and user.loginType.name() == 'WAYBLE'} ? 'bg-gray-100 text-gray-800' : 'bg-yellow-100 text-yellow-800'" + th:text="${user.loginType != null ? user.loginType.name() : '미설정'}">
@@ -128,7 +128,7 @@

- +