diff --git a/assets/api-path-collection.json b/assets/api-path-collection.json index be1aceb..277a761 100644 --- a/assets/api-path-collection.json +++ b/assets/api-path-collection.json @@ -1,1701 +1,2257 @@ -{ - "meta": { - "format": "httpie", - "version": "1.0.0", - "contentType": "collection", - "schema": "https://schema.httpie.io/1.0.0.json", - "docs": "https://httpie.io/r/help/export-from-httpie", - "source": "HTTPie Desktop 2025.2.0" - }, - "entry": { - "name": "final-project-uas-v2", - "icon": { - "name": "default", - "color": "red" - }, - "auth": { - "type": "none" - }, - "requests": [ - { - "name": "Auth — /api/v1/auth", - "url": "", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "inherited" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Cek Server Hidup", - "url": "http://localhost:8080/api/v1/auth/ping", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "inherited" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Register Akun Baru (GUARDIAN)", - "url": "http://localhost:8080/api/v1/auth/login", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "inherited" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"email\": \"guardian@test.com\",\n \"password\": \"password123\",\n \"displayName\": \"Guardian Satu\",\n \"role\": \"GUARDIAN\"\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Register Akun Baru (USER)", - "url": "http://localhost:8080/api/v1/auth/register", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "inherited" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"email\": \"user@test.com\",\n \"password\": \"password123\",\n \"displayName\": \"User Satu\",\n \"role\": \"USER\"\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Login Get Token (USER)", - "url": "http://localhost:8080/api/v1/auth/login", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "inherited" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"email\": \"user@test.com\",\n \"password\": \"password123\",\n \"displayName\": \"User Satu\",\n \"role\": \"USER\"\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Login Get Token (GUARDIAN)", - "url": "http://localhost:8080/api/v1/auth/login", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "inherited" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"email\": \"guardian@test.com\",\n \"password\": \"password123\"\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Refresh Token (GUARDIAN)", - "url": "http://localhost:8080/api/v1/auth/refresh", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "inherited" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"refreshToken\": \"1a66db59-fd2d-496d-bd6e-057e1ededc18-cfe94ef3-c1e3-4cd0-b9b5-9ab4eaf91e18\"\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Logout (GUARDIAN)", - "url": "http://localhost:8080/api/v1/auth/logout", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjE3NDksImV4cCI6MTc3ODEyNTM0OX0.SCN8gudz9RnzfLIOtzwPESBsI4sHKmwYKEC8mlDDDP0" - }, - "target": "headers" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Update FCM Token (USER)", - "url": "http://localhost:8080/api/v1/auth/fcm-token", - "method": "PUT", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "inherited" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"fcmToken\": \"fcm_device_token_dari_firebase_sdk\"\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Pairing — /api/v1/shared/pairing", - "url": "", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "inherited" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Guardian Invite User", - "url": "http://localhost:8080/api/v1/shared/pairing/invite", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjE3NDksImV4cCI6MTc3ODEyNTM0OX0.SCN8gudz9RnzfLIOtzwPESBsI4sHKmwYKEC8mlDDDP0" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"uniqueUserId\": \"EO7JZKK19Z9A\"\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Accept or Deny Invite (USER)", - "url": "http://localhost:8080/api/v1/shared/pairing/respond", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"pairingId\": 1,\n \"accept\": true\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Unpair (GUARDIAN)", - "url": "http://localhost:8080/api/v1/shared/pairing/unpair", - "method": "DELETE", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjE3NDksImV4cCI6MTc3ODEyNTM0OX0.SCN8gudz9RnzfLIOtzwPESBsI4sHKmwYKEC8mlDDDP0" - }, - "target": "headers" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Check Pairing Status (GUARDIAN)", - "url": "http://localhost:8080/api/v1/shared/pairing/status", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjE3NDksImV4cCI6MTc3ODEyNTM0OX0.SCN8gudz9RnzfLIOtzwPESBsI4sHKmwYKEC8mlDDDP0" - }, - "target": "headers" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "User endpoints — /api/v1/user (ROLE_USER)", - "url": "", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "inherited" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "User Own Profile", - "url": "http://localhost:8080/api/v1/user/profile", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "User Location", - "url": "http://localhost:8080/api/v1/user/location", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"lat\": -7.2575,\n \"lng\": 112.7521,\n \"accuracy\": 5.0,\n \"speed\": 1.2,\n \"heading\": 270.0\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "YOLO Log Obstacle", - "url": "http://localhost:8080/api/v1/user/obstacle", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"label\": \"person\",\n \"confidence\": 0.87,\n \"direction\": \"CENTER\",\n \"estimatedDist\": \"Very Close\",\n \"lat\": -7.2575,\n \"lng\": 112.7521\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Trigger SOS Alert (USER)", - "url": "http://localhost:8080/api/v1/user/sos", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"triggerType\": \"MANUAL\",\n \"lat\": -7.2575,\n \"lng\": 112.7521\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "WalkGuide START Log", - "url": "http://localhost:8080/api/v1/user/walkguide/start", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "WalkGuide STOP Log", - "url": "http://localhost:8080/api/v1/user/walkguide/stop", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Log User Activity", - "url": "http://localhost:8080/api/v1/user/activity-logs?page=0&size=20", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "List User Notification", - "url": "http://localhost:8080/api/v1/user/notifications?page=0&size=20", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Unread Notif Count (USER)", - "url": "http://localhost:8080/api/v1/user/notifications/unread-count", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Read All Notif Function Mark (USER)", - "url": "http://localhost:8080/api/v1/user/notifications/mark-all-read", - "method": "PUT", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Only Mark 1 Notif Read (USER)", - "url": "http://localhost:8080/api/v1/user/notifications/5/read", - "method": "PUT", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Take User Setting", - "url": "http://localhost:8080/api/v1/user/settings", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Updates User Setting", - "url": "http://localhost:8080/api/v1/user/settings", - "method": "PUT", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"ttsLanguage\": \"id-ID\",\n \"warnNoGuardian\": true,\n \"hapticEnabled\": true\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "List Voice Commands (USER)", - "url": "http://localhost:8080/api/v1/user/voice-commands", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"ttsLanguage\": \"id-ID\",\n \"warnNoGuardian\": true,\n \"hapticEnabled\": true\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "List All Shortcut (USER)", - "url": "http://localhost:8080/api/v1/user/shortcuts", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"ttsLanguage\": \"id-ID\",\n \"warnNoGuardian\": true,\n \"hapticEnabled\": true\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Update Shortcut (USER)", - "url": "http://localhost:8080/api/v1/user/shortcuts", - "method": "PUT", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"shortcutKey\": \"CALL_GUARDIAN\",\n \"buttonName\": \"Volume Up\",\n \"buttonCode\": 24,\n \"enabled\": true\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Check AI Config (USER)", - "url": "http://localhost:8080/api/v1/user/ai-config", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Guardian endpoints — /api/v1/guardian (ROLE_GUARDIAN)", - "url": "", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "inherited" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Home Data (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/dashboard ", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Get User Location (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/user-location", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "See User History (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/location-history?page=0&size=50", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "User Activity Log (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/activity-logs?page=0&size=20", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Log User Obstacle (USER)", - "url": "http://localhost:8080/api/v1/guardian/obstacle-logs?page=0&size=20", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "none", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Send Notif to User (GUARDIAN)", - "url": " http://localhost:8080/api/v1/guardian/notifications/send", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"notifType\": \"TEXT\",\n \"content\": \"Hati-hati, ada jalan rusak di depanmu\"\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Send Notif to User AUDIO (GUARDIAN)", - "url": " http://localhost:8080/api/v1/guardian/notifications/send", - "method": "POST", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"notifType\": \"VOICE_NOTE\",\n \"voiceNoteUrl\": \"https://example.com/audio/note.m4a\",\n \"voiceNoteDuration\": 15\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Lihat SOS dari User (Guardian)", - "url": "http://localhost:8080/api/v1/guardian/sos-events?page=0&size=20", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Acknowledge SOS (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/sos/3/acknowledge", - "method": "PUT", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "See AI Config (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/ai-config", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Update AI Config YOLO (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/ai-config", - "method": "PUT", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"confidenceThreshold\": 0.6,\n \"alertDistanceClose\": 1.5,\n \"alertDistanceMedium\": 3.0,\n \"maxInferenceFps\": 5,\n \"enabledLabels\": \"ALL\"\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "List CMD Voice User (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/voice-commands", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Update Voice Trigger Phase (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/voice-commands", - "method": "PUT", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"commandKey\": \"START_WALKGUIDE\",\n \"triggerPhrase\": \"mulai walkguide\",\n \"enabled\": true\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "List USER Shortcut (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/shortcuts", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "See Geofence Config (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/geofence", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Set Geofence Area (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/geofence", - "method": "PUT", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"centerLat\": -7.2575,\n \"centerLng\": 112.7521,\n \"radiusMeters\": 200.0,\n \"enabled\": true\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "See USER TTS Settings (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/user-settings ", - "method": "GET", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - }, - { - "name": "Update USER TTS Settings (GUARDIAN)", - "url": "http://localhost:8080/api/v1/guardian/user-settings ", - "method": "PUT", - "headers": [], - "queryParams": [], - "pathParams": [], - "auth": { - "type": "bearer", - "credentials": { - "username": "", - "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" - }, - "target": "headers" - }, - "body": { - "type": "text", - "file": { - "name": "" - }, - "text": { - "value": "{\n \"ttsLanguage\": \"id-ID\",\n \"ttsPitch\": 1.0,\n \"ttsSpeed\": 0.9,\n \"warnNoGuardian\": true,\n \"hapticEnabled\": true\n}", - "format": "application/json" - }, - "form": { - "isMultipart": false, - "fields": [] - }, - "graphql": { - "query": "", - "variables": "" - } - } - } - ] - } -} \ No newline at end of file +{ + "meta": { + "format": "httpie", + "version": "1.0.0", + "contentType": "collection", + "schema": "https://schema.httpie.io/1.0.0.json", + "docs": "https://httpie.io/r/help/export-from-httpie", + "source": "HTTPie Desktop 2025.2.0" + }, + "entry": { + "name": "final-project-uas-v2", + "icon": { + "name": "default", + "color": "red" + }, + "auth": { + "type": "none" + }, + "requests": [ + { + "name": "Auth — /api/v1/auth", + "url": "", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Cek Server Hidup", + "url": "http://localhost:8080/api/v1/auth/ping", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Register Akun Baru (GUARDIAN)", + "url": "http://localhost:8080/api/v1/auth/register", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"email\": \"guardian@test.com\",\n \"password\": \"password123\",\n \"displayName\": \"Guardian Satu\",\n \"role\": \"GUARDIAN\"\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Register Akun Baru (USER)", + "url": "http://localhost:8080/api/v1/auth/register", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"email\": \"user@test.com\",\n \"password\": \"password123\",\n \"displayName\": \"User Satu\",\n \"role\": \"USER\"\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Login Get Token (USER)", + "url": "http://localhost:8080/api/v1/auth/login", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"email\": \"user@test.com\",\n \"password\": \"password123\",\n \"displayName\": \"User Satu\",\n \"role\": \"USER\"\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Login Get Token (GUARDIAN)", + "url": "http://localhost:8080/api/v1/auth/login", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"email\": \"guardian@test.com\",\n \"password\": \"password123\"\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Refresh Token (GUARDIAN)", + "url": "http://localhost:8080/api/v1/auth/refresh", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"refreshToken\": \"1a66db59-fd2d-496d-bd6e-057e1ededc18-cfe94ef3-c1e3-4cd0-b9b5-9ab4eaf91e18\"\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Logout (GUARDIAN)", + "url": "http://localhost:8080/api/v1/auth/logout", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjE3NDksImV4cCI6MTc3ODEyNTM0OX0.SCN8gudz9RnzfLIOtzwPESBsI4sHKmwYKEC8mlDDDP0" + }, + "target": "headers" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Update FCM Token (USER)", + "url": "http://localhost:8080/api/v1/auth/fcm-token", + "method": "PUT", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"fcmToken\": \"fcm_device_token_dari_firebase_sdk\"\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Pairing — /api/v1/shared/pairing", + "url": "", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Guardian Invite User", + "url": "http://localhost:8080/api/v1/shared/pairing/invite", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjE3NDksImV4cCI6MTc3ODEyNTM0OX0.SCN8gudz9RnzfLIOtzwPESBsI4sHKmwYKEC8mlDDDP0" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"uniqueUserId\": \"EO7JZKK19Z9A\"\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Accept or Deny Invite (USER)", + "url": "http://localhost:8080/api/v1/shared/pairing/respond", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"pairingId\": 1,\n \"accept\": true\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Unpair (GUARDIAN)", + "url": "http://localhost:8080/api/v1/shared/pairing/unpair", + "method": "DELETE", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjE3NDksImV4cCI6MTc3ODEyNTM0OX0.SCN8gudz9RnzfLIOtzwPESBsI4sHKmwYKEC8mlDDDP0" + }, + "target": "headers" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Check Pairing Status (GUARDIAN)", + "url": "http://localhost:8080/api/v1/shared/pairing/status", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjE3NDksImV4cCI6MTc3ODEyNTM0OX0.SCN8gudz9RnzfLIOtzwPESBsI4sHKmwYKEC8mlDDDP0" + }, + "target": "headers" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "User endpoints — /api/v1/user (ROLE_USER)", + "url": "", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "User Own Profile", + "url": "http://localhost:8080/api/v1/user/profile", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "User Location", + "url": "http://localhost:8080/api/v1/user/location", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"lat\": -7.2575,\n \"lng\": 112.7521,\n \"accuracy\": 5.0,\n \"speed\": 1.2,\n \"heading\": 270.0\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "YOLO Log Obstacle", + "url": "http://localhost:8080/api/v1/user/obstacle", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"label\": \"person\",\n \"confidence\": 0.87,\n \"direction\": \"CENTER\",\n \"estimatedDist\": \"Very Close\",\n \"lat\": -7.2575,\n \"lng\": 112.7521\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Trigger SOS Alert (USER)", + "url": "http://localhost:8080/api/v1/user/sos", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"triggerType\": \"MANUAL\",\n \"lat\": -7.2575,\n \"lng\": 112.7521\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "WalkGuide START Log", + "url": "http://localhost:8080/api/v1/user/walkguide/start", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "WalkGuide STOP Log", + "url": "http://localhost:8080/api/v1/user/walkguide/stop", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Log User Activity", + "url": "http://localhost:8080/api/v1/user/activity-logs?page=0\u0026size=20", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "List User Notification", + "url": "http://localhost:8080/api/v1/user/notifications?page=0\u0026size=20", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Unread Notif Count (USER)", + "url": "http://localhost:8080/api/v1/user/notifications/unread-count", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Read All Notif Function Mark (USER)", + "url": "http://localhost:8080/api/v1/user/notifications/mark-all-read", + "method": "PUT", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Only Mark 1 Notif Read (USER)", + "url": "http://localhost:8080/api/v1/user/notifications/5/read", + "method": "PUT", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Take User Setting", + "url": "http://localhost:8080/api/v1/user/settings", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Updates User Setting", + "url": "http://localhost:8080/api/v1/user/settings", + "method": "PUT", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"ttsLanguage\": \"id-ID\",\n \"warnNoGuardian\": true,\n \"hapticEnabled\": true\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "List Voice Commands (USER)", + "url": "http://localhost:8080/api/v1/user/voice-commands", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"ttsLanguage\": \"id-ID\",\n \"warnNoGuardian\": true,\n \"hapticEnabled\": true\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "List All Shortcut (USER)", + "url": "http://localhost:8080/api/v1/user/shortcuts", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"ttsLanguage\": \"id-ID\",\n \"warnNoGuardian\": true,\n \"hapticEnabled\": true\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Update Shortcut (USER)", + "url": "http://localhost:8080/api/v1/user/shortcuts", + "method": "PUT", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"shortcutKey\": \"CALL_GUARDIAN\",\n \"buttonName\": \"Volume Up\",\n \"buttonCode\": 24,\n \"enabled\": true\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Check AI Config (USER)", + "url": "http://localhost:8080/api/v1/user/ai-config", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9VU0VSIiwidXNlcklkIjo4LCJzdWIiOiJ1c2VyQHRlc3QuY29tIiwiaWF0IjoxNzc4MTIyNTAyLCJleHAiOjE3NzgxMjYxMDJ9.Wr1mVj0nk7M-OMEwoIZScDHabw4Y3Po3ToW4e10It3w" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Guardian endpoints — /api/v1/guardian (ROLE_GUARDIAN)", + "url": "", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Home Data (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/dashboard", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Get User Location (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/user-location", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "See User History (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/location-history?page=0\u0026size=50", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "User Activity Log (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/activity-logs?page=0\u0026size=20", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Log User Obstacle (USER)", + "url": "http://localhost:8080/api/v1/guardian/obstacle-logs?page=0\u0026size=20", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Send Notif to User (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/notifications/send", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"notifType\": \"TEXT\",\n \"content\": \"Hati-hati, ada jalan rusak di depanmu\"\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Send Notif to User AUDIO (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/notifications/send", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"notifType\": \"VOICE_NOTE\",\n \"voiceNoteUrl\": \"https://example.com/audio/note.m4a\",\n \"voiceNoteDuration\": 15\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Lihat SOS dari User (Guardian)", + "url": "http://localhost:8080/api/v1/guardian/sos-events?page=0\u0026size=20", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Acknowledge SOS (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/sos/3/acknowledge", + "method": "PUT", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "See AI Config (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/ai-config", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Update AI Config YOLO (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/ai-config", + "method": "PUT", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"confidenceThreshold\": 0.6,\n \"alertDistanceClose\": 1.5,\n \"alertDistanceMedium\": 3.0,\n \"maxInferenceFps\": 5,\n \"enabledLabels\": \"ALL\"\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "List CMD Voice User (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/voice-commands", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Update Voice Trigger Phase (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/voice-commands", + "method": "PUT", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"commandKey\": \"START_WALKGUIDE\",\n \"triggerPhrase\": \"mulai walkguide\",\n \"enabled\": true\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "List USER Shortcut (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/shortcuts", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "See Geofence Config (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/geofence", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Set Geofence Area (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/geofence", + "method": "PUT", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"centerLat\": -7.2575,\n \"centerLng\": 112.7521,\n \"radiusMeters\": 200.0,\n \"enabled\": true\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "See USER TTS Settings (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/user-settings", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Update USER TTS Settings (GUARDIAN)", + "url": "http://localhost:8080/api/v1/guardian/user-settings", + "method": "PUT", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "bearer", + "credentials": { + "username": "", + "password": "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiUk9MRV9HVUFSRElBTiIsInVzZXJJZCI6Nywic3ViIjoiZ3VhcmRpYW5AdGVzdC5jb20iLCJpYXQiOjE3NzgxMjIxNTAsImV4cCI6MTc3ODEyNTc1MH0.CxmnZ4m_5M9sdU2tpC8z1PY8W1dHtfWWMDWa1lrd9sk" + }, + "target": "headers" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"ttsLanguage\": \"id-ID\",\n \"ttsPitch\": 1.0,\n \"ttsSpeed\": 0.9,\n \"warnNoGuardian\": true,\n \"hapticEnabled\": true\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Shared Call — /api/v1/shared/call", + "url": "", + "method": "GET", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "none", + "file": { + "name": "" + }, + "text": { + "value": "", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Generate Agora Token", + "url": "http://localhost:8080/api/v1/shared/call/token", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"receiverId\": 8\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "Notify Incoming Call", + "url": "http://localhost:8080/api/v1/shared/call/notify", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"receiverId\": 8,\n \"channelName\": \"call_7_8\",\n \"agoraToken\": \"TOKEN_DARI_RESPONSE_TOKEN\",\n \"receiverUid\": 8\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + }, + { + "name": "End Call", + "url": "http://localhost:8080/api/v1/shared/call/end", + "method": "POST", + "headers": [ + + ], + "queryParams": [ + + ], + "pathParams": [ + + ], + "auth": { + "type": "inherited" + }, + "body": { + "type": "text", + "file": { + "name": "" + }, + "text": { + "value": "{\n \"otherId\": 8\n}", + "format": "application/json" + }, + "form": { + "isMultipart": false, + "fields": [ + + ] + }, + "graphql": { + "query": "", + "variables": "" + } + } + } + ] + } +} diff --git a/ooad-docs/BENCHMARK_EVIDENCE_TEMPLATE.md b/ooad-docs/BENCHMARK_EVIDENCE_TEMPLATE.md new file mode 100644 index 0000000..e32235e --- /dev/null +++ b/ooad-docs/BENCHMARK_EVIDENCE_TEMPLATE.md @@ -0,0 +1,39 @@ +# Benchmark Evidence Template + +This file is intentionally a template, not a fabricated result. Fill it after running benchmarks on the required machine/device. + +## Flutter Device Benchmark + +| Metric | Tool | Threshold | Result | Evidence File | +|---|---|---:|---:|---| +| Memory baseline | DevTools Memory | report MB | TBD | screenshot TBD | +| Memory leak check | DevTools Memory | no steady growth | TBD | screenshot TBD | +| Frame rate / jank | DevTools Performance | >= 90% frames < 16ms | TBD | screenshot TBD | +| CPU profile | DevTools CPU Profiler | top 3 operations documented | TBD | screenshot TBD | +| API latency | Dio logs | < 1500ms | TBD | log TBD | +| Cold start | `flutter run --profile --trace-startup` | < 3000ms | TBD | trace TBD | +| APK size | `flutter build apk --analyze-size` | < 50MB | TBD | report TBD | + +## Backend Load Benchmark + +| Metric | Tool | Threshold | Result | Evidence File | +|---|---|---:|---:|---| +| Throughput | k6/JMeter | >= 100 req/s | TBD | k6 summary TBD | +| p95 latency | k6/JMeter | < 500ms | TBD | k6 summary TBD | +| Error rate | k6/JMeter | < 1% | TBD | k6 summary TBD | +| Slow query | DB/Actuator logs | no query > 200ms | TBD | log TBD | +| JVM memory | Actuator metrics | no heap exhaustion | TBD | metrics TBD | + +## Commands To Run + +```powershell +cd "D:\CodeSpace\Final Project Gabungan - Broken Test\walkguide-mobile\walkguide_app" +flutter run --profile --trace-startup +flutter build apk --analyze-size +``` + +```bash +cd "walkguide-backend/demo/k6-tests" +./run-all-tests.sh smoke +./run-all-tests.sh load +``` diff --git a/ooad-docs/DESIGN_PATTERNS.md b/ooad-docs/DESIGN_PATTERNS.md new file mode 100644 index 0000000..f0b7780 --- /dev/null +++ b/ooad-docs/DESIGN_PATTERNS.md @@ -0,0 +1,38 @@ +# WalkGuide Design Pattern Documentation + +## Builder - Creational +- Backend DTO/entity builders via Lombok `@Builder`. +- Files: `PairingStatusResponse.java`, `AgoraTokenResponse.java`, entity classes such as `PairingRelation.java`. +- Reason: response/entity construction has many optional fields, so builder calls are clearer than long constructors. + +## Singleton / Service Locator - Creational +- Flutter registers app-wide services once with GetIt. +- File: `walkguide-mobile/walkguide_app/lib/app/injection_container.dart`. +- Examples: `TtsService`, `WebSocketService`, `CallService`, `YoloDetector`. +- Reason: resource-heavy services need one shared lifecycle. + +## Facade - Structural +- Flutter service classes hide low-level plugins from UI. +- Files: `TtsService`, `HapticService`, `FcmService`, `CallService`, `WebSocketService`. +- Reason: screens call simple domain-oriented methods instead of plugin APIs directly. + +## Repository - Structural +- Backend repositories abstract JPA persistence. +- Files: `UserRepository`, `PairingRelationRepository`, `LocationHistoryRepository`, etc. +- Reason: service layer works against repository contracts, not SQL. + +## Observer - Behavioral +- Flutter BLoC/Cubit and ChangeNotifier notify screens on state changes. +- Backend WebSocket broker pushes location/SOS/notification updates to subscribers. +- Files: `AppCubit`, `WebSocketService`, `LocationBroadcaster`. +- Reason: real-time features need push updates without polling. + +## Strategy - Behavioral +- Obstacle direction/distance analysis can vary independently from camera capture. +- File: `core/ai/obstacle_analyzer.dart`. +- Reason: detection interpretation is isolated so thresholds/rules can evolve. + +## Chain of Responsibility - Behavioral +- Dio interceptors handle token injection, refresh, and error flow. +- File: `core/network/api_client.dart`. +- Reason: each request passes through consistent auth/error handling before reaching UI. diff --git a/ooad-docs/TRACEABILITY_AUDIT.md b/ooad-docs/TRACEABILITY_AUDIT.md new file mode 100644 index 0000000..2b4e72f --- /dev/null +++ b/ooad-docs/TRACEABILITY_AUDIT.md @@ -0,0 +1,29 @@ +# WalkGuide Traceability Audit + +## Use Case To Code + +| Use Case | Flutter Entry | Backend Entry | Status | +|---|---|---|---| +| Register/Login | `features/auth/*` | `AuthController`, `AuthService` | Implemented | +| Pair Guardian/User | `features/pairing/pairing_screens.dart` | `PairingController`, `PairingService` | Implemented | +| Start/Stop WalkGuide | `features/walk_guide/walk_guide_screen.dart` | `POST /user/walkguide/start`, `POST /user/walkguide/stop` | Implemented | +| Obstacle Detection | `core/ai/*`, `walk_guide_screen.dart` | `POST /user/obstacle` | Partially implemented; real `.tflite` model file still required | +| Location Tracking | `LocationReporterService`, navigation/walk screens | `LocationService`, `LocationBroadcaster` | Implemented | +| SOS | `features/sos/sos_screen.dart` | `SosService`, `GuardianController` | Implemented | +| Notifications | `features/notifications/notification_screen.dart` | `NotificationService`, `FcmService` | Partially implemented; backend FCM is log-only without credentials | +| Guardian Dashboard | `guardian_dashboard_screen.dart` | `GuardianDashboardService` | Implemented | +| Call | `features/call/call_screen.dart`, `CallService` | `CallController`, `AgoraTokenService` | Partially implemented; Agora App ID/credential required for live call | +| Geofence | guardian dashboard screens | `GeofenceService` | Implemented | + +## Design Deviations + +- Flutter uses a pragmatic mix of BLoC/Cubit, ChangeNotifier, and StatefulWidget. This deviates from strict full-BLoC architecture but keeps feature screens small for the exam demo. +- Offline storage uses `SharedPreferences` queue instead of a full Drift database for cached entities. The dependency exists, but production-grade SQLite cache is not fully wired. +- Backend FCM service is log-only until Firebase Admin credentials are provided. +- Agora call flow is implemented at API and service level, but live RTC depends on a real Agora App ID. + +## Remaining Evidence + +- Export rendered OOAD diagrams from the PlantUML files in this folder. +- Run backend tests and archive JaCoCo/Surefire reports. +- Run Flutter benchmarks on a physical Android device and add screenshots/results. diff --git a/ooad-docs/diagrams/class-diagram.puml b/ooad-docs/diagrams/class-diagram.puml new file mode 100644 index 0000000..ed9f6ab --- /dev/null +++ b/ooad-docs/diagrams/class-diagram.puml @@ -0,0 +1,71 @@ +@startuml +skinparam classAttributeIconSize 0 + +class User { + +Long id + +String email + +String role + +String uniqueUserId + +String displayName + +String fcmToken +} + +class PairingRelation { + +Long id + +PairingStatus status + +LocalDateTime invitedAt + +LocalDateTime respondedAt +} + +class LocationHistory +class ActivityLog +class ObstacleLog +class GuardianNotification +class SosEvent +class UserSettings +class AiConfig +class VoiceCommandConfig +class HardwareShortcut +class GeofenceConfig +class RefreshToken + +User "1" -- "0..*" LocationHistory +User "1" -- "0..*" ActivityLog +User "1" -- "0..*" ObstacleLog +User "1" -- "0..*" SosEvent +User "1" -- "0..1" UserSettings +User "1" -- "0..*" RefreshToken +User "1" -- "0..*" PairingRelation : guardian +User "1" -- "0..*" PairingRelation : user +PairingRelation "1" -- "0..*" GuardianNotification +PairingRelation "1" -- "0..1" AiConfig +PairingRelation "1" -- "0..*" VoiceCommandConfig +PairingRelation "1" -- "0..*" HardwareShortcut +PairingRelation "1" -- "0..1" GeofenceConfig + +class AuthController +class PairingController +class UserController +class GuardianController +class CallController +class AuthService +class PairingService +class LocationService +class NotificationService +class SosService +class AgoraTokenService +class FcmService +class LocationBroadcaster + +AuthController --> AuthService +PairingController --> PairingService +UserController --> LocationService +UserController --> SosService +GuardianController --> NotificationService +GuardianController --> SosService +CallController --> AgoraTokenService +CallController --> FcmService +LocationService --> LocationBroadcaster +NotificationService --> LocationBroadcaster +SosService --> LocationBroadcaster +@enduml diff --git a/ooad-docs/diagrams/component-diagram.puml b/ooad-docs/diagrams/component-diagram.puml new file mode 100644 index 0000000..c3d8914 --- /dev/null +++ b/ooad-docs/diagrams/component-diagram.puml @@ -0,0 +1,35 @@ +@startuml +skinparam componentStyle rectangle + +component "Flutter Mobile App" { + [Presentation Screens] + [ApiClient + Interceptors] + [TTS/STT/YOLO/Location Services] + [WebSocketService] + [CallService] +} + +component "Spring Boot Backend" { + [Controllers] + [Services] + [Repositories] + [Security/JWT] + [WebSocket Broker] +} + +database "PostgreSQL" as DB +cloud "Firebase FCM" as FCM +cloud "Agora RTC" as Agora +cloud "OpenStreetMap/OSRM" as Maps + +[Presentation Screens] --> [ApiClient + Interceptors] +[ApiClient + Interceptors] --> [Controllers] : REST /api/v1 +[WebSocketService] --> [WebSocket Broker] : STOMP /ws +[CallService] --> [Controllers] : /shared/call +[Controllers] --> [Services] +[Services] --> [Repositories] +[Repositories] --> DB +[Services] --> FCM +[CallService] --> Agora +[Presentation Screens] --> Maps +@enduml diff --git a/ooad-docs/diagrams/erd-diagram.puml b/ooad-docs/diagrams/erd-diagram.puml new file mode 100644 index 0000000..1e6bc71 --- /dev/null +++ b/ooad-docs/diagrams/erd-diagram.puml @@ -0,0 +1,101 @@ +@startuml +hide circle +skinparam linetype ortho + +entity users { + * id : BIGSERIAL <> + -- + email : VARCHAR + password : VARCHAR + role : VARCHAR + unique_user_id : CHAR(12) + display_name : VARCHAR + fcm_token : VARCHAR + created_at : TIMESTAMP +} + +entity pairing_relations { + * id : BIGSERIAL <> + -- + guardian_id : BIGINT <> + user_id : BIGINT <> + status : VARCHAR + invited_at : TIMESTAMP + responded_at : TIMESTAMP +} + +entity activity_logs { + * id : BIGSERIAL <> + -- + user_id : BIGINT <> + log_type : VARCHAR + description : TEXT + metadata : JSONB + created_at : TIMESTAMP +} + +entity obstacle_logs { + * id : BIGSERIAL <> + -- + user_id : BIGINT <> + label : VARCHAR + confidence : FLOAT + direction : VARCHAR + estimated_dist : VARCHAR + lat : DOUBLE + lng : DOUBLE +} + +entity location_history { + * id : BIGSERIAL <> + -- + user_id : BIGINT <> + lat : DOUBLE + lng : DOUBLE + accuracy : FLOAT + speed : FLOAT + heading : FLOAT +} + +entity guardian_notifications { + * id : BIGSERIAL <> + -- + guardian_id : BIGINT <> + user_id : BIGINT <> + notif_type : VARCHAR + content : TEXT + is_read : BOOLEAN +} + +entity sos_events { + * id : BIGSERIAL <> + -- + user_id : BIGINT <> + trigger_type : VARCHAR + lat : DOUBLE + lng : DOUBLE + status : VARCHAR +} + +entity user_settings +entity ai_configs +entity voice_command_configs +entity hardware_shortcuts +entity geofence_configs +entity refresh_tokens + +users ||--o{ pairing_relations : guardian_id +users ||--o{ pairing_relations : user_id +users ||--o{ activity_logs +users ||--o{ obstacle_logs +users ||--o{ location_history +users ||--o{ guardian_notifications : guardian_id +users ||--o{ guardian_notifications : user_id +users ||--o{ sos_events +users ||--o| user_settings +users ||--o{ refresh_tokens +pairing_relations ||--o| ai_configs +pairing_relations ||--o{ voice_command_configs +pairing_relations ||--o{ hardware_shortcuts +pairing_relations ||--o| geofence_configs +@enduml diff --git a/ooad-docs/diagrams/sequence-login.puml b/ooad-docs/diagrams/sequence-login.puml new file mode 100644 index 0000000..92dba34 --- /dev/null +++ b/ooad-docs/diagrams/sequence-login.puml @@ -0,0 +1,19 @@ +@startuml +actor User +participant "Flutter LoginScreen" as UI +participant "ApiClient/Dio" as Dio +participant "AuthController" as Controller +participant "AuthService" as Service +database "PostgreSQL" as DB + +User -> UI : enter email/password +UI -> Dio : POST /api/v1/auth/login +Dio -> Controller : LoginRequest +Controller -> Service : login(req) +Service -> DB : find user + refresh token +DB --> Service : user +Service --> Controller : AuthDataResponse +Controller --> Dio : ApiResponse +Dio --> UI : tokens + role +UI -> UI : save tokens and route by role +@enduml diff --git a/ooad-docs/diagrams/sequence-pairing.puml b/ooad-docs/diagrams/sequence-pairing.puml new file mode 100644 index 0000000..0fe79f6 --- /dev/null +++ b/ooad-docs/diagrams/sequence-pairing.puml @@ -0,0 +1,23 @@ +@startuml +actor Guardian +actor User +participant "GuardianPairingScreen" as GUI +participant "PairingController" as Controller +participant "PairingService" as Service +database "PostgreSQL" as DB +participant "FcmService" as FCM + +Guardian -> GUI : input uniqueUserId +GUI -> Controller : POST /shared/pairing/invite +Controller -> Service : inviteUser(guardianId, uniqueUserId) +Service -> DB : validate and create PENDING relation +Service -> FCM : notify user +Service --> Controller : PairingStatusResponse +Controller --> GUI : invite status + +User -> Controller : POST /shared/pairing/respond +Controller -> Service : respondToPairing(userId, pairingId, accept) +Service -> DB : update ACTIVE/REJECTED +Service -> DB : seed default AI/voice/shortcut configs +Service -> FCM : notify guardian +@enduml diff --git a/ooad-docs/diagrams/sequence-sos.puml b/ooad-docs/diagrams/sequence-sos.puml new file mode 100644 index 0000000..382bcb6 --- /dev/null +++ b/ooad-docs/diagrams/sequence-sos.puml @@ -0,0 +1,22 @@ +@startuml +actor User +actor Guardian +participant "SosScreen" as UI +participant "UserController" as UserController +participant "SosService" as SosService +database "PostgreSQL" as DB +participant "FcmService" as FCM +participant "LocationBroadcaster" as WS +participant "GuardianDashboard" as Dashboard + +User -> UI : press SOS / voice command +UI -> UserController : POST /api/v1/user/sos +UserController -> SosService : triggerSos(userId, req) +SosService -> DB : save sos_events +SosService -> FCM : push high-priority SOS +SosService -> WS : /queue/sos/{guardianId} +WS -> Dashboard : realtime SOS alert +Guardian -> Dashboard : acknowledge +Dashboard -> SosService : PUT /guardian/sos/{id}/acknowledge +SosService -> DB : status ACKNOWLEDGED +@enduml diff --git a/ooad-docs/diagrams/state-sos-event.puml b/ooad-docs/diagrams/state-sos-event.puml new file mode 100644 index 0000000..68d6c77 --- /dev/null +++ b/ooad-docs/diagrams/state-sos-event.puml @@ -0,0 +1,7 @@ +@startuml +[*] --> TRIGGERED : User sends SOS +TRIGGERED --> ACKNOWLEDGED : Guardian acknowledges +ACKNOWLEDGED --> RESOLVED : incident handled +TRIGGERED --> RESOLVED : auto/manual close +RESOLVED --> [*] +@enduml diff --git a/ooad-docs/diagrams/use-case-diagram.puml b/ooad-docs/diagrams/use-case-diagram.puml new file mode 100644 index 0000000..fe903bf --- /dev/null +++ b/ooad-docs/diagrams/use-case-diagram.puml @@ -0,0 +1,45 @@ +@startuml +left to right direction +actor "User\n(Visually Impaired)" as User +actor "Guardian" as Guardian +actor "Firebase FCM" as FCM +actor "Agora RTC" as Agora +actor "OpenStreetMap/OSRM" as Map + +rectangle "WalkGuide System" { + usecase "Register/Login" as UCAuth + usecase "Pair Guardian and User" as UCPair + usecase "Start WalkGuide" as UCWalk + usecase "Detect Obstacle" as UCDetect + usecase "Report Location" as UCLoc + usecase "Trigger SOS" as UCSos + usecase "Read Notifications" as UCNotif + usecase "Call Partner" as UCCall + usecase "Monitor Dashboard" as UCDash + usecase "Configure AI, TTS,\nVoice Commands, Geofence" as UCConfig + usecase "Acknowledge SOS" as UCAck + usecase "Navigate Route" as UCNav +} + +User --> UCAuth +Guardian --> UCAuth +Guardian --> UCPair +User --> UCPair +User --> UCWalk +UCWalk --> UCDetect : <> +UCWalk --> UCLoc : <> +User --> UCSos +User --> UCNotif +User --> UCCall +Guardian --> UCCall +Guardian --> UCDash +Guardian --> UCConfig +Guardian --> UCAck +User --> UCNav + +UCSos --> FCM +UCNotif --> FCM +UCCall --> Agora +UCCall --> FCM +UCNav --> Map +@enduml diff --git a/walkguide-backend/demo/src/main/java/com/walkguide/dto/response/PairingStatusResponse.java b/walkguide-backend/demo/src/main/java/com/walkguide/dto/response/PairingStatusResponse.java index 5ccd9c9..8fd8d9f 100644 --- a/walkguide-backend/demo/src/main/java/com/walkguide/dto/response/PairingStatusResponse.java +++ b/walkguide-backend/demo/src/main/java/com/walkguide/dto/response/PairingStatusResponse.java @@ -8,6 +8,7 @@ import java.time.LocalDateTime; public class PairingStatusResponse { private Long pairingId; private String status; // PENDING, ACTIVE, REJECTED, NONE + private Long pairedWithId; // ID partner yang dipair private String pairedWithName; // nama Guardian (untuk User) atau nama User (untuk Guardian) private String pairedWithEmail; private String uniqueUserId; // ID user yang di-pair diff --git a/walkguide-backend/demo/src/main/java/com/walkguide/service/PairingService.java b/walkguide-backend/demo/src/main/java/com/walkguide/service/PairingService.java index d4733a5..bb4db44 100644 --- a/walkguide-backend/demo/src/main/java/com/walkguide/service/PairingService.java +++ b/walkguide-backend/demo/src/main/java/com/walkguide/service/PairingService.java @@ -207,6 +207,7 @@ public class PairingService { return PairingStatusResponse.builder() .pairingId(p.getId()) .status(p.getStatus().name()) + .pairedWithId("GUARDIAN".equals(viewerRole) ? user.getId() : guardian.getId()) .pairedWithName(pairedWithName) .pairedWithEmail(pairedWithEmail) .uniqueUserId(user.getUniqueUserId()) diff --git a/walkguide-backend/demo/src/main/resources/openapi.yaml b/walkguide-backend/demo/src/main/resources/openapi.yaml new file mode 100644 index 0000000..7b028ae --- /dev/null +++ b/walkguide-backend/demo/src/main/resources/openapi.yaml @@ -0,0 +1,287 @@ +openapi: 3.0.3 +info: + title: WalkGuide API + version: 1.0.0 + description: Design contract for WalkGuide Flutter and Spring Boot integration. +servers: + - url: http://localhost:8080/api/v1 +security: + - bearerAuth: [] +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + schemas: + ApiResponse: + type: object + properties: + success: { type: boolean } + data: { nullable: true } + message: { type: string } + timestamp: { type: string, format: date-time } + LoginRequest: + type: object + required: [email, password] + properties: + email: { type: string, format: email } + password: { type: string } + RegisterRequest: + type: object + required: [email, password, displayName, role] + properties: + email: { type: string, format: email } + password: { type: string, minLength: 6 } + displayName: { type: string } + role: { type: string, enum: [USER, GUARDIAN] } + PairingInviteRequest: + type: object + required: [uniqueUserId] + properties: + uniqueUserId: { type: string, minLength: 12, maxLength: 12 } + PairingRespondRequest: + type: object + required: [pairingId, accept] + properties: + pairingId: { type: integer, format: int64 } + accept: { type: boolean } + LocationUpdateRequest: + type: object + properties: + lat: { type: number, format: double } + lng: { type: number, format: double } + accuracy: { type: number, format: double } + speed: { type: number, format: double } + heading: { type: number, format: double } + CallTokenRequest: + type: object + required: [receiverId] + properties: + receiverId: { type: integer, format: int64 } +paths: + /auth/ping: + get: + security: [] + responses: + "200": { description: Server health, content: { application/json: { schema: { $ref: "#/components/schemas/ApiResponse" } } } } + /auth/register: + post: + security: [] + requestBody: + required: true + content: + application/json: + schema: { $ref: "#/components/schemas/RegisterRequest" } + responses: + "200": { description: Registered } + /auth/login: + post: + security: [] + requestBody: + required: true + content: + application/json: + schema: { $ref: "#/components/schemas/LoginRequest" } + responses: + "200": { description: Logged in } + /auth/refresh: + post: + security: [] + responses: + "200": { description: Token refreshed } + /auth/logout: + post: + responses: + "200": { description: Logged out } + /auth/fcm-token: + put: + responses: + "200": { description: FCM token updated } + /shared/pairing/invite: + post: + requestBody: + required: true + content: + application/json: + schema: { $ref: "#/components/schemas/PairingInviteRequest" } + responses: + "200": { description: Invite sent } + /shared/pairing/respond: + post: + requestBody: + required: true + content: + application/json: + schema: { $ref: "#/components/schemas/PairingRespondRequest" } + responses: + "200": { description: Invite responded } + /shared/pairing/unpair: + delete: + responses: + "200": { description: Pairing removed } + /shared/pairing/status: + get: + responses: + "200": { description: Pairing status } + /shared/call/token: + post: + requestBody: + required: true + content: + application/json: + schema: { $ref: "#/components/schemas/CallTokenRequest" } + responses: + "200": { description: Agora token generated } + /shared/call/notify: + post: + responses: + "200": { description: Incoming call notification sent } + /shared/call/end: + post: + responses: + "200": { description: Call end notification sent } + /user/profile: + get: + responses: + "200": { description: Current user profile } + /user/settings: + get: + responses: + "200": { description: User settings } + put: + responses: + "200": { description: User settings updated } + /user/voice-commands: + get: + responses: + "200": { description: Voice commands } + /user/shortcuts: + get: + responses: + "200": { description: Hardware shortcuts } + put: + responses: + "200": { description: Hardware shortcut updated } + /user/ai-config: + get: + responses: + "200": { description: AI config } + /user/location: + post: + requestBody: + content: + application/json: + schema: { $ref: "#/components/schemas/LocationUpdateRequest" } + responses: + "200": { description: Location stored } + /user/obstacle: + post: + responses: + "200": { description: Obstacle stored } + /user/sos: + post: + responses: + "200": { description: SOS triggered } + /user/activity-logs: + get: + responses: + "200": { description: User activity logs } + /user/notifications: + get: + responses: + "200": { description: User notifications } + /user/notifications/unread-count: + get: + responses: + "200": { description: Unread notification count } + /user/notifications/mark-all-read: + put: + responses: + "200": { description: All notifications marked read } + /user/notifications/{id}/read: + put: + parameters: + - in: path + name: id + required: true + schema: { type: integer, format: int64 } + responses: + "200": { description: One notification marked read } + /user/walkguide/start: + post: + responses: + "200": { description: WalkGuide start logged } + /user/walkguide/stop: + post: + responses: + "200": { description: WalkGuide stop logged } + /guardian/dashboard: + get: + responses: + "200": { description: Guardian dashboard } + /guardian/user-location: + get: + responses: + "200": { description: Paired user latest location } + /guardian/location-history: + get: + responses: + "200": { description: Paired user location history } + /guardian/activity-logs: + get: + responses: + "200": { description: Paired user activity logs } + /guardian/obstacle-logs: + get: + responses: + "200": { description: Paired user obstacle logs } + /guardian/notifications/send: + post: + responses: + "200": { description: Notification sent to paired user } + /guardian/sos-events: + get: + responses: + "200": { description: Paired user SOS events } + /guardian/sos/{id}/acknowledge: + put: + parameters: + - in: path + name: id + required: true + schema: { type: integer, format: int64 } + responses: + "200": { description: SOS acknowledged } + /guardian/ai-config: + get: + responses: + "200": { description: Paired user AI config } + put: + responses: + "200": { description: Paired user AI config updated } + /guardian/voice-commands: + get: + responses: + "200": { description: Paired user voice commands } + put: + responses: + "200": { description: Paired user voice command updated } + /guardian/shortcuts: + get: + responses: + "200": { description: Paired user shortcuts } + /guardian/geofence: + get: + responses: + "200": { description: Geofence config } + put: + responses: + "200": { description: Geofence config updated } + /guardian/user-settings: + get: + responses: + "200": { description: Paired user settings } + put: + responses: + "200": { description: Paired user settings updated } diff --git a/walkguide-mobile/walkguide_app/lib/core/services/call_service.dart b/walkguide-mobile/walkguide_app/lib/core/services/call_service.dart index 3926e82..b26c91b 100644 --- a/walkguide-mobile/walkguide_app/lib/core/services/call_service.dart +++ b/walkguide-mobile/walkguide_app/lib/core/services/call_service.dart @@ -10,23 +10,68 @@ class CallService { CallService(this._apiClient); - Future?> requestToken(String channelName) async { - final res = await _apiClient.dio.post('/shared/call/token', data: {'channelName': channelName}); + Future?> requestToken({required int receiverId}) async { + final res = await _apiClient.dio.post( + '/shared/call/token', + data: {'receiverId': receiverId}, + ); final data = res.data['data']; return data is Map ? data : null; } - Future notifyIncomingCall({required int receiverId, required String channelName}) async { + Future getPairedReceiverId() async { + final res = await _apiClient.dio.get('/pairing/status'); + final data = res.data['data']; + if (data is! Map) return null; + final id = data['pairedWithId']; + return id is num ? id.toInt() : int.tryParse(id?.toString() ?? ''); + } + + Future notifyIncomingCall({ + required int receiverId, + required String channelName, + String? agoraToken, + int receiverUid = 0, + }) async { await _apiClient.dio.post('/shared/call/notify', data: { 'receiverId': receiverId, 'channelName': channelName, + 'agoraToken': agoraToken, + 'receiverUid': receiverUid, }); } - Future joinChannel({required String channelName, int uid = 0}) async { + Future callPairedUser({int uid = 0}) async { + final receiverId = await getPairedReceiverId(); + if (receiverId == null) return false; + + final tokenData = await requestToken(receiverId: receiverId); + final channelName = tokenData?['channelName']?.toString(); + final token = tokenData?['token']?.toString(); + if (channelName == null || channelName.isEmpty) return false; + + final joined = await joinChannel( + channelName: channelName, + token: token, + uid: uid, + ); + if (joined) { + await notifyIncomingCall( + receiverId: receiverId, + channelName: channelName, + agoraToken: token, + receiverUid: uid, + ); + } + return joined; + } + + Future joinChannel({ + required String channelName, + String? token, + int uid = 0, + }) async { try { - final tokenData = await requestToken(channelName); - final token = tokenData?['token']?.toString(); _engine ??= createAgoraRtcEngine(); await _engine!.initialize(const RtcEngineContext(appId: AppConstants.agoraAppId)); await _engine!.enableAudio(); diff --git a/walkguide-mobile/walkguide_app/lib/features/activity_log/activity_log_screen.dart b/walkguide-mobile/walkguide_app/lib/features/activity_log/activity_log_screen.dart index a24dfd9..99a74cc 100644 --- a/walkguide-mobile/walkguide_app/lib/features/activity_log/activity_log_screen.dart +++ b/walkguide-mobile/walkguide_app/lib/features/activity_log/activity_log_screen.dart @@ -148,7 +148,7 @@ class _ActivityLogScreenState extends State { onSelected: (_) { setState(() => _applyFilter(f)); }, - selectedColor: AppColors.primary.withOpacity(0.15), + selectedColor: AppColors.primary.withValues(alpha: 0.15), checkmarkColor: AppColors.primary, labelStyle: TextStyle( color: selected ? AppColors.primary : AppColors.muted, @@ -232,7 +232,7 @@ class _LogCard extends StatelessWidget { width: 36, height: 36, decoration: BoxDecoration( - color: meta.color.withOpacity(0.12), + color: meta.color.withValues(alpha: 0.12), shape: BoxShape.circle, ), child: Icon(meta.icon, color: meta.color, size: 18), diff --git a/walkguide-mobile/walkguide_app/lib/features/auth/splash_screen.dart b/walkguide-mobile/walkguide_app/lib/features/auth/splash_screen.dart index 834593d..517cb94 100644 --- a/walkguide-mobile/walkguide_app/lib/features/auth/splash_screen.dart +++ b/walkguide-mobile/walkguide_app/lib/features/auth/splash_screen.dart @@ -91,7 +91,7 @@ class _SplashScreenState extends State width: 100, height: 100, decoration: BoxDecoration( - color: Colors.white.withOpacity(0.12), + color: Colors.white.withValues(alpha: 0.12), borderRadius: BorderRadius.circular(28), ), child: const Icon( diff --git a/walkguide-mobile/walkguide_app/lib/features/call/call_screen.dart b/walkguide-mobile/walkguide_app/lib/features/call/call_screen.dart index 554e7fd..881f12d 100644 --- a/walkguide-mobile/walkguide_app/lib/features/call/call_screen.dart +++ b/walkguide-mobile/walkguide_app/lib/features/call/call_screen.dart @@ -1,4 +1,4 @@ -// ignore_for_file: use_build_context_synchronously +// ignore_for_file: use_build_context_synchronously, prefer_const_constructors // lib/features/call/call_screen.dart // // CallScreen — user memanggil Guardian via Agora @@ -34,8 +34,6 @@ class CallScreen extends StatefulWidget { class _CallScreenState extends State with SingleTickerProviderStateMixin { - static const _channelName = 'walkguide-call'; - _CallPhase _phase = _CallPhase.calling; bool _muted = false; bool _speakerOn = true; @@ -61,8 +59,7 @@ class _CallScreenState extends State } Future _startCall() async { - final joined = - await sl().joinChannel(channelName: _channelName); + final joined = await sl().callPairedUser(); if (!mounted) return; diff --git a/walkguide-mobile/walkguide_app/lib/features/home/presentation/guardian_dashboard_screen.dart b/walkguide-mobile/walkguide_app/lib/features/home/presentation/guardian_dashboard_screen.dart index 4d11621..dfe0c7c 100644 --- a/walkguide-mobile/walkguide_app/lib/features/home/presentation/guardian_dashboard_screen.dart +++ b/walkguide-mobile/walkguide_app/lib/features/home/presentation/guardian_dashboard_screen.dart @@ -1,6 +1,5 @@ -// ignore_for_file: use_build_context_synchronously, deprecated_member_use +// ignore_for_file: use_build_context_synchronously, deprecated_member_use, prefer_const_constructors import 'dart:async'; -import 'dart:math' as math; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; @@ -36,7 +35,6 @@ class _GuardianDashboardScreenState extends State bool _loading = true; String? _error; String _guardianName = 'Guardian'; - int _refreshCount = 0; // ── Live location (WebSocket) ──────────────────────────────────────────────── LatLng? _liveLatLng; @@ -156,7 +154,6 @@ class _GuardianDashboardScreenState extends State _liveLatLng = newLatLng; } _loading = false; - _refreshCount++; }); // If SOS pending, start flash @@ -672,7 +669,7 @@ class _GuardianDashboardScreenState extends State Border.all(color: const Color(0xFFE2E8F0), width: 1), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.04), + color: Colors.black.withValues(alpha: 0.04), blurRadius: 12, offset: const Offset(0, 2)), ], @@ -708,7 +705,7 @@ class _GuardianDashboardScreenState extends State decoration: BoxDecoration( shape: BoxShape.circle, color: const Color(0xFF1A56DB) - .withOpacity(0.25 * _pulseAnim.value), + .withValues(alpha: 0.25 * _pulseAnim.value), ), ), Container( @@ -760,11 +757,11 @@ class _GuardianDashboardScreenState extends State padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 5), decoration: BoxDecoration( - color: Colors.white.withOpacity(0.92), + color: Colors.white.withValues(alpha: 0.92), borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.1), + color: Colors.black.withValues(alpha: 0.1), blurRadius: 8), ], ), @@ -801,7 +798,7 @@ class _GuardianDashboardScreenState extends State horizontal: 10, vertical: 5), decoration: BoxDecoration( color: - const Color(0xFF1A56DB).withOpacity(0.9), + const Color(0xFF1A56DB).withValues(alpha: 0.9), borderRadius: BorderRadius.circular(20), ), child: Text('Buka Peta', @@ -823,11 +820,11 @@ class _GuardianDashboardScreenState extends State padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 6), decoration: BoxDecoration( - color: Colors.white.withOpacity(0.92), + color: Colors.white.withValues(alpha: 0.92), borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.08), + color: Colors.black.withValues(alpha: 0.08), blurRadius: 6), ], ), @@ -859,7 +856,7 @@ class _GuardianDashboardScreenState extends State border: Border.all(color: const Color(0xFFE2E8F0)), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.04), + color: Colors.black.withValues(alpha: 0.04), blurRadius: 12, offset: const Offset(0, 2)), ], @@ -872,7 +869,7 @@ class _GuardianDashboardScreenState extends State CircleAvatar( radius: 20, backgroundColor: - const Color(0xFF1A56DB).withOpacity(0.1), + const Color(0xFF1A56DB).withValues(alpha: 0.1), child: Text( d.userName.isNotEmpty ? d.userName[0].toUpperCase() @@ -1051,7 +1048,7 @@ class _GuardianDashboardScreenState extends State border: Border.all(color: const Color(0xFFE2E8F0)), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.04), + color: Colors.black.withValues(alpha: 0.04), blurRadius: 12, offset: const Offset(0, 2)), ], @@ -1357,7 +1354,7 @@ class _KpiCard extends StatelessWidget { width: 1), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.03), + color: Colors.black.withValues(alpha: 0.03), blurRadius: 8), ], ), @@ -1421,7 +1418,7 @@ class _ActivityTile extends StatelessWidget { width: 32, height: 32, decoration: BoxDecoration( - color: cfg.color.withOpacity(0.1), + color: cfg.color.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), ), child: Icon(cfg.icon, size: 16, color: cfg.color), @@ -1485,7 +1482,7 @@ class _QuickActionCard extends StatelessWidget { width: 28, height: 28, decoration: BoxDecoration( - color: item.color.withOpacity(0.1), + color: item.color.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(7), ), child: Icon(item.icon, @@ -1527,7 +1524,7 @@ class _SosBadge extends StatelessWidget { borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( - color: const Color(0xFFDC2626).withOpacity(0.4), + color: const Color(0xFFDC2626).withValues(alpha: 0.4), blurRadius: 8, spreadRadius: 1), ], diff --git a/walkguide-mobile/walkguide_app/lib/features/navigation_mode/navigation_mode_screen.dart b/walkguide-mobile/walkguide_app/lib/features/navigation_mode/navigation_mode_screen.dart index 6d406b6..05dc4c6 100644 --- a/walkguide-mobile/walkguide_app/lib/features/navigation_mode/navigation_mode_screen.dart +++ b/walkguide-mobile/walkguide_app/lib/features/navigation_mode/navigation_mode_screen.dart @@ -100,7 +100,7 @@ class _NavState extends ChangeNotifier { 'heading': pos.heading, }) .timeout(const Duration(seconds: 5)) - .catchError((_) => null); + .ignore(); } // ── search Nominatim ───────────────────────────────────────────────────── diff --git a/walkguide-mobile/walkguide_app/lib/features/notifications/notification_screen.dart b/walkguide-mobile/walkguide_app/lib/features/notifications/notification_screen.dart index 9ef05e7..3da509f 100644 --- a/walkguide-mobile/walkguide_app/lib/features/notifications/notification_screen.dart +++ b/walkguide-mobile/walkguide_app/lib/features/notifications/notification_screen.dart @@ -4,10 +4,8 @@ import 'dart:async'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import '../../app/injection_container.dart'; -import '../../core/constants/app_constants.dart'; import '../../core/network/api_client.dart'; import '../../core/services/tts_service.dart'; import '../../core/theme/app_colors.dart'; @@ -254,13 +252,13 @@ class _NotifCard extends StatelessWidget { borderRadius: BorderRadius.circular(14), border: Border.all( color: unread - ? AppColors.primary.withOpacity(0.3) + ? AppColors.primary.withValues(alpha: 0.3) : const Color(0xFFE2E8F0), width: unread ? 1.5 : 1, ), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.04), + color: Colors.black.withValues(alpha: 0.04), blurRadius: 8, offset: const Offset(0, 2), ), @@ -279,8 +277,8 @@ class _NotifCard extends StatelessWidget { height: 36, decoration: BoxDecoration( color: isVoice - ? AppColors.success.withOpacity(0.12) - : AppColors.primary.withOpacity(0.12), + ? AppColors.success.withValues(alpha: 0.12) + : AppColors.primary.withValues(alpha: 0.12), borderRadius: BorderRadius.circular(10), ), child: Icon( diff --git a/walkguide-mobile/walkguide_app/lib/features/pairing/pairing_screens.dart b/walkguide-mobile/walkguide_app/lib/features/pairing/pairing_screens.dart index 27f0fa6..c70745d 100644 --- a/walkguide-mobile/walkguide_app/lib/features/pairing/pairing_screens.dart +++ b/walkguide-mobile/walkguide_app/lib/features/pairing/pairing_screens.dart @@ -1,10 +1,9 @@ -// ignore_for_file: use_build_context_synchronously, deprecated_member_use +// ignore_for_file: use_build_context_synchronously, deprecated_member_use, prefer_const_constructors import 'dart:async'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; import '../../app/injection_container.dart'; import '../../core/network/api_client.dart'; @@ -382,10 +381,8 @@ class _Page extends StatelessWidget { final String title; final String? subtitle; final Widget child; - final List? actions; - const _Page( - {required this.title, required this.child, this.subtitle, this.actions}); + const _Page({required this.title, required this.child, this.subtitle}); @override Widget build(BuildContext context) { @@ -412,7 +409,6 @@ class _Page extends StatelessWidget { ], ), ), - ...?actions, ], ), const SizedBox(height: 16), diff --git a/walkguide-mobile/walkguide_app/lib/features/screens.dart b/walkguide-mobile/walkguide_app/lib/features/screens.dart index cdbafdb..b709804 100644 --- a/walkguide-mobile/walkguide_app/lib/features/screens.dart +++ b/walkguide-mobile/walkguide_app/lib/features/screens.dart @@ -2168,10 +2168,10 @@ class _MapStatus extends StatelessWidget { Widget build(BuildContext context) { return DecoratedBox( decoration: BoxDecoration( - color: Colors.white.withOpacity(0.92), + color: Colors.white.withValues(alpha: 0.92), borderRadius: BorderRadius.circular(12), boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.12), blurRadius: 18) + BoxShadow(color: Colors.black.withValues(alpha: 0.12), blurRadius: 18) ], ), child: Padding( @@ -2251,7 +2251,7 @@ class _Pill extends StatelessWidget { Widget build(BuildContext context) { return DecoratedBox( decoration: BoxDecoration( - color: color.withOpacity(0.16), + color: color.withValues(alpha: 0.16), borderRadius: BorderRadius.circular(999), border: Border.all(color: color)), child: Padding( diff --git a/walkguide-mobile/walkguide_app/lib/features/settings/user_settings_screen.dart b/walkguide-mobile/walkguide_app/lib/features/settings/user_settings_screen.dart index 0527855..a686376 100644 --- a/walkguide-mobile/walkguide_app/lib/features/settings/user_settings_screen.dart +++ b/walkguide-mobile/walkguide_app/lib/features/settings/user_settings_screen.dart @@ -1,4 +1,4 @@ -// ignore_for_file: use_build_context_synchronously +// ignore_for_file: use_build_context_synchronously, prefer_const_constructors, deprecated_member_use // lib/features/settings/user_settings_screen.dart import 'dart:async'; @@ -146,10 +146,10 @@ class _UserSettingsScreenState extends State { Future _logout() async { await sl().clearAll(); context.read().clearSession(); - unawaited(_api + _api .post('/auth/logout') .timeout(const Duration(seconds: 3)) - .catchError((_) => null)); + .ignore(); if (mounted) context.go('/login'); } diff --git a/walkguide-mobile/walkguide_app/lib/features/sos/sos_screen.dart b/walkguide-mobile/walkguide_app/lib/features/sos/sos_screen.dart index e6631dc..6a142b9 100644 --- a/walkguide-mobile/walkguide_app/lib/features/sos/sos_screen.dart +++ b/walkguide-mobile/walkguide_app/lib/features/sos/sos_screen.dart @@ -1,12 +1,11 @@ // lib/features/sos/sos_screen.dart -// ignore_for_file: use_build_context_synchronously +// ignore_for_file: use_build_context_synchronously, prefer_const_constructors, curly_braces_in_flow_control_structures import 'dart:async'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:go_router/go_router.dart'; import '../../app/injection_container.dart'; import '../../core/network/api_client.dart'; @@ -326,7 +325,7 @@ class _SosButton extends StatelessWidget { backgroundColor: active ? const Color(0xFFB91C1C) : const Color(0xFFDC2626), elevation: active ? 12 : 4, - shadowColor: const Color(0xFFDC2626).withOpacity(0.5), + shadowColor: const Color(0xFFDC2626).withValues(alpha: 0.5), ), onPressed: onPressed, child: Column( @@ -363,7 +362,7 @@ class _SendingIndicator extends StatelessWidget { dimension: 200, child: DecoratedBox( decoration: BoxDecoration( - color: const Color(0xFFDC2626).withOpacity(0.15), + color: const Color(0xFFDC2626).withValues(alpha: 0.15), shape: BoxShape.circle, border: Border.all(color: const Color(0xFFDC2626), width: 3), ), @@ -505,7 +504,7 @@ class _SosEventTile extends StatelessWidget { Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: statusColor.withOpacity(0.1), + color: statusColor.withValues(alpha: 0.1), shape: BoxShape.circle, ), child: Icon(statusIcon, color: statusColor, size: 20), @@ -521,7 +520,7 @@ class _SosEventTile extends StatelessWidget { padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 2), decoration: BoxDecoration( - color: statusColor.withOpacity(0.1), + color: statusColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(99), ), child: Text( diff --git a/walkguide-mobile/walkguide_app/lib/features/walk_guide/walk_guide_screen.dart b/walkguide-mobile/walkguide_app/lib/features/walk_guide/walk_guide_screen.dart index 713d55d..9df5c09 100644 --- a/walkguide-mobile/walkguide_app/lib/features/walk_guide/walk_guide_screen.dart +++ b/walkguide-mobile/walkguide_app/lib/features/walk_guide/walk_guide_screen.dart @@ -466,7 +466,7 @@ class _Pill extends StatelessWidget { Widget build(BuildContext context) { return DecoratedBox( decoration: BoxDecoration( - color: color.withOpacity(0.16), + color: color.withValues(alpha: 0.16), borderRadius: BorderRadius.circular(999), border: Border.all(color: color)), child: Padding( @@ -506,12 +506,10 @@ class _EmptyPanel extends StatelessWidget { final IconData icon; final String title; final String message; - final Widget? action; const _EmptyPanel( {required this.icon, required this.title, - required this.message, - this.action}); + required this.message}); @override Widget build(BuildContext context) { @@ -533,10 +531,6 @@ class _EmptyPanel extends StatelessWidget { const TextStyle(fontWeight: FontWeight.w800, fontSize: 18)), const SizedBox(height: 6), Text(message, textAlign: TextAlign.center), - if (action != null) ...[ - const SizedBox(height: 12), - action!, - ], ], ), ); diff --git a/walkguide-mobile/walkguide_app/pubspec.lock b/walkguide-mobile/walkguide_app/pubspec.lock index 6a507b7..a5f4313 100644 --- a/walkguide-mobile/walkguide_app/pubspec.lock +++ b/walkguide-mobile/walkguide_app/pubspec.lock @@ -800,7 +800,7 @@ packages: source: sdk version: "0.0.0" intl: - dependency: transitive + dependency: "direct main" description: name: intl sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" @@ -947,10 +947,10 @@ packages: dependency: transitive description: name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.16.0" mgrs_dart: dependency: transitive description: @@ -1592,26 +1592,26 @@ packages: dependency: transitive description: name: test - sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7" + sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb" url: "https://pub.dev" source: hosted - version: "1.26.3" + version: "1.26.2" test_api: dependency: transitive description: name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.7" + version: "0.7.6" test_core: dependency: transitive description: name: test_core - sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0" + sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a" url: "https://pub.dev" source: hosted - version: "0.6.12" + version: "0.6.11" tflite_flutter: dependency: "direct main" description: diff --git a/walkguide-mobile/walkguide_app/pubspec.yaml b/walkguide-mobile/walkguide_app/pubspec.yaml index 0be6260..deeaed7 100644 --- a/walkguide-mobile/walkguide_app/pubspec.yaml +++ b/walkguide-mobile/walkguide_app/pubspec.yaml @@ -75,6 +75,7 @@ dependencies: cupertino_icons: ^1.0.8 cached_network_image: ^3.3.1 shimmer: ^3.0.0 + intl: ^0.20.2 # STOMP client untuk WebSocket stomp_dart_client: ^2.1.0 diff --git a/walkguide-mobile/walkguide_app/test/integration_test/app_flow_test.dart b/walkguide-mobile/walkguide_app/test/integration_test/app_flow_test.dart index 008684a..58c9943 100644 --- a/walkguide-mobile/walkguide_app/test/integration_test/app_flow_test.dart +++ b/walkguide-mobile/walkguide_app/test/integration_test/app_flow_test.dart @@ -1,5 +1,6 @@ -// integration_test/app_flow_test.dart -// +// integration_test/app_flow_test.dart +// ignore_for_file: prefer_const_constructors, no_leading_underscores_for_local_identifiers +// // Integration Tests (E2E) untuk WalkGuide App — 3 alur utama: // Flow 1: Login → Dashboard → Logout // Flow 2: Login → WalkGuide → Start → Stop → SOS diff --git a/walkguide-mobile/walkguide_app/test/unit/obstacle_analyzer_test.dart b/walkguide-mobile/walkguide_app/test/unit/obstacle_analyzer_test.dart index 56b43cc..fd980ea 100644 --- a/walkguide-mobile/walkguide_app/test/unit/obstacle_analyzer_test.dart +++ b/walkguide-mobile/walkguide_app/test/unit/obstacle_analyzer_test.dart @@ -1,5 +1,6 @@ -// test/unit/obstacle_analyzer_test.dart -// +// test/unit/obstacle_analyzer_test.dart +// ignore_for_file: prefer_const_declarations +// // Unit test untuk ObstacleAnalyzer — logika AI direction & distance. // Jalankan: flutter test test/unit/obstacle_analyzer_test.dart // diff --git a/walkguide-mobile/walkguide_app/test/unit/voice_command_handler_test.dart b/walkguide-mobile/walkguide_app/test/unit/voice_command_handler_test.dart index a2feb26..b08dcae 100644 --- a/walkguide-mobile/walkguide_app/test/unit/voice_command_handler_test.dart +++ b/walkguide-mobile/walkguide_app/test/unit/voice_command_handler_test.dart @@ -51,14 +51,14 @@ class _FakeStt { // VoiceCommandHandler (mirror dari project) typedef CommandCallback = void Function(VoiceCommandKey key); -class VoiceCommandHandler { +class _VoiceCommandHandler { final _FakeStt _stt; final _FakeTts _tts; List _commands = []; CommandCallback? onCommand; - VoiceCommandHandler(this._stt, this._tts); + _VoiceCommandHandler(this._stt, this._tts); void loadCommands(List commands) { _commands = commands; @@ -137,7 +137,7 @@ class VoiceCommandHandler { // ---------- Tests ---------- void main() { - late VoiceCommandHandler handler; + late _VoiceCommandHandler handler; late _FakeStt fakeStt; late _FakeTts fakeTts; @@ -146,7 +146,7 @@ void main() { setUp(() { fakeStt = _FakeStt(); fakeTts = _FakeTts(); - handler = VoiceCommandHandler(fakeStt, fakeTts); + handler = _VoiceCommandHandler(fakeStt, fakeTts); dispatchedCommands.clear(); handler.loadDefaultCommands(); handler.onCommand = dispatchedCommands.add; diff --git a/walkguide-mobile/walkguide_app/test/widget/login_screen_test.dart b/walkguide-mobile/walkguide_app/test/widget/login_screen_test.dart index 49f8f54..e3e7770 100644 --- a/walkguide-mobile/walkguide_app/test/widget/login_screen_test.dart +++ b/walkguide-mobile/walkguide_app/test/widget/login_screen_test.dart @@ -151,8 +151,6 @@ class _StubLoginScreenState extends State<_StubLoginScreen> { } // Workaround untuk SizedBox(height(12)) yang error — gunakan helper -SizedBox _gap(double h) => SizedBox(height: h); - // --------------------------------------------------------------------------- // Tests // --------------------------------------------------------------------------- @@ -397,4 +395,4 @@ void main() { }); }); }); -} \ No newline at end of file +} diff --git a/walkguide-mobile/walkguide_app/test/widget/manual_screen_test.dart b/walkguide-mobile/walkguide_app/test/widget/manual_screen_test.dart index e3215e0..ceac807 100644 --- a/walkguide-mobile/walkguide_app/test/widget/manual_screen_test.dart +++ b/walkguide-mobile/walkguide_app/test/widget/manual_screen_test.dart @@ -1,5 +1,6 @@ -// test/widget/manual_screen_test.dart -// +// test/widget/manual_screen_test.dart +// ignore_for_file: prefer_const_constructors +// // Widget tests untuk ManualScreen — halaman panduan perintah suara. // Jalankan: flutter test test/widget/manual_screen_test.dart diff --git a/walkguide-mobile/walkguide_app/test/widget/notification_screen_test.dart b/walkguide-mobile/walkguide_app/test/widget/notification_screen_test.dart index 38803a6..0d20977 100644 --- a/walkguide-mobile/walkguide_app/test/widget/notification_screen_test.dart +++ b/walkguide-mobile/walkguide_app/test/widget/notification_screen_test.dart @@ -1,5 +1,6 @@ -// test/widget/notification_screen_test.dart -// +// test/widget/notification_screen_test.dart +// ignore_for_file: prefer_const_constructors +// // Widget tests untuk NotificationScreen — menampilkan notifikasi dari Guardian. // Jalankan: flutter test test/widget/notification_screen_test.dart diff --git a/walkguide-mobile/walkguide_app/test/widget/sos_screen_test.dart b/walkguide-mobile/walkguide_app/test/widget/sos_screen_test.dart index 29e7916..461fc17 100644 --- a/walkguide-mobile/walkguide_app/test/widget/sos_screen_test.dart +++ b/walkguide-mobile/walkguide_app/test/widget/sos_screen_test.dart @@ -167,7 +167,7 @@ class _StubSosScreenState extends State<_StubSosScreen> { shape: BoxShape.circle, boxShadow: [ BoxShadow( - color: Colors.red.withOpacity(0.4), + color: Colors.red.withValues(alpha: 0.4), blurRadius: 20, spreadRadius: 4, ), diff --git a/walkguide-mobile/walkguide_app/test/widget/walk_guide_screen_test.dart b/walkguide-mobile/walkguide_app/test/widget/walk_guide_screen_test.dart index 52f821c..1e92493 100644 --- a/walkguide-mobile/walkguide_app/test/widget/walk_guide_screen_test.dart +++ b/walkguide-mobile/walkguide_app/test/widget/walk_guide_screen_test.dart @@ -1,5 +1,6 @@ -// test/widget/walk_guide_screen_test.dart -// +// test/widget/walk_guide_screen_test.dart +// ignore_for_file: prefer_const_constructors, prefer_const_literals_to_create_immutables +// // Widget tests untuk WalkGuideScreen — layar utama navigasi tunanetra. // Jalankan: flutter test test/widget/walk_guide_screen_test.dart // @@ -264,7 +265,7 @@ class _DetectionOverlay extends StatelessWidget { margin: const EdgeInsets.symmetric(horizontal: 16), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( - color: detection.isAlert ? Colors.red.withOpacity(0.85) : Colors.black87, + color: detection.isAlert ? Colors.red.withValues(alpha: 0.85) : Colors.black87, borderRadius: BorderRadius.circular(8), ), child: Text( @@ -578,4 +579,4 @@ void main() { }); }); }); -} \ No newline at end of file +}