Fix local dev config and ALOTTTT OFF FLUTTER, im tired boss..

This commit is contained in:
Wowieee4
2026-05-26 21:09:13 +07:00
parent b8ad8df993
commit a629357e8c
72 changed files with 2566 additions and 530 deletions
@@ -98,6 +98,13 @@ public class GuardianController {
"SOS diakui"));
}
@PutMapping("/sos/{id}/resolve")
public ResponseEntity<ApiResponse<SosEventResponse>> resolveSos(@PathVariable Long id) {
return ResponseEntity.ok(ApiResponse.ok(
sosService.resolveSos(SecurityHelper.getCurrentUserId(), id),
"SOS ditangani"));
}
@GetMapping("/ai-config")
public ResponseEntity<ApiResponse<AiConfigResponse>> getAiConfig() {
// Guardian lihat config user yang dipair
@@ -117,7 +124,7 @@ public class GuardianController {
@GetMapping("/voice-commands")
public ResponseEntity<ApiResponse<?>> getVoiceCommands() {
return ResponseEntity.ok(ApiResponse.ok(
voiceCommandService.getAll(SecurityHelper.getCurrentUserId()),
voiceCommandService.getAllForGuardian(SecurityHelper.getCurrentUserId()),
"Voice commands"));
}
@@ -132,10 +139,18 @@ public class GuardianController {
@GetMapping("/shortcuts")
public ResponseEntity<ApiResponse<?>> getShortcuts() {
return ResponseEntity.ok(ApiResponse.ok(
hardwareShortcutService.getAll(SecurityHelper.getCurrentUserId()),
hardwareShortcutService.getAllForGuardian(SecurityHelper.getCurrentUserId()),
"Hardware shortcuts"));
}
@PutMapping("/shortcuts")
public ResponseEntity<ApiResponse<HardwareShortcutResponse>> updateShortcut(
@RequestBody HardwareShortcutUpdateRequest req) {
return ResponseEntity.ok(ApiResponse.ok(
hardwareShortcutService.updateByGuardian(SecurityHelper.getCurrentUserId(), req),
"Hardware shortcut diperbarui"));
}
@GetMapping("/geofence")
public ResponseEntity<ApiResponse<GeofenceResponse>> getGeofence() {
return ResponseEntity.ok(ApiResponse.ok(
@@ -3,8 +3,6 @@ package com.walkguide.controller;
import com.walkguide.dto.ApiResponse;
import com.walkguide.dto.request.*;
import com.walkguide.dto.response.*;
import com.walkguide.enums.ActivityLogType;
import com.walkguide.repository.UserRepository;
import com.walkguide.security.SecurityHelper;
import com.walkguide.service.*;
import lombok.RequiredArgsConstructor;
@@ -29,21 +27,13 @@ public class UserController {
private final AiConfigService aiConfigService;
private final VoiceCommandService voiceCommandService;
private final HardwareShortcutService hardwareShortcutService;
private final UserRepository userRepository;
private final UserService userService;
@GetMapping("/profile")
public ResponseEntity<ApiResponse<?>> getProfile() {
Long userId = SecurityHelper.getCurrentUserId();
var user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("User tidak ditemukan"));
var profile = java.util.Map.of(
"id", user.getId(),
"email", user.getEmail(),
"displayName", user.getDisplayName() != null ? user.getDisplayName() : "",
"role", user.getRole(),
"uniqueUserId", user.getUniqueUserId() != null ? user.getUniqueUserId() : ""
);
return ResponseEntity.ok(ApiResponse.ok(profile, "Profil user"));
return ResponseEntity.ok(ApiResponse.ok(
userService.getProfile(SecurityHelper.getCurrentUserId()),
"Profil user"));
}
@GetMapping("/settings")
@@ -163,19 +153,13 @@ public class UserController {
@PostMapping("/walkguide/start")
public ResponseEntity<ApiResponse<Void>> walkGuideStart() {
Long userId = SecurityHelper.getCurrentUserId();
userRepository.findById(userId).ifPresent(u ->
activityLogService.createLog(u, ActivityLogType.WALKGUIDE_START,
"WalkGuide dimulai", null));
userService.logWalkGuideStart(SecurityHelper.getCurrentUserId());
return ResponseEntity.ok(ApiResponse.ok(null, "WalkGuide dimulai"));
}
@PostMapping("/walkguide/stop")
public ResponseEntity<ApiResponse<Void>> walkGuideStop() {
Long userId = SecurityHelper.getCurrentUserId();
userRepository.findById(userId).ifPresent(u ->
activityLogService.createLog(u, ActivityLogType.WALKGUIDE_STOP,
"WalkGuide dihentikan", null));
userService.logWalkGuideStop(SecurityHelper.getCurrentUserId());
return ResponseEntity.ok(ApiResponse.ok(null, "WalkGuide dihentikan"));
}
}
@@ -2,9 +2,12 @@ package com.walkguide.service;
import com.walkguide.dto.request.HardwareShortcutUpdateRequest;
import com.walkguide.dto.response.HardwareShortcutResponse;
import com.walkguide.enums.PairingStatus;
import com.walkguide.enums.HardwareShortcutKey;
import com.walkguide.exception.PairingException;
import com.walkguide.exception.ResourceNotFoundException;
import com.walkguide.repository.HardwareShortcutRepository;
import com.walkguide.repository.PairingRelationRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@@ -15,6 +18,7 @@ import java.util.stream.Collectors;
public class HardwareShortcutService {
private final HardwareShortcutRepository hardwareShortcutRepository;
private final PairingRelationRepository pairingRelationRepository;
public List<HardwareShortcutResponse> getAll(Long userId) {
return hardwareShortcutRepository.findByUserId(userId).stream()
@@ -25,6 +29,13 @@ public class HardwareShortcutService {
.collect(Collectors.toList());
}
public List<HardwareShortcutResponse> getAllForGuardian(Long guardianId) {
var pairing = pairingRelationRepository
.findByGuardian_IdAndStatus(guardianId, PairingStatus.ACTIVE)
.orElseThrow(() -> new PairingException("Tidak ada user yang dipair"));
return getAll(pairing.getUser().getId());
}
// Bisa dipanggil dari HP User langsung (capture button) atau dari Guardian
public HardwareShortcutResponse update(Long userId, HardwareShortcutUpdateRequest req) {
HardwareShortcutKey key = HardwareShortcutKey.valueOf(req.getShortcutKey());
@@ -43,4 +54,11 @@ public class HardwareShortcutService {
.buttonName(shortcut.getButtonName()).buttonCode(shortcut.getButtonCode())
.enabled(shortcut.getEnabled()).build();
}
public HardwareShortcutResponse updateByGuardian(Long guardianId, HardwareShortcutUpdateRequest req) {
var pairing = pairingRelationRepository
.findByGuardian_IdAndStatus(guardianId, PairingStatus.ACTIVE)
.orElseThrow(() -> new PairingException("Tidak ada user yang dipair"));
return update(pairing.getUser().getId(), req);
}
}
@@ -87,6 +87,7 @@ public class SosService {
public SosEventResponse acknowledgeSos(Long guardianId, Long sosId) {
SosEvent sos = sosEventRepository.findById(sosId)
.orElseThrow(() -> new ResourceNotFoundException("SOS event tidak ditemukan"));
assertGuardianOwnsSos(guardianId, sos.getUserId());
sos.setStatus(SosStatus.ACKNOWLEDGED);
sos.setAcknowledgedAt(LocalDateTime.now());
@@ -111,6 +112,33 @@ public class SosService {
return toResponse(sos);
}
@Transactional
public SosEventResponse resolveSos(Long guardianId, Long sosId) {
SosEvent sos = sosEventRepository.findById(sosId)
.orElseThrow(() -> new ResourceNotFoundException("SOS event tidak ditemukan"));
assertGuardianOwnsSos(guardianId, sos.getUserId());
if (sos.getAcknowledgedAt() == null) {
sos.setAcknowledgedAt(LocalDateTime.now());
}
sos.setStatus(SosStatus.RESOLVED);
sosEventRepository.save(sos);
User user = userRepository.findById(sos.getUserId())
.orElseThrow(() -> new ResourceNotFoundException("User tidak ditemukan"));
activityLogService.createLog(user, ActivityLogType.SOS_ACKNOWLEDGED,
"Guardian menandai SOS sudah ditangani", null);
pairingRelationRepository.findByUser_IdAndStatus(sos.getUserId(), PairingStatus.ACTIVE)
.ifPresent(pairing -> fcmService.sendToToken(
pairing.getUser().getFcmToken(),
"SOS Sudah Ditangani",
"Guardian kamu sudah menandai SOS sebagai selesai.",
Map.of("type", "SOS_RESOLVED")));
return toResponse(sos);
}
public Page<SosEventResponse> getSosEvents(Long userId, Pageable pageable) {
return sosEventRepository.findByUserIdOrderByCreatedAtDesc(userId, pageable)
.map(this::toResponse);
@@ -125,6 +153,15 @@ public class SosService {
.map(this::toResponse);
}
private void assertGuardianOwnsSos(Long guardianId, Long userId) {
var pairing = pairingRelationRepository
.findByGuardian_IdAndStatus(guardianId, PairingStatus.ACTIVE)
.orElseThrow(() -> new ResourceNotFoundException("Tidak ada user yang dipair"));
if (!pairing.getUser().getId().equals(userId)) {
throw new ResourceNotFoundException("SOS event tidak ditemukan untuk guardian ini");
}
}
private SosEventResponse toResponse(SosEvent s) {
return SosEventResponse.builder()
.id(s.getId())
@@ -0,0 +1,40 @@
package com.walkguide.service;
import com.walkguide.enums.ActivityLogType;
import com.walkguide.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final ActivityLogService activityLogService;
public Map<String, Object> getProfile(Long userId) {
var user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("User tidak ditemukan"));
return Map.of(
"id", user.getId(),
"email", user.getEmail(),
"displayName", user.getDisplayName() != null ? user.getDisplayName() : "",
"role", user.getRole(),
"uniqueUserId", user.getUniqueUserId() != null ? user.getUniqueUserId() : ""
);
}
public void logWalkGuideStart(Long userId) {
userRepository.findById(userId).ifPresent(user ->
activityLogService.createLog(user, ActivityLogType.WALKGUIDE_START,
"WalkGuide dimulai", null));
}
public void logWalkGuideStop(Long userId) {
userRepository.findById(userId).ifPresent(user ->
activityLogService.createLog(user, ActivityLogType.WALKGUIDE_STOP,
"WalkGuide dihentikan", null));
}
}
@@ -52,6 +52,13 @@ public class VoiceCommandService {
.collect(Collectors.toList());
}
public List<VoiceCommandResponse> getAllForGuardian(Long guardianId) {
var pairing = pairingRelationRepository
.findByGuardian_IdAndStatus(guardianId, PairingStatus.ACTIVE)
.orElseThrow(() -> new PairingException("Tidak ada user yang dipair"));
return getAll(pairing.getUser().getId());
}
public VoiceCommandResponse updateByGuardian(Long guardianId, VoiceCommandUpdateRequest req) {
var pairing = pairingRelationRepository
.findByGuardian_IdAndStatus(guardianId, PairingStatus.ACTIVE)