Initial commit
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
3
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
1
.idea/.name
generated
Normal file
@ -0,0 +1 @@
|
||||
smart119
|
22
.idea/androidTestResultsUserPreferences.xml
generated
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AndroidTestResultsUserPreferences">
|
||||
<option name="androidTestResultsTableState">
|
||||
<map>
|
||||
<entry key="28629151">
|
||||
<value>
|
||||
<AndroidTestResultsTableState>
|
||||
<option name="preferredColumnWidths">
|
||||
<map>
|
||||
<entry key="Duration" value="90" />
|
||||
<entry key="Tests" value="360" />
|
||||
<entry key="samsung SM-P615N" value="120" />
|
||||
</map>
|
||||
</option>
|
||||
</AndroidTestResultsTableState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
123
.idea/codeStyles/Project.xml
generated
Normal file
@ -0,0 +1,123 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<JetCodeStyleSettings>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
<arrangement>
|
||||
<rules>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:android</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:id</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>style</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
6
.idea/compiler.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="21" />
|
||||
</component>
|
||||
</project>
|
21
.idea/deploymentTargetSelector.xml
generated
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetSelector">
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2025-03-17T01:37:05.045672200Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\pj\.android\avd\Galaxy_Tab_S6_API_35.avd" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
<SelectionState runConfigName="All Tests">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
</SelectionState>
|
||||
</selectionStates>
|
||||
</component>
|
||||
</project>
|
20
.idea/gradle.xml
generated
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveExternalAnnotations" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
6
.idea/kotlinc.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.9.24" />
|
||||
</component>
|
||||
</project>
|
10
.idea/migrations.xml
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectMigrations">
|
||||
<option name="MigrateToGradleLocalJavaHome">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
9
.idea/misc.xml
generated
Normal file
@ -0,0 +1,9 @@
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
17
.idea/runConfigurations.xml
generated
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
1
app/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
89
app/build.gradle.kts
Normal file
@ -0,0 +1,89 @@
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.example.smart119"
|
||||
compileSdk = 34
|
||||
|
||||
signingConfigs {
|
||||
create("release") {
|
||||
storeFile = file("D:\\work\\Android\\release\\release.jks") // 키스토어 파일 경로
|
||||
storePassword = "rnrmq1!" // 키스토어 비밀번호
|
||||
keyAlias = "release_key" // 키 별칭
|
||||
keyPassword = "admin123#" // 키 비밀번호
|
||||
}
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.example.smart119"
|
||||
minSdk = 30
|
||||
targetSdk = 34
|
||||
versionCode = 2
|
||||
versionName = "2.1"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
buildConfigField("String", "APP_VERSION", "\"${versionName}\"")
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
isDebuggable = true // ✅ 디버깅 활성화
|
||||
}
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
signingConfig = signingConfigs.getByName("release") // 🔹 릴리즈 서명 추가
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.appcompat)
|
||||
implementation(libs.material)
|
||||
implementation(libs.androidx.constraintlayout)
|
||||
implementation(libs.androidx.navigation.fragment.ktx)
|
||||
implementation(libs.androidx.navigation.ui.ktx)
|
||||
implementation(libs.androidx.databinding.runtime)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
|
||||
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
||||
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
|
||||
// Gson 라이브러리
|
||||
implementation("com.google.code.gson:gson:2.8.9")
|
||||
|
||||
// RxJava Core 라이브러리
|
||||
implementation("io.reactivex.rxjava3:rxjava:3.1.5")
|
||||
// RxAndroid (Android-specific extensions)
|
||||
implementation("io.reactivex.rxjava3:rxandroid:3.0.2")
|
||||
|
||||
// gps, Fused Location Provider API
|
||||
implementation("com.google.android.gms:play-services-location:21.0.1")
|
||||
implementation("com.google.android.gms:play-services-location:21.0.1")
|
||||
|
||||
//view pager2
|
||||
implementation("androidx.viewpager2:viewpager2:1.1.0")
|
||||
}
|
21
app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
BIN
app/release/baselineProfiles/0/app-release.dm
Normal file
BIN
app/release/baselineProfiles/1/app-release.dm
Normal file
37
app/release/output-metadata.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"version": 3,
|
||||
"artifactType": {
|
||||
"type": "APK",
|
||||
"kind": "Directory"
|
||||
},
|
||||
"applicationId": "com.example.smart119",
|
||||
"variantName": "release",
|
||||
"elements": [
|
||||
{
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"attributes": [],
|
||||
"versionCode": 2,
|
||||
"versionName": "2.1",
|
||||
"outputFile": "app-release.apk"
|
||||
}
|
||||
],
|
||||
"elementType": "File",
|
||||
"baselineProfiles": [
|
||||
{
|
||||
"minApi": 28,
|
||||
"maxApi": 30,
|
||||
"baselineProfiles": [
|
||||
"baselineProfiles/1/app-release.dm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"minApi": 31,
|
||||
"maxApi": 2147483647,
|
||||
"baselineProfiles": [
|
||||
"baselineProfiles/0/app-release.dm"
|
||||
]
|
||||
}
|
||||
],
|
||||
"minSdkVersionForDexing": 30
|
||||
}
|
BIN
app/release/smart119_2_1.apk
Normal file
@ -0,0 +1,24 @@
|
||||
package com.example.smart119
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.example.smart119", appContext.packageName)
|
||||
}
|
||||
}
|
42
app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
<application
|
||||
android:name="com.example.smart119.App"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Smart119"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:windowSoftInputMode="adjustPan"
|
||||
android:theme="@style/Theme.Smart119">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".LocationService"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="location" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
BIN
app/src/main/ic_launcher-playstore.png
Normal file
After Width: | Height: | Size: 163 KiB |
183
app/src/main/java/com/example/smart119/API_Helper.kt
Normal file
@ -0,0 +1,183 @@
|
||||
package com.example.smart119
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.widget.Toast
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonObject
|
||||
import kotlin.math.*
|
||||
|
||||
object API_Helper {
|
||||
|
||||
fun ETA_SEC_TO_STRING(duration:Int):String {
|
||||
var ret_string = "";
|
||||
val minutes = duration / 60 // 분 계산
|
||||
val seconds = duration % 60 // 초 계산
|
||||
if (duration < 60) {
|
||||
ret_string = "${seconds}초"
|
||||
}
|
||||
else {
|
||||
ret_string = "${minutes}분 ${seconds}초"
|
||||
}
|
||||
|
||||
return ret_string
|
||||
}
|
||||
|
||||
fun DISTANCE_FORMAT_METER_TO_KM(meters: String): String {
|
||||
val km = meters.toDoubleOrNull()?.div(1000) ?: return "Invalid input"
|
||||
return String.format("%.2f km", km)
|
||||
}
|
||||
|
||||
|
||||
fun lidar_levelState(level:Int): String {
|
||||
return when (level) {
|
||||
-1 -> "정보 없음"
|
||||
0 -> "원활"
|
||||
1 -> "보통"
|
||||
2 -> "약간 혼잡"
|
||||
3 -> "혼잡"
|
||||
4 -> "매우 혼잡"
|
||||
else -> "잘못된 레벨"
|
||||
}
|
||||
}
|
||||
fun lidar_levelState_Color(level:String):String {
|
||||
return when (level) {
|
||||
"정보 없음" -> "#87CEEB"
|
||||
"원활" -> "#4CAF50"
|
||||
"보통" -> "#FFEB3B"
|
||||
"약간 혼잡" -> "#FF9800"
|
||||
"혼잡" -> "#F44336"
|
||||
"매우 혼잡" -> "#B71C1C"
|
||||
else -> "#000000" // 잘못된 레벨
|
||||
}
|
||||
}
|
||||
|
||||
fun make_findpath_param(org:String, dest:String, summary:Boolean = true):Map<String, String> {
|
||||
|
||||
return mapOf(
|
||||
"origin" to "${org}", //126.705098, 37.412087 출발지 경도, 위도
|
||||
"destination" to "${dest}", //126.696239, 37.395276 도착지 경도, 위도
|
||||
"priority" to "DISTANCE", // 'RECOMMEND' : 추천경로, 'TIME' : 최단시간, 'DISTANCE' : 최단경로
|
||||
"car_type" to "1", //자동차 타입 '1' : 소형(예시) 승용차, 16인승 이하 승합차, 2.5 톤 미만 화물차), '2' : 중형, '3' : 대형, '4' : 대형 화물, '5' : 특수 화물, '6' : 경차, '7' : 이륜차
|
||||
"car_fuel" to "DIESEL", //연료 종류
|
||||
"car_hipass" to "true", // 하이패스 장착 여부
|
||||
"summary" to "${summary}", //요약 전달(true 요약정보 제공, false 미제공)
|
||||
)
|
||||
|
||||
/*
|
||||
car_type : [1,
|
||||
*/
|
||||
}
|
||||
|
||||
fun make_getAddr_param(lon:String, lat:String):Map<String, String> {
|
||||
|
||||
return mapOf(
|
||||
"x" to "${lon}", //126.705098,
|
||||
"y" to "${lat}" //37.395276
|
||||
)
|
||||
|
||||
/*
|
||||
car_type : [1,
|
||||
*/
|
||||
}
|
||||
|
||||
fun make_addressHosp_param(
|
||||
Q0:String, // 광역시/도
|
||||
Q1:String, // 시군구
|
||||
QD:String, // 진료과
|
||||
QZ:String, // 병원분류코드
|
||||
QN:String, // 관련검색어
|
||||
page:String = "1", // 페이지
|
||||
row:String = "10", // 결과 개수
|
||||
):JsonObject {
|
||||
var _param = mapOf(
|
||||
"Q0" to Q0,
|
||||
"Q1" to Q1,
|
||||
"QD" to QD,
|
||||
"QZ" to QZ,
|
||||
"QN" to QN,
|
||||
"page" to page,
|
||||
"row" to row,
|
||||
)
|
||||
val gson = Gson()
|
||||
val json = gson.toJsonTree(_param).asJsonObject
|
||||
return json
|
||||
}
|
||||
|
||||
fun make_arroundHosp_param(
|
||||
lon:String,
|
||||
lat:String,
|
||||
page: String = "1",
|
||||
dgids:List<String> = emptyList(),
|
||||
row: String = "10",
|
||||
radius: String = "5"
|
||||
): JsonObject {
|
||||
var order = "distance"
|
||||
var _param = mapOf(
|
||||
"lon" to lon, //126.696239 경도
|
||||
"lat" to lat, //37.395276 위도
|
||||
"radius" to radius, // 경/위도 기준 meter 단위 반경내의 병원
|
||||
"order" to order, // 정렬 기준 "distance" 고정
|
||||
"row" to row, // 결과 row 개수
|
||||
"page" to page, // 결과 page 번째
|
||||
"dgidIdName" to dgids, // 진료과에 대한 항목들
|
||||
)
|
||||
val gson = Gson()
|
||||
val json = gson.toJsonTree(_param).asJsonObject
|
||||
return json
|
||||
}
|
||||
|
||||
fun make_arroundHosp_param2(
|
||||
lon:String,
|
||||
lat:String,
|
||||
emogemdv:String = "", // 필수
|
||||
prtcode:String = "", // 필수
|
||||
emogdesc:String = "", // 필수 아님
|
||||
radius: String = "3",
|
||||
row: String = "10",
|
||||
page: String = "1",
|
||||
emergency: String = "Y"
|
||||
): JsonObject {
|
||||
var order = "distance"
|
||||
var _param = mapOf(
|
||||
"lon" to lon, //126.696239 경도
|
||||
"lat" to lat, //37.395276 위도
|
||||
"emogemdv" to emogemdv, // 의료기관번호
|
||||
"prtcode" to prtcode, // 진료과코드
|
||||
"emogdesc" to emogdesc, // 연관검색어
|
||||
"radius" to radius, // 반경(km단위, 숫자만 입력)
|
||||
"row" to row, // 행
|
||||
"page" to page, // 페이지
|
||||
"emergency" to emergency // 응급실 여부("Y", "N")
|
||||
)
|
||||
val gson = Gson()
|
||||
val json = gson.toJsonTree(_param).asJsonObject
|
||||
return json
|
||||
}
|
||||
|
||||
fun make_detail_hosp_param(
|
||||
hpid: String
|
||||
) :JsonObject {
|
||||
var _param = mapOf(
|
||||
"hpid" to hpid, // 병원 아이디
|
||||
)
|
||||
val gson = Gson()
|
||||
val json = gson.toJsonTree(_param).asJsonObject
|
||||
return json
|
||||
}
|
||||
|
||||
fun calculateDistance(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Double {
|
||||
val R = 6371.0 // 지구 반지름 (단위: km)
|
||||
|
||||
val dLat = Math.toRadians(lat2 - lat1)
|
||||
val dLon = Math.toRadians(lon2 - lon1)
|
||||
|
||||
val a = sin(dLat / 2) * sin(dLat / 2) +
|
||||
cos(Math.toRadians(lat1)) * cos(Math.toRadians(lat2)) *
|
||||
sin(dLon / 2) * sin(dLon / 2)
|
||||
|
||||
val c = 2 * atan2(sqrt(a), sqrt(1 - a))
|
||||
|
||||
return R * c // 거리 반환 (단위: km)
|
||||
}
|
||||
}
|
138
app/src/main/java/com/example/smart119/AlertDialogUtil.kt
Normal file
@ -0,0 +1,138 @@
|
||||
package com.example.smart119
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.util.TypedValue
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
|
||||
object AlertDialogUtil {
|
||||
// 기본 AlertDialog 생성 함수
|
||||
fun showAlert(
|
||||
context: Context,
|
||||
title: String,
|
||||
message: String,
|
||||
positiveText: String = "확인",
|
||||
negativeText: String = "취소",
|
||||
onPositiveClick: (() -> Unit)? = null,
|
||||
onNegativeClick: (() -> Unit)? = null
|
||||
) {
|
||||
val builder = AlertDialog.Builder(context)
|
||||
builder.setTitle(title)
|
||||
// builder.setMessage(message)
|
||||
|
||||
val messageTextView = TextView(context).apply {
|
||||
text = message
|
||||
setPadding(40, 40, 40, 0)
|
||||
textSize = 16f
|
||||
setLineSpacing(10f, 1.2f) // 첫 번째 인자는 추가 간격(px), 두 번째 인자는 배수
|
||||
}
|
||||
builder.setView(messageTextView)
|
||||
|
||||
// Positive 버튼 설정
|
||||
builder.setPositiveButton(positiveText) { dialog, _ ->
|
||||
onPositiveClick?.invoke() // Positive 버튼 클릭 동작
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
// Negative 버튼 설정
|
||||
builder.setNegativeButton(negativeText) { dialog, _ ->
|
||||
onNegativeClick?.invoke() // Negative 버튼 클릭 동작
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
// 팝업 표시
|
||||
val dialog = builder.create()
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
fun showAlert_OK(
|
||||
context: Context,
|
||||
title: String,
|
||||
message: String,
|
||||
positiveText: String = "확인",
|
||||
negativeText: String = "취소",
|
||||
onPositiveClick: (() -> Unit)? = null
|
||||
// onNegativeClick: (() -> Unit)? = null
|
||||
) {
|
||||
val builder = AlertDialog.Builder(context)
|
||||
builder.setTitle(title)
|
||||
// builder.setMessage(message)
|
||||
|
||||
val messageTextView = TextView(context).apply {
|
||||
text = message
|
||||
setPadding(40, 40, 40, 0)
|
||||
textSize = 16f
|
||||
setLineSpacing(10f, 1.2f) // 첫 번째 인자는 추가 간격(px), 두 번째 인자는 배수
|
||||
}
|
||||
builder.setView(messageTextView)
|
||||
|
||||
// Positive 버튼 설정
|
||||
builder.setPositiveButton(positiveText) { dialog, _ ->
|
||||
onPositiveClick?.invoke() // Positive 버튼 클릭 동작
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
// Negative 버튼 설정
|
||||
// builder.setNegativeButton(negativeText) { dialog, _ ->
|
||||
// onNegativeClick?.invoke() // Negative 버튼 클릭 동작
|
||||
// dialog.dismiss()
|
||||
// }
|
||||
|
||||
// 팝업 표시
|
||||
val dialog = builder.create()
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
fun showAlert_CUSTOM(
|
||||
context: Context,
|
||||
title: String,
|
||||
sppStr: SpannableStringBuilder,
|
||||
positiveText: String = "확인",
|
||||
negativeText: String = "취소",
|
||||
onPositiveClick: (() -> Unit)? = null,
|
||||
onNegativeClick: (() -> Unit)? = null
|
||||
) {
|
||||
val builder = AlertDialog.Builder(context)
|
||||
builder.setTitle(title)
|
||||
/*
|
||||
val spannableMessage = SpannableStringBuilder().apply {
|
||||
val boldText = "확인"
|
||||
append(boldText)
|
||||
setSpan(StyleSpan(Typeface.BOLD), 0, boldText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
append(" 선택시 환자정보가 전송됩니다.")
|
||||
}
|
||||
*/
|
||||
|
||||
val textView = TextView(context).apply {
|
||||
text = sppStr
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f)
|
||||
setLineSpacing(12f, 1.3f) // 줄간 간격 조절 (추가간격 px, 배수)
|
||||
setPadding(40, 40, 40, 0) // 내부 여백도 함께 설정
|
||||
}
|
||||
|
||||
// builder.setMessage(sppStr)
|
||||
builder.setView(textView)
|
||||
|
||||
// Positive 버튼 설정
|
||||
builder.setPositiveButton(positiveText) { dialog, _ ->
|
||||
onPositiveClick?.invoke() // Positive 버튼 클릭 동작
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
// Negative 버튼 설정
|
||||
builder.setNegativeButton(negativeText) { dialog, _ ->
|
||||
onNegativeClick?.invoke() // Negative 버튼 클릭 동작
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
// 팝업 표시
|
||||
val dialog = builder.create()
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
fun getActivityContext(): Activity? {
|
||||
return GlobalActivityTracker.currentActivity
|
||||
}
|
||||
}
|
18
app/src/main/java/com/example/smart119/App.kt
Normal file
@ -0,0 +1,18 @@
|
||||
package com.example.smart119
|
||||
|
||||
import android.app.Application
|
||||
import android.util.Log
|
||||
|
||||
class App : Application() {
|
||||
companion object {
|
||||
lateinit var instance: App
|
||||
private set
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
Log.d("App", "App.onCreate 실행됨")
|
||||
registerActivityLifecycleCallbacks(GlobalActivityTracker)
|
||||
instance = this
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.example.smart119
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
|
||||
object GlobalActivityTracker : Application.ActivityLifecycleCallbacks {
|
||||
var currentActivity: Activity? = null
|
||||
|
||||
override fun onActivityResumed(activity: Activity) {
|
||||
currentActivity = activity
|
||||
Log.d("GlobalActivityTracker", "현재 액티비티: ${activity.localClassName}")
|
||||
}
|
||||
|
||||
override fun onActivityPaused(activity: Activity) {
|
||||
if (currentActivity === activity) {
|
||||
currentActivity = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
|
||||
override fun onActivityStarted(activity: Activity) {}
|
||||
override fun onActivityStopped(activity: Activity) {}
|
||||
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
|
||||
override fun onActivityDestroyed(activity: Activity) {}
|
||||
}
|
14
app/src/main/java/com/example/smart119/HelpUtility.kt
Normal file
@ -0,0 +1,14 @@
|
||||
package com.example.smart119
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
|
||||
object HelpUtility {
|
||||
private val delayHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
fun delay_executor(delayMillis: Long = 1000, callback: () -> Unit) {
|
||||
delayHandler.postDelayed({
|
||||
callback()
|
||||
}, delayMillis)
|
||||
}
|
||||
}
|
6
app/src/main/java/com/example/smart119/ListItem.kt
Normal file
@ -0,0 +1,6 @@
|
||||
package com.example.smart119
|
||||
|
||||
sealed class ListItem {
|
||||
data class Header(val columns: List<String>) : ListItem()
|
||||
data class Row(val values: List<String>) : ListItem()
|
||||
}
|
99
app/src/main/java/com/example/smart119/LocationService.kt
Normal file
@ -0,0 +1,99 @@
|
||||
package com.example.smart119
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.location.Location
|
||||
import android.os.IBinder
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.google.android.gms.location.FusedLocationProviderClient
|
||||
import com.google.android.gms.location.LocationCallback
|
||||
import com.google.android.gms.location.LocationRequest
|
||||
import com.google.android.gms.location.LocationResult
|
||||
import com.google.android.gms.location.LocationServices
|
||||
import com.google.android.gms.location.Priority
|
||||
|
||||
class LocationService : Service() {
|
||||
private lateinit var fusedLocationClient: FusedLocationProviderClient
|
||||
private lateinit var locationCallback: LocationCallback
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
|
||||
|
||||
locationCallback = object : LocationCallback() {
|
||||
override fun onLocationResult(result: LocationResult) {
|
||||
for (location: Location in result.locations) {
|
||||
// Log.d("LocationService", "위치: ${location.latitude}, ${location.longitude}")
|
||||
// TODO: 서버 전송 또는 처리 로직 추가
|
||||
val lat = location.latitude
|
||||
val lon = location.longitude
|
||||
|
||||
// ✅ LocationHelper에 위치 저장
|
||||
LocationHelper.setCurrentLocation(lat, lon)
|
||||
println("[GPS_UPDATE] lon:${lon}, lat:${lat}")
|
||||
|
||||
// ✅ Broadcast도 필요 시 같이 전송
|
||||
// broadcastLocation(lat, lon)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startLocationUpdates()
|
||||
}
|
||||
|
||||
private fun startLocationUpdates() {
|
||||
val request = LocationRequest.create().apply {
|
||||
interval = 5_000
|
||||
fastestInterval = 3_000
|
||||
priority = Priority.PRIORITY_HIGH_ACCURACY
|
||||
}
|
||||
|
||||
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
!= PackageManager.PERMISSION_GRANTED
|
||||
) return
|
||||
|
||||
fusedLocationClient.requestLocationUpdates(request, locationCallback, Looper.getMainLooper())
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
startForegroundServiceWithNotification()
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
private fun startForegroundServiceWithNotification() {
|
||||
val channelId = "location_service_channel"
|
||||
val channel = NotificationChannel(
|
||||
channelId,
|
||||
"Location Service",
|
||||
NotificationManager.IMPORTANCE_LOW
|
||||
)
|
||||
val manager = getSystemService(NotificationManager::class.java)
|
||||
manager.createNotificationChannel(channel)
|
||||
|
||||
val notification = NotificationCompat.Builder(this, channelId)
|
||||
.setContentTitle("위치 추적 중")
|
||||
.setContentText("백그라운드에서 위치를 추적하고 있습니다.")
|
||||
.setSmallIcon(R.drawable.ic_location_on)
|
||||
.build()
|
||||
|
||||
try {
|
||||
startForeground(1, notification)
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
fusedLocationClient.removeLocationUpdates(locationCallback)
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? = null
|
||||
}
|
179
app/src/main/java/com/example/smart119/LocationUtils.kt
Normal file
@ -0,0 +1,179 @@
|
||||
package com.example.smart119
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.location.LocationManager
|
||||
import android.net.Uri
|
||||
import android.provider.Settings
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.android.gms.location.FusedLocationProviderClient
|
||||
import com.google.android.gms.location.LocationServices
|
||||
import com.google.gson.JsonObject
|
||||
|
||||
object LocationHelper {
|
||||
private lateinit var fusedLocationClient: FusedLocationProviderClient
|
||||
private val LOCATION_PERMISSION_REQUEST_CODE = 100
|
||||
|
||||
// ✅ 실시간 위치 저장용 변수
|
||||
private var currentLat: Double = 0.0
|
||||
private var currentLon: Double = 0.0
|
||||
|
||||
|
||||
|
||||
fun startLocationService(ctx: Context, onFinish: () -> Unit = {}) {
|
||||
if (!checkAndRequestLocationPermission(ctx, onFinish)) return
|
||||
|
||||
if (!isGpsEnabled(ctx)) {
|
||||
promptEnableGps(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
val serviceIntent = Intent(ctx, LocationService::class.java)
|
||||
ContextCompat.startForegroundService(ctx, serviceIntent)
|
||||
println("[startLocationService] - start")
|
||||
}
|
||||
fun stopLocationService(ctx: Context) {
|
||||
val serviceIntent = Intent(ctx, LocationService::class.java)
|
||||
ctx.stopService(serviceIntent)
|
||||
}
|
||||
|
||||
fun setCurrentLocation(lat: Double, lon: Double) {
|
||||
currentLat = lat
|
||||
currentLon = lon
|
||||
}
|
||||
|
||||
fun getCurrentLat(): Double = currentLat
|
||||
fun getCurrentLon(): Double = currentLon
|
||||
|
||||
fun init(
|
||||
ctx: Context,
|
||||
onFinish:() -> Unit
|
||||
) {
|
||||
fusedLocationClient = LocationServices.getFusedLocationProviderClient(ctx)
|
||||
if (!checkAndRequestLocationPermission(ctx, onFinish)) {
|
||||
return
|
||||
}
|
||||
|
||||
handleGpsState(ctx)
|
||||
}
|
||||
|
||||
fun handleGpsState(ctx: Context) {
|
||||
if (isGpsEnabled(ctx)) {
|
||||
//Toast.makeText(this, "GPS is already enabled", Toast.LENGTH_SHORT).show()
|
||||
println("GPS Enabled")
|
||||
startLocationService(ctx)
|
||||
} else {
|
||||
println("GPS not Enabled")
|
||||
promptEnableGps(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// fun permissionResultInvoke(
|
||||
// ctx: Context,
|
||||
// requestCode: Int,
|
||||
// permissions: Array<out String>,
|
||||
// grantResults: IntArray,
|
||||
// onFinish: () -> Unit
|
||||
// ) {
|
||||
// if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
|
||||
// if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
// LocationHelper.handleGpsState(ctx)
|
||||
// } else {
|
||||
// // "다시 묻지 않음" 여부 확인
|
||||
// if (!ActivityCompat.shouldShowRequestPermissionRationale(
|
||||
// ctx as Activity, Manifest.permission.ACCESS_FINE_LOCATION
|
||||
// )
|
||||
// ) {
|
||||
// // 설정 화면으로 이동 안내(MainActivity에 구현)
|
||||
// showSettingsDialog(ctx, onFinish)
|
||||
// } else {
|
||||
// Toast.makeText(ctx, "권한이 거부되었습니다. 앱을 종료합니다.", Toast.LENGTH_SHORT).show()
|
||||
// onFinish();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
private fun showSettingsDialog(ctx: Context, onFinish: () -> Unit) {
|
||||
AlertDialog.Builder(ctx)
|
||||
.setTitle("권한 필요")
|
||||
.setMessage("위치 권한이 필요합니다. 설정에서 권한을 허용해주세요.")
|
||||
.setPositiveButton("설정으로 이동") { _, _ ->
|
||||
goToAppSettings(ctx)
|
||||
}
|
||||
.setNegativeButton("취소") { _, _ ->
|
||||
Toast.makeText(ctx, "권한이 거부되었습니다. 앱을 종료합니다.", Toast.LENGTH_SHORT).show()
|
||||
onFinish()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
private fun goToAppSettings(context: Context) {
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||
data = Uri.fromParts("package", context.packageName, null)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
//1.현재 gps 상태 확인
|
||||
private fun isGpsEnabled(ctx: Context): Boolean {
|
||||
val locationManager = ctx.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
|
||||
}
|
||||
|
||||
//2.gps 활성화 요청
|
||||
private fun promptEnableGps(ctx: Context) {
|
||||
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
|
||||
ctx.startActivity(intent)
|
||||
}
|
||||
|
||||
//3. 권한 요청 코드
|
||||
private fun checkAndRequestLocationPermission(ctx: Context, onFinish: () -> Unit): Boolean {
|
||||
if (ContextCompat.checkSelfPermission(ctx, Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
!= PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(
|
||||
ctx as Activity,
|
||||
Manifest.permission.ACCESS_FINE_LOCATION
|
||||
)
|
||||
) {
|
||||
// 권한 요청 설명
|
||||
showPermissionRationale(ctx, onFinish)
|
||||
} else {
|
||||
// 권한 요청
|
||||
ActivityCompat.requestPermissions(
|
||||
ctx,
|
||||
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
|
||||
LOCATION_PERMISSION_REQUEST_CODE
|
||||
)
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun showPermissionRationale(ctx: Context, onFinish: () -> Unit) {
|
||||
AlertDialog.Builder(ctx)
|
||||
.setTitle("위치 권한 필요")
|
||||
.setMessage("앱에서 정확한 위치 서비스를 제공하려면 위치 권한이 필요합니다.")
|
||||
.setPositiveButton("권한 허용") { _, _ ->
|
||||
ActivityCompat.requestPermissions(
|
||||
ctx as Activity,
|
||||
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
|
||||
LOCATION_PERMISSION_REQUEST_CODE
|
||||
)
|
||||
}
|
||||
.setNegativeButton("취소") { _, _ ->
|
||||
Toast.makeText(ctx, "권한이 거부되었습니다. 앱을 종료합니다.", Toast.LENGTH_SHORT).show()
|
||||
onFinish()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
}
|
32
app/src/main/java/com/example/smart119/LoginManager.kt
Normal file
@ -0,0 +1,32 @@
|
||||
package com.example.smart119
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
|
||||
object LoginManager {
|
||||
private var isLoggedIn: Boolean = false // 기본값 설정
|
||||
var tryLoginBody: JsonObject = JsonObject().apply {
|
||||
addProperty("userId", "")
|
||||
addProperty("carNo", "")
|
||||
addProperty("ver", "")
|
||||
}
|
||||
|
||||
// 로그인 상태 확인
|
||||
fun isLoggedIn(): Boolean {
|
||||
return isLoggedIn
|
||||
}
|
||||
|
||||
// 로그인 상태 업데이트
|
||||
fun setLoggedIn(status: Boolean) {
|
||||
isLoggedIn = status
|
||||
}
|
||||
|
||||
fun getLoggedInfo() :JsonObject{
|
||||
return tryLoginBody;
|
||||
}
|
||||
|
||||
fun setLoggedInfo(userId:String, carNo:String, ver:String) {
|
||||
tryLoginBody.addProperty("userId", userId)
|
||||
tryLoginBody.addProperty("carNo", carNo)
|
||||
tryLoginBody.addProperty("ver", ver)
|
||||
}
|
||||
}
|
335
app/src/main/java/com/example/smart119/MainActivity.kt
Normal file
@ -0,0 +1,335 @@
|
||||
package com.example.smart119
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.ui.AppBarConfiguration
|
||||
import androidx.navigation.ui.navigateUp
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.example.smart119.databinding.ActivityMainBinding
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import com.example.smart119.datas.HospitalSearch
|
||||
import com.example.smart119.datas.SaveLogin
|
||||
import com.example.smart119.interfaces.RetrofitClient
|
||||
import com.example.smart119.viewModel.TransferViewModel
|
||||
import com.example.smart119.views.LoadingDialog
|
||||
import com.google.android.gms.location.FusedLocationProviderClient
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.gson.JsonObject
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var appBarConfiguration: AppBarConfiguration
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
private lateinit var fusedLocationClient: FusedLocationProviderClient
|
||||
private val LOCATION_PERMISSION_REQUEST_CODE = 100
|
||||
private val viewModel by viewModels<TransferViewModel>()
|
||||
|
||||
private val requestPermissionLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
|
||||
if (isGranted) {
|
||||
// 권한이 허용되면 서비스 시작
|
||||
LocationHelper.startLocationService(this)
|
||||
} else {
|
||||
// 권한 거부됨 -> 필요한 안내 처리
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
// binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
|
||||
|
||||
// fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
|
||||
|
||||
// 권한 요청 흐름 시작
|
||||
// if (!checkAndRequestLocationPermission()) {
|
||||
// return
|
||||
// }
|
||||
|
||||
// LocationHelper.init(this, {
|
||||
// finish()
|
||||
// });
|
||||
LocationHelper.startLocationService(this)
|
||||
|
||||
SaveLogin.init(this);
|
||||
HospitalSearch.init_hospital_req(this)
|
||||
|
||||
|
||||
// LocationHelper.getLastKnownLocation_TOASTMSG(this)
|
||||
|
||||
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
|
||||
val navController = navHostFragment.navController
|
||||
|
||||
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
bottomNavigationView.setupWithNavController(navController)
|
||||
|
||||
//이송 초기화
|
||||
TransferManager.setIdle()
|
||||
|
||||
//네비게이션하고 fragment 연결
|
||||
bottomNavigationView.setOnItemSelectedListener { item ->
|
||||
when (item.itemId) {
|
||||
R.id.emgLogin -> {
|
||||
if (LoginManager.isLoggedIn()) {
|
||||
val _inputId = SaveLogin.getUserId()
|
||||
val _inputCarno = SaveLogin.getCarNo()
|
||||
val message = """
|
||||
현재 로그인된 정보입니다.
|
||||
아이디: $_inputId
|
||||
차량번호: $_inputCarno
|
||||
로그아웃하시겠습니까?
|
||||
|
||||
""".trimIndent()
|
||||
|
||||
AlertDialogUtil.showAlert(
|
||||
context = this,
|
||||
title = "로그인 상태 확인",
|
||||
message = message,
|
||||
onPositiveClick = {
|
||||
//로그아웃 처리
|
||||
println("logout")
|
||||
navController.navigate(R.id.LoginFragment)
|
||||
SaveLogin.setLogin(false)
|
||||
TransferManager.clear_state()
|
||||
},
|
||||
onNegativeClick = {
|
||||
|
||||
}
|
||||
)
|
||||
false
|
||||
}
|
||||
else {
|
||||
navController.navigate(R.id.LoginFragment)
|
||||
true
|
||||
}
|
||||
}
|
||||
R.id.hospSearch -> {
|
||||
navController.navigate(R.id.HospSearchFragment)
|
||||
true
|
||||
}
|
||||
R.id.hospTransfer -> {
|
||||
navController.navigate(R.id.TransferFragment)
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
TransferManager.registerListener("transfer_update_event", ::TransferUpdateEvent)
|
||||
TransferManager.registerListener("transfer_dialogmsg_event", ::TransferDialogMsgEvent)
|
||||
|
||||
MedicalInfo.init()
|
||||
|
||||
// viewModel.requestData()
|
||||
// viewModel.someLiveData.observe(viewLifecycleOwner) { result ->
|
||||
// // UI 업데이트
|
||||
// }
|
||||
}
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
menuInflater.inflate(R.menu.menu_main, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
return when (item.itemId) {
|
||||
R.id.action_settings -> true
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
val navController = findNavController(R.id.nav_host_fragment_content_main)
|
||||
return navController.navigateUp(appBarConfiguration)
|
||||
|| super.onSupportNavigateUp()
|
||||
}
|
||||
|
||||
//권한 확인
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<out String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
|
||||
if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
|
||||
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
LocationHelper.handleGpsState(this)
|
||||
} else {
|
||||
// "다시 묻지 않음" 여부 확인
|
||||
if (!ActivityCompat.shouldShowRequestPermissionRationale(
|
||||
this as Activity, Manifest.permission.ACCESS_FINE_LOCATION
|
||||
)
|
||||
) {
|
||||
// 설정 화면으로 이동 안내(MainActivity에 구현)
|
||||
showSettingsDialog(this@MainActivity) { finish() }
|
||||
} else {
|
||||
Toast.makeText(this, "권한이 거부되었습니다. 앱을 종료합니다.", Toast.LENGTH_SHORT).show()
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
println("gps 권한 여부 코드 : ${requestCode}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSettingsDialog(activity: Activity, onFinish: () -> Unit) {
|
||||
AlertDialog.Builder(activity)
|
||||
.setTitle("권한 필요")
|
||||
.setMessage("위치 권한이 필요합니다. 설정에서 권한을 허용해주세요.")
|
||||
.setPositiveButton("설정으로 이동") { _, _ ->
|
||||
goToAppSettings(activity)
|
||||
}
|
||||
.setNegativeButton("취소") { _, _ ->
|
||||
Toast.makeText(activity, "권한이 거부되었습니다. 앱을 종료합니다.", Toast.LENGTH_SHORT).show()
|
||||
onFinish()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun goToAppSettings(activity: Activity) {
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||
data = Uri.fromParts("package", activity.packageName, null)
|
||||
}
|
||||
activity.startActivity(intent)
|
||||
}
|
||||
|
||||
private fun onAccessButtonClick() {
|
||||
Toast.makeText(this, "Button clicked!", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
|
||||
fun TransferUpdateEvent(data: JsonObject?) {
|
||||
}
|
||||
|
||||
fun TransferDialogMsgEvent(data: JsonObject?) {
|
||||
try {
|
||||
var _msgObj = data?.asJsonObject!!;
|
||||
|
||||
AlertDialogUtil.showAlert(
|
||||
context = this,
|
||||
title = _msgObj["title"].toString().trim('"'),
|
||||
message = _msgObj["msg"].toString().trim('"'),
|
||||
onPositiveClick = {
|
||||
val activity = AlertDialogUtil.getActivityContext()
|
||||
val bottomNav = activity?.findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
if (bottomNav != null &&
|
||||
bottomNav.selectedItemId != R.id.hospSearch
|
||||
){
|
||||
bottomNav.selectedItemId = R.id.hospSearch
|
||||
}
|
||||
},
|
||||
onNegativeClick = {
|
||||
val activity = AlertDialogUtil.getActivityContext()
|
||||
val bottomNav = activity?.findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
if (bottomNav != null &&
|
||||
bottomNav.selectedItemId != R.id.hospSearch
|
||||
) {
|
||||
bottomNav.selectedItemId = R.id.hospSearch
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
//TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
//3. 권한 요청 코드
|
||||
private fun checkAndRequestLocationPermission(): Boolean {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
!= PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(
|
||||
this,
|
||||
Manifest.permission.ACCESS_FINE_LOCATION
|
||||
)
|
||||
) {
|
||||
// 권한 요청 설명
|
||||
showPermissionRationale()
|
||||
} else {
|
||||
// 권한 요청
|
||||
ActivityCompat.requestPermissions(
|
||||
this,
|
||||
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
|
||||
LOCATION_PERMISSION_REQUEST_CODE
|
||||
)
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun showPermissionRationale() {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle("위치 권한 필요")
|
||||
.setMessage("앱에서 정확한 위치 서비스를 제공하려면 위치 권한이 필요합니다.")
|
||||
.setPositiveButton("권한 허용") { _, _ ->
|
||||
ActivityCompat.requestPermissions(
|
||||
this,
|
||||
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
|
||||
LOCATION_PERMISSION_REQUEST_CODE
|
||||
)
|
||||
}
|
||||
.setNegativeButton("취소") { _, _ ->
|
||||
Toast.makeText(this, "권한이 거부되었습니다. 앱을 종료합니다.", Toast.LENGTH_SHORT).show()
|
||||
finish()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun showSettingsDialog() {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle("권한 필요")
|
||||
.setMessage("위치 권한이 필요합니다. 설정에서 권한을 허용해주세요.")
|
||||
.setPositiveButton("설정으로 이동") { _, _ ->
|
||||
goToAppSettings(this)
|
||||
}
|
||||
.setNegativeButton("취소") { _, _ ->
|
||||
Toast.makeText(this, "권한이 거부되었습니다. 앱을 종료합니다.", Toast.LENGTH_SHORT).show()
|
||||
finish()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
//4. 설정 화면으로 이동
|
||||
fun goToAppSettings(context: Context) {
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||
data = Uri.fromParts("package", context.packageName, null)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
LocationHelper.stopLocationService(this)
|
||||
TransferManager.clear_state();
|
||||
}
|
||||
}
|
218
app/src/main/java/com/example/smart119/MedicalDepartment.kt
Normal file
@ -0,0 +1,218 @@
|
||||
package com.example.smart119
|
||||
|
||||
object MedicalInfo {
|
||||
private val prtcodeMap = mutableMapOf<String, String>() // 진료과 목록용 맵
|
||||
private val emogemdvMap = mutableMapOf<String, String>() // 의료기관 목록용 맵
|
||||
private val addressQZMap = mutableMapOf<String, String>() // QZ 분류용 맵
|
||||
private val prtGroupMap = mutableMapOf<String, MutableList<String>>() // 진료과 리스트 맵
|
||||
|
||||
fun init() {
|
||||
prtcode_init()
|
||||
emogemdv_init()
|
||||
address_qz_init();
|
||||
prtGroupMap_init();
|
||||
}
|
||||
private fun prtcode_init() {
|
||||
prtcodeMap.put("가정의학과", "D022")
|
||||
prtcodeMap.put("결핵과", "D015")
|
||||
prtcodeMap.put("구강내과", "D040")
|
||||
prtcodeMap.put("구강병리과", "D042")
|
||||
prtcodeMap.put("구강악안면방사선과", "D041")
|
||||
prtcodeMap.put("구강악안면외과", "D034")
|
||||
prtcodeMap.put("구강안면외과", "D054")
|
||||
prtcodeMap.put("내과", "D001")
|
||||
prtcodeMap.put("마취통증의학과", "D017")
|
||||
prtcodeMap.put("방사선종양학과", "D031")
|
||||
prtcodeMap.put("병리과", "D032")
|
||||
prtcodeMap.put("비뇨의학과", "D014")
|
||||
prtcodeMap.put("사상체질과", "D050")
|
||||
prtcodeMap.put("산부인과", "D011")
|
||||
prtcodeMap.put("산업의학과", "D025")
|
||||
prtcodeMap.put("성형외과", "D010")
|
||||
prtcodeMap.put("소아청소년과", "D002")
|
||||
prtcodeMap.put("소아치과", "D037")
|
||||
prtcodeMap.put("신경과", "D003")
|
||||
prtcodeMap.put("신경외과", "D009")
|
||||
prtcodeMap.put("심장혈관흉부외과", "D007")
|
||||
prtcodeMap.put("안과", "D012")
|
||||
prtcodeMap.put("영상의학과", "D018")
|
||||
prtcodeMap.put("영상치의학과", "D055")
|
||||
prtcodeMap.put("예방의학과", "D029")
|
||||
prtcodeMap.put("예방치과", "D043")
|
||||
prtcodeMap.put("외과", "D006")
|
||||
prtcodeMap.put("응급의학과", "D024")
|
||||
prtcodeMap.put("이비인후과", "D013")
|
||||
prtcodeMap.put("작업환경의학과", "D053")
|
||||
prtcodeMap.put("재활의학과", "D016")
|
||||
prtcodeMap.put("정신건강의학과", "D004")
|
||||
prtcodeMap.put("정형외과", "D008")
|
||||
prtcodeMap.put("진단검사의학과", "D033")
|
||||
prtcodeMap.put("치과", "D026")
|
||||
prtcodeMap.put("치과교정과", "D036")
|
||||
prtcodeMap.put("치과보존과", "D039")
|
||||
prtcodeMap.put("치과보철과", "D035")
|
||||
prtcodeMap.put("치료방사선과", "D019")
|
||||
prtcodeMap.put("치주과", "D038")
|
||||
prtcodeMap.put("침구과", "D051")
|
||||
prtcodeMap.put("통합치의학과", "D056")
|
||||
prtcodeMap.put("피부과", "D005")
|
||||
prtcodeMap.put("한방내과", "D044")
|
||||
prtcodeMap.put("한방부인과", "D045")
|
||||
prtcodeMap.put("한방소아과", "D046")
|
||||
prtcodeMap.put("한방신경정신과", "D048")
|
||||
prtcodeMap.put("한방안이비인후피부과", "D047")
|
||||
prtcodeMap.put("한방응급과", "D052")
|
||||
prtcodeMap.put("한방재활의학과", "D049")
|
||||
prtcodeMap.put("해부병리과", "D021")
|
||||
prtcodeMap.put("핵의학과", "D023")
|
||||
}
|
||||
private fun emogemdv_init() {
|
||||
emogemdvMap.put("상급종합병원", "001")
|
||||
emogemdvMap.put("종합병원", "011")
|
||||
emogemdvMap.put("병원", "021")
|
||||
emogemdvMap.put("요양병원", "028")
|
||||
emogemdvMap.put("의원", "031")
|
||||
emogemdvMap.put("치과병원", "041")
|
||||
emogemdvMap.put("치과의원", "051")
|
||||
emogemdvMap.put("보건소", "071")
|
||||
emogemdvMap.put("보건지소", "072")
|
||||
emogemdvMap.put("보건진료소", "073")
|
||||
emogemdvMap.put("보건의료원", "075")
|
||||
emogemdvMap.put("한방병원", "092")
|
||||
emogemdvMap.put("한의원", "093")
|
||||
}
|
||||
private fun address_qz_init() { // 주소검색 시 병원 분류 코드
|
||||
addressQZMap.put("종합병원", "A")
|
||||
addressQZMap.put("병원", "B")
|
||||
addressQZMap.put("의원", "C")
|
||||
addressQZMap.put("요양병원", "D")
|
||||
addressQZMap.put("한방병원", "E")
|
||||
addressQZMap.put("한의원", "G")
|
||||
addressQZMap.put("기타", "I")
|
||||
addressQZMap.put("치과병원", "M")
|
||||
addressQZMap.put("치과의원", "N")
|
||||
addressQZMap.put("보건소", "R")
|
||||
addressQZMap.put("기타(구급차)", "W")
|
||||
}
|
||||
|
||||
private fun prtGroupMap_init() {
|
||||
prtGroupMap.put(
|
||||
"🚨 응급 및 외상 치료",
|
||||
mutableListOf("응급의학과", "외과", "신경외과", "심장혈관흉부외과")
|
||||
)
|
||||
|
||||
prtGroupMap.put(
|
||||
"🏥 내과 및 심장 관련",
|
||||
mutableListOf("내과", "심장내과", "결핵과", "예방의학과", "산업의학과", "작업환경의학과")
|
||||
)
|
||||
|
||||
prtGroupMap.put(
|
||||
"🦴 골절 및 재활",
|
||||
mutableListOf("정형외과", "재활의학과", "한방재활의학과")
|
||||
)
|
||||
|
||||
prtGroupMap.put(
|
||||
"💊 마취 및 통증 관리",
|
||||
mutableListOf("마취통증의학과")
|
||||
)
|
||||
|
||||
prtGroupMap.put(
|
||||
"👶 소아 및 여성 건강",
|
||||
mutableListOf("소아청소년과", "산부인과", "한방소아과", "한방부인과")
|
||||
)
|
||||
|
||||
prtGroupMap.put(
|
||||
"🦷 치과 계열",
|
||||
mutableListOf(
|
||||
"치과", "구강내과", "구강병리과", "구강악안면방사선과", "구강악안면외과",
|
||||
"소아치과", "치과교정과", "치과보존과", "치과보철과", "치주과",
|
||||
"영상치의학과", "예방치과", "통합치의학과"
|
||||
)
|
||||
)
|
||||
|
||||
prtGroupMap.put(
|
||||
"🧠 신경 및 정신 건강",
|
||||
mutableListOf("신경과", "정신건강의학과", "한방신경정신과")
|
||||
)
|
||||
|
||||
prtGroupMap.put(
|
||||
"👂 이비인후과 및 안과",
|
||||
mutableListOf("이비인후과", "안과", "한방안이비인후피부과")
|
||||
)
|
||||
|
||||
prtGroupMap.put(
|
||||
"📡 방사선 및 영상의학",
|
||||
mutableListOf("영상의학과", "치료방사선과", "방사선종양학과", "핵의학과")
|
||||
)
|
||||
|
||||
prtGroupMap.put(
|
||||
"🩺 병리 및 진단의학",
|
||||
mutableListOf("병리과", "해부병리과", "진단검사의학과")
|
||||
)
|
||||
|
||||
prtGroupMap.put(
|
||||
"🩸 비뇨 및 피부과",
|
||||
mutableListOf("비뇨의학과", "피부과")
|
||||
)
|
||||
|
||||
prtGroupMap.put(
|
||||
"🌿 한방 계열",
|
||||
mutableListOf(
|
||||
"한방내과", "한방부인과", "한방소아과", "한방신경정신과", "한방안이비인후피부과",
|
||||
"한방응급과", "한방재활의학과", "침구과", "사상체질과"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun get_prt_code(prtName:String):String? {
|
||||
return prtcodeMap.get(prtName)
|
||||
}
|
||||
fun get_emogemdv_code(emogemdvName:String):String? {
|
||||
return emogemdvMap.get(emogemdvName)
|
||||
}
|
||||
fun get_addressQZ_code(qzName:String):String? {
|
||||
return addressQZMap.get(qzName)
|
||||
}
|
||||
|
||||
fun get_prt_list():MutableList<String> {
|
||||
var returnList:MutableList<String> = mutableListOf()
|
||||
prtcodeMap.forEach { key, value ->
|
||||
returnList.add(key)
|
||||
}
|
||||
return returnList
|
||||
}
|
||||
fun get_emogemdv_list():MutableList<String> {
|
||||
var returnList:MutableList<String> = mutableListOf()
|
||||
emogemdvMap.forEach { key, value ->
|
||||
returnList.add(key)
|
||||
}
|
||||
return returnList
|
||||
}
|
||||
fun get_addressQZ_list():MutableList<String> {
|
||||
var returnList:MutableList<String> = mutableListOf()
|
||||
addressQZMap.forEach { key, value ->
|
||||
returnList.add(key)
|
||||
}
|
||||
return returnList
|
||||
}
|
||||
|
||||
fun get_prt_group_map():MutableMap<String, MutableList<String>> {
|
||||
return prtGroupMap;
|
||||
}
|
||||
|
||||
/* //region 사용 예
|
||||
val prtCode = MedicalInfo.get_prt_code("신경외과")
|
||||
val emoCode = MedicalInfo.get_emogemdv_code("병원")
|
||||
println("신경외과:${prtCode}, 병원:${emoCode}")
|
||||
|
||||
val getPRTList = MedicalInfo.get_prt_list()
|
||||
getPRTList.forEach { prtName ->
|
||||
println(prtName)
|
||||
}
|
||||
println("aaaaaaaaaaaaaaaa")
|
||||
val getEMOList = MedicalInfo.get_emogemdv_list()
|
||||
getEMOList.forEach { emoName ->
|
||||
println(emoName)
|
||||
}
|
||||
*/ // endregion
|
||||
}
|
52
app/src/main/java/com/example/smart119/MyCookieJar.kt
Normal file
@ -0,0 +1,52 @@
|
||||
package com.example.smart119
|
||||
import okhttp3.Cookie
|
||||
import okhttp3.CookieJar
|
||||
import okhttp3.HttpUrl
|
||||
|
||||
object MyCookieJar : CookieJar {
|
||||
|
||||
private val cookieStore: MutableMap<String, MutableList<Cookie>> = mutableMapOf()
|
||||
private val cookieCustom: MutableMap<String, String> = mutableMapOf()
|
||||
|
||||
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
|
||||
val host = url.url().host // URL의 호스트 이름 추출
|
||||
if (cookies.isNotEmpty()) {
|
||||
cookieStore[host] = cookies.toMutableList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadForRequest(url: HttpUrl): List<Cookie> {
|
||||
val host = url.url().host
|
||||
return cookieStore[host] ?: mutableListOf()
|
||||
}
|
||||
fun setCookie(cookie:String) {
|
||||
var cookieSplits = cookie.split("=")
|
||||
// println(cookieSplits[0])
|
||||
// println(cookieSplits[1])
|
||||
cookieCustom.put(cookieSplits[0], cookie)
|
||||
}
|
||||
fun getCustomCookies():MutableList<String> {
|
||||
var retList:MutableList<String> = mutableListOf()
|
||||
cookieCustom.forEach { key, value ->
|
||||
retList.add(value)
|
||||
}
|
||||
|
||||
return retList;
|
||||
}
|
||||
fun getAllCookies():List<Cookie> {
|
||||
return cookieStore.values.flatten()
|
||||
}
|
||||
|
||||
|
||||
// 쿠키 상태 확인 (디버깅용)
|
||||
fun getCookies(): Map<String, List<Cookie>> {
|
||||
return cookieStore
|
||||
}
|
||||
|
||||
// 모든 쿠키 삭제
|
||||
fun clearCookies() {
|
||||
cookieStore.clear()
|
||||
}
|
||||
|
||||
|
||||
}
|
40
app/src/main/java/com/example/smart119/RandomNumberUtil.kt
Normal file
@ -0,0 +1,40 @@
|
||||
package com.example.smart119
|
||||
|
||||
import kotlin.random.Random
|
||||
|
||||
object RandomNumberUtil {
|
||||
|
||||
private var randNumList:List<Int> = mutableListOf()
|
||||
private var _num_count_min = 0;
|
||||
private var _num_counter = 0;
|
||||
private var _num_count_max = 5;
|
||||
|
||||
fun num_increase():Boolean {
|
||||
_num_counter++;
|
||||
if (_num_counter == _num_count_max) return false
|
||||
else return true;
|
||||
}
|
||||
|
||||
fun setRandDescending(min: Int, max: Int, count: Int){
|
||||
_num_count_min = min;
|
||||
_num_count_max = count;
|
||||
_num_counter = min;
|
||||
|
||||
require(max >= min) { "max should be greater than or equal to min" }
|
||||
require(count > 0) { "count should be greater than 0" }
|
||||
|
||||
// 랜덤 숫자 생성
|
||||
val randomNumbers = List(count - 1) { Random.nextInt(min, max + 1) } // count-1개의 랜덤 값 생성
|
||||
|
||||
// 마지막 값을 0으로 추가
|
||||
val finalList = randomNumbers + 0
|
||||
|
||||
randNumList = finalList.sortedDescending()
|
||||
// 내림차순 정렬
|
||||
}
|
||||
|
||||
fun getCurrentNumber():Int {
|
||||
return randNumList[_num_counter]
|
||||
}
|
||||
|
||||
}
|
221
app/src/main/java/com/example/smart119/SpreadsheetAdapter.kt
Normal file
@ -0,0 +1,221 @@
|
||||
package com.example.smart119
|
||||
|
||||
import android.graphics.Color
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.gson.JsonObject
|
||||
|
||||
class SpreadsheetAdapter(
|
||||
private var items: List<ListItem>,
|
||||
private val onButtonClick: (ListItem.Row, Int) -> Unit, // button click 이벤트
|
||||
private val onRowClick: (ListItem.Row) -> Unit// Row click 이벤트
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
companion object {
|
||||
const val VIEW_TYPE_HEADER = 0
|
||||
const val VIEW_TYPE_ROW = 1
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when (items[position]) {
|
||||
is ListItem.Header -> VIEW_TYPE_HEADER
|
||||
is ListItem.Row -> VIEW_TYPE_ROW
|
||||
else -> throw IllegalArgumentException("Unknown view type at position $position")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return if (viewType == VIEW_TYPE_HEADER) {
|
||||
val view = inflater.inflate(R.layout.header_row, parent, false)
|
||||
HeaderViewHolder(view)
|
||||
} else {
|
||||
val view = inflater.inflate(R.layout.data_row, parent, false)
|
||||
RowViewHolder(view, onButtonClick, onRowClick)
|
||||
}
|
||||
}
|
||||
|
||||
private var _columnCount = 0
|
||||
private var selectedPosition: Int = RecyclerView.NO_POSITION
|
||||
private var headerList: List<ListItem>? = null
|
||||
private var _IndexMap:MutableMap<String, Int> = mutableMapOf()
|
||||
|
||||
fun setColumnCount(count:Int) {
|
||||
_columnCount = count
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (val item = items[position]) {
|
||||
is ListItem.Header -> (holder as HeaderViewHolder).bind(item)
|
||||
is ListItem.Row -> (holder as RowViewHolder).bind(item, position)
|
||||
else -> throw IllegalArgumentException("Unsupported item type at position $position")
|
||||
}
|
||||
|
||||
/*
|
||||
holder.itemView.setOnClickListener {
|
||||
val previousPosition = selectedPosition
|
||||
selectedPosition = position
|
||||
|
||||
// 이전 선택 항목과 현재 선택 항목 갱신
|
||||
notifyItemChanged(previousPosition)
|
||||
notifyItemChanged(selectedPosition)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = items.size
|
||||
|
||||
fun setSelectedHospitalPos(selPos:Int) {
|
||||
selectedPosition = selPos
|
||||
}
|
||||
|
||||
fun getSelectedHospital() : ListItem? {
|
||||
//return this.items[selectedPosition]
|
||||
return if(selectedPosition in 0 until items.size) {
|
||||
this.items[selectedPosition]
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
fun getSelectedPosition():Int {
|
||||
var valid = selectedPosition - _columnCount;
|
||||
if(valid < 0) valid = 0
|
||||
return valid
|
||||
}
|
||||
|
||||
fun getSelectedHospital_JSON() : JsonObject? {
|
||||
//return this.items[selectedPosition]
|
||||
var returnValue = JsonObject()
|
||||
if(selectedPosition in 0 until items.size) {
|
||||
var _row = (this.items[selectedPosition] as ListItem.Row);
|
||||
returnValue = JsonObject().apply {
|
||||
addProperty("name", "${_row.values[0]}")
|
||||
addProperty("address", "${_row.values[1]}")
|
||||
addProperty("tell","${_row.values[2]}")
|
||||
addProperty("lidar","${_row.values[3]}")
|
||||
addProperty("distance","${_row.values[4]}")
|
||||
}
|
||||
}
|
||||
return returnValue
|
||||
}
|
||||
|
||||
private fun default_list_headers() {
|
||||
this.items = listOf(
|
||||
ListItem.Header(listOf("병원이름")), // 헤더 열 정의
|
||||
ListItem.Header(listOf("주소")),
|
||||
ListItem.Header(listOf("전화번호")),
|
||||
ListItem.Header(listOf("라이다 혼잡도")),
|
||||
ListItem.Header(listOf("거리")),
|
||||
ListItem.Header(listOf("병원별 이송 시작")),
|
||||
)
|
||||
}
|
||||
|
||||
fun hospitalListUpdate(searchResult:List<List<String>>, idList: List<String>) {
|
||||
//기본 헤더 설정
|
||||
default_list_headers()
|
||||
|
||||
//추가 검색된 결과 설정
|
||||
// var loop_count = 0;
|
||||
// for (addItem in searchResult) {
|
||||
// this.items = this.items + ListItem.Row(addItem)
|
||||
// println(addItem[0])
|
||||
// loop_count++;
|
||||
// }
|
||||
|
||||
searchResult.forEachIndexed { index, addItem ->
|
||||
this.items = this.items + ListItem.Row(addItem)
|
||||
if (idList.size > index) {
|
||||
_IndexMap[idList[index]] = this.items.size - 1 // ID와 리스트 인덱스 매핑
|
||||
}
|
||||
}
|
||||
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun getHospitalById(id: String): ListItem.Row? {
|
||||
val position = _IndexMap[id] ?: return null
|
||||
return if (position in 0 until items.size) {
|
||||
items[position] as? ListItem.Row
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun clearHospitalList() {
|
||||
if(this.items.size == 6) return;
|
||||
|
||||
if (selectedPosition != RecyclerView.NO_POSITION) selectedPosition = RecyclerView.NO_POSITION
|
||||
|
||||
if (_IndexMap != null) _IndexMap.clear()
|
||||
|
||||
default_list_headers()
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
// fun getSelectedHospitalName(): String {
|
||||
// return selRowHospName
|
||||
// }
|
||||
|
||||
// 헤더 ViewHolder
|
||||
class HeaderViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
private val columns: List<TextView> = listOf(
|
||||
itemView.findViewById(R.id.column1) // 추가 열에 따라 확장 가능
|
||||
)
|
||||
|
||||
fun bind(header: ListItem.Header) {
|
||||
header.columns.forEachIndexed { index, column ->
|
||||
columns[index].text = column
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 데이터 행 ViewHolder
|
||||
class RowViewHolder(
|
||||
itemView: View,
|
||||
private val onButtonClick: (ListItem.Row, Int) -> Unit,
|
||||
private val onRowClick: (ListItem.Row) -> Unit
|
||||
) : RecyclerView.ViewHolder(itemView) {
|
||||
private val cells: List<TextView> = listOf(
|
||||
itemView.findViewById(R.id.cell1),
|
||||
itemView.findViewById(R.id.cell2),
|
||||
itemView.findViewById(R.id.cell3), // 추가 열에 따라 확장 가능
|
||||
itemView.findViewById(R.id.cell4),
|
||||
itemView.findViewById(R.id.cell5)
|
||||
)
|
||||
|
||||
private val lContainer: LinearLayout = itemView.findViewById(R.id.cell6_container)
|
||||
private val lContButton: Button = itemView.findViewById(R.id.cell6_button)
|
||||
private val lLidarView : View = itemView.findViewById(R.id.cell4_lidar_color)
|
||||
|
||||
fun bind(row: ListItem.Row, pos:Int) {
|
||||
row.values.take(cells.size).forEachIndexed { index, value ->
|
||||
cells[index].text = value
|
||||
|
||||
if (index == 3) lLidarView.setBackgroundColor(
|
||||
Color.parseColor(API_Helper.lidar_levelState_Color(value))
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
// 선택된 항목 하이라이트 적용
|
||||
if (isSelected) {
|
||||
itemView.setBackgroundColor(Color.parseColor("#DCDCDC")) // 선택된 배경색
|
||||
onRowClick(row)
|
||||
} else {
|
||||
itemView.setBackgroundColor(Color.WHITE) // 기본 배경색
|
||||
}
|
||||
*/
|
||||
|
||||
lContButton.setOnClickListener {
|
||||
onButtonClick(row, pos) // 버튼 클릭 시 Row의 position 전달
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
742
app/src/main/java/com/example/smart119/TransferManager.kt
Normal file
@ -0,0 +1,742 @@
|
||||
package com.example.smart119
|
||||
|
||||
import android.graphics.Color
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import com.example.smart119.datas.HospitalSearch
|
||||
import com.example.smart119.datas.SaveLogin
|
||||
import com.example.smart119.interfaces.RetrofitClient
|
||||
import com.example.smart119.views.FragmentHandler
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
enum class TransferState {
|
||||
IDLE, // 유휴상태
|
||||
STARTED, // 이송시작
|
||||
CANCELED, // 이송취소
|
||||
COMPLETED, // 이송완료
|
||||
END, // 이송 종료
|
||||
CHANGED // 이송변경
|
||||
}
|
||||
|
||||
enum class ETAState {
|
||||
CONTINUE, // API 계속 진행 상태
|
||||
END // API 정지 or Cancel
|
||||
}
|
||||
|
||||
object TransferManager {
|
||||
@Volatile
|
||||
private var currentState: TransferState = TransferState.IDLE
|
||||
public var serverState = AtomicBoolean(false)
|
||||
|
||||
@Volatile
|
||||
private var ETA_STATE: ETAState = ETAState.CONTINUE
|
||||
|
||||
private var transferThread: Thread? = null
|
||||
private val isRunning = AtomicBoolean(false)
|
||||
private val sleepTime: Long = 5000
|
||||
|
||||
private var isKeepFindPath = AtomicBoolean(false)
|
||||
|
||||
private var isUpdateETA = AtomicBoolean(false)
|
||||
private val updateDelayTime: Long = 10000; //5초 update eta 지연 수행 시간
|
||||
private val runningEvtListener = mutableMapOf<String, (JsonObject?) -> Unit>()
|
||||
|
||||
private var errorDefLon: Double = 127.00663305137988;
|
||||
private var errorDefLat: Double = 37.56777199202061;
|
||||
|
||||
private var _selectedHospInfo:JsonObject = JsonObject();
|
||||
|
||||
private var lastUpdateData:JsonObject = JsonObject().apply {
|
||||
addProperty("hpid", "")
|
||||
addProperty("levelState", "")
|
||||
addProperty("eta", "")
|
||||
addProperty("currentTime", "")
|
||||
addProperty("leftDistance", "")
|
||||
addProperty("transferState", "")
|
||||
};
|
||||
|
||||
fun set_transfer_data(
|
||||
hpid:String, levelState:String, eta:String,
|
||||
currentTime:String, leftDistance:String, transferState:String
|
||||
) {
|
||||
if (hpid != "") lastUpdateData.addProperty("hpid", hpid)
|
||||
if (levelState != "") lastUpdateData.addProperty("levelState", levelState)
|
||||
if (eta != "") lastUpdateData.addProperty("eta", eta)
|
||||
if (currentTime != "") lastUpdateData.addProperty("currentTime", currentTime)
|
||||
if (leftDistance != "") lastUpdateData.addProperty("leftDistance", leftDistance)
|
||||
if (transferState != "") {
|
||||
|
||||
lastUpdateData.addProperty("transferState", transferState)
|
||||
}
|
||||
}
|
||||
fun get_transfer_data():JsonObject {
|
||||
return lastUpdateData
|
||||
}
|
||||
// 이벤트 리스너 등록
|
||||
fun registerListener(key: String, listener: (JsonObject?) -> Unit) {
|
||||
if (runningEvtListener.containsKey(key)) {
|
||||
// println("Listener with key '$key' already registered.")
|
||||
} else {
|
||||
runningEvtListener[key] = listener
|
||||
// println("Listener with key '$key' registered.")
|
||||
}
|
||||
}
|
||||
|
||||
// 이벤트 발생
|
||||
private fun dispatchEvent(eventName: String, data: JsonObject? = null) {
|
||||
val listener = runningEvtListener[eventName]
|
||||
if (listener != null) {
|
||||
println("Dispatching event: $eventName")
|
||||
listener(data)
|
||||
} else {
|
||||
println("No listener registered for event: $eventName")
|
||||
}
|
||||
}
|
||||
|
||||
fun getState(): TransferState {
|
||||
return currentState
|
||||
}
|
||||
|
||||
|
||||
// 이송 시작
|
||||
fun startTransfer():Boolean {
|
||||
if (currentState == TransferState.STARTED) {
|
||||
println("Transfer is already started.")
|
||||
return false
|
||||
}
|
||||
|
||||
currentState = TransferState.STARTED
|
||||
ETA_STATE = ETAState.CONTINUE;
|
||||
isRunning.set(true)
|
||||
isKeepFindPath.set(true)
|
||||
// "/startEmergency.do" 먼저 실행 후, 결과에 따라 thread 시작
|
||||
|
||||
try {
|
||||
_SET_HOSPINFO(HospitalSearch.getSelectedData())
|
||||
UpdateTransferInfomation();
|
||||
}
|
||||
catch (e:Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
|
||||
if (API_STARTEMG()) {
|
||||
transferThread = Thread {
|
||||
println("Transfer started.")
|
||||
while (isRunning.get() && currentState == TransferState.STARTED) {
|
||||
try {
|
||||
// 이송 중 반복 작업 수행
|
||||
println("Transfer in progress... SLEEP TIME[${sleepTime}ms]")
|
||||
// 등록한 이벤트 함수로 update중인 상태 전달
|
||||
// if (!RandomNumberUtil.num_increase()) {
|
||||
// println("END!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
||||
// API_END_TRANSFER();
|
||||
// continue
|
||||
// }
|
||||
//#region 서버로부터 종료 코드를 받는 경우,
|
||||
//#endregion
|
||||
|
||||
// println("이전 데이터");
|
||||
// println(HospitalSearch.getSelectedData());
|
||||
// println("변경 데이터");
|
||||
// println(_GET_HOSPINFO());
|
||||
|
||||
Thread.sleep(sleepTime) // 1초마다 실행
|
||||
} catch (e: InterruptedException) {
|
||||
println("Transfer loop interrupted.")
|
||||
}
|
||||
}
|
||||
println("Transfer loop stopped.")
|
||||
isKeepFindPath.set(false);
|
||||
}
|
||||
|
||||
transferThread?.start()
|
||||
return true;
|
||||
} else {
|
||||
isKeepFindPath.set(false);
|
||||
SendDialogMsg("응급 이송 시작 오류", "API START시 오류 발생")
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private fun _SET_HOSPINFO(hospInfo:JsonObject?) {
|
||||
val copiedJson = JsonParser.parseString(hospInfo.toString()).asJsonObject
|
||||
_selectedHospInfo = copiedJson
|
||||
}
|
||||
|
||||
private fun _GET_HOSPINFO():JsonObject? {
|
||||
return _selectedHospInfo;
|
||||
}
|
||||
|
||||
fun SendDialogMsg(title:String, msg:String) {
|
||||
var sendMsg = JsonObject().apply {
|
||||
addProperty("title", title)
|
||||
addProperty("msg", msg)
|
||||
}
|
||||
|
||||
// val transferHandler = FragmentHandler.getView("TransferFragment");
|
||||
// if (transferHandler != null) {
|
||||
// val bottomNaviView = transferHandler.findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
// bottomNaviView.selectedItemId = R.id.hospSearch;
|
||||
// }
|
||||
dispatchEvent("transfer_dialogmsg_event", sendMsg)
|
||||
}
|
||||
|
||||
// 이송 취소
|
||||
fun cancelTransfer() {
|
||||
if (currentState != TransferState.STARTED &&
|
||||
serverState == AtomicBoolean(false)) {
|
||||
println("Cannot cancel. Transfer is not active.")
|
||||
return
|
||||
}
|
||||
|
||||
currentState = TransferState.CANCELED
|
||||
println("Transfer set CANCELED")
|
||||
API_END_TRANSFER()
|
||||
}
|
||||
|
||||
// 이송 종료
|
||||
fun completeTransfer() {
|
||||
if (currentState != TransferState.STARTED) {
|
||||
println("Cannot complete. Transfer is not active.")
|
||||
return
|
||||
}
|
||||
|
||||
currentState = TransferState.COMPLETED
|
||||
println("Transfer set COMPLETED")
|
||||
API_END_TRANSFER()
|
||||
stopTransferLoop()
|
||||
}
|
||||
|
||||
// 이송 변경
|
||||
fun changeTransfer() {
|
||||
if (currentState != TransferState.STARTED) {
|
||||
println("Cannot change. Transfer is not active.")
|
||||
return
|
||||
}
|
||||
|
||||
// currentState = TransferState.CHANGED
|
||||
///updateETDHospId.do
|
||||
println("Transfer state changed.")
|
||||
// 이송 변경에 따른 추가 작업 수행
|
||||
API_CHANGE_HOSPITAL()
|
||||
}
|
||||
|
||||
// 이송 종료 상태로 설정
|
||||
fun setEnd() {
|
||||
if (currentState == TransferState.STARTED) {
|
||||
isRunning.set(false)
|
||||
isKeepFindPath.set(false)
|
||||
transferThread?.interrupt()
|
||||
transferThread = null
|
||||
}
|
||||
currentState = TransferState.END;
|
||||
println("Transfer set to END state.")
|
||||
|
||||
SendDialogMsg("이송 종료", "응급 이송이 종료되었습니다.")
|
||||
}
|
||||
|
||||
fun setCancel() {
|
||||
isRunning.set(false)
|
||||
isKeepFindPath.set(false)
|
||||
transferThread?.interrupt()
|
||||
transferThread = null
|
||||
|
||||
currentState = TransferState.END;
|
||||
SendDialogMsg("이송 종료", "응급 이송이 취소되었습니다.")
|
||||
}
|
||||
|
||||
// IDLE 상태로 설정
|
||||
fun setIdle() {
|
||||
if (currentState == TransferState.STARTED) {
|
||||
stopTransferLoop()
|
||||
}
|
||||
currentState = TransferState.IDLE
|
||||
println("Transfer set to IDLE state.")
|
||||
}
|
||||
|
||||
// 루프 중단
|
||||
private fun stopTransferLoop() {
|
||||
isRunning.set(false)
|
||||
isKeepFindPath.set(false)
|
||||
transferThread?.interrupt()
|
||||
transferThread = null
|
||||
ETA_STATE = ETAState.END
|
||||
|
||||
currentState = TransferState.IDLE
|
||||
SendDialogMsg("응급 이송 종료", "이송이 종료되었습니다.")
|
||||
}
|
||||
|
||||
// 현재 상태 조회
|
||||
fun getCurrentState(): TransferState {
|
||||
return currentState
|
||||
}
|
||||
|
||||
//pingpong을 위한 메시지 api 수행
|
||||
private fun FindPath_ETA() {
|
||||
isUpdateETA.set(false)
|
||||
if (!isRunning.get() && currentState != TransferState.STARTED) return;
|
||||
|
||||
try {
|
||||
// val resObj = res.getAsJsonObject();
|
||||
// val callResult = resObj["isSuccess"]?.asBoolean ?: true;
|
||||
val lon = LocationHelper.getCurrentLon();
|
||||
val lat = LocationHelper.getCurrentLat();
|
||||
// val lon = resObj["lon"]?.asDouble ?: 0.0;
|
||||
// val lat = resObj["lat"]?.asDouble ?: 0.0;
|
||||
|
||||
val src_pos = "${lon}, ${lat}";
|
||||
|
||||
val selectedHospital = _GET_HOSPINFO();
|
||||
var hosp_lon = selectedHospital?.get("lon")?.asString
|
||||
var hosp_lat = selectedHospital?.get("lat")?.asString
|
||||
if (hosp_lon == "null" || hosp_lon == "") {
|
||||
hosp_lon = errorDefLon.toString()
|
||||
}
|
||||
if (hosp_lat == "null" || hosp_lat == "") {
|
||||
hosp_lat = errorDefLat.toString()
|
||||
}
|
||||
var dst_pos = "${hosp_lon}, ${hosp_lat}";
|
||||
|
||||
if (isKeepFindPath.get()) {
|
||||
HelpUtility.delay_executor(updateDelayTime) {
|
||||
RetrofitClient.pathInstance.findPath(
|
||||
API_Helper.make_findpath_param(src_pos, dst_pos)
|
||||
).enqueue(findPathResponse())
|
||||
}
|
||||
}
|
||||
else {
|
||||
UpdateTransferInfomation_TIME()
|
||||
}
|
||||
|
||||
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
// SendDialogMsg("오류 발생", "길찾기 중 오류가 발생하였습니다. ${e.message}")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun UpdateTransferInfomation_ETA(loc:JsonObject) {
|
||||
|
||||
try {
|
||||
var tfView = FragmentHandler.getView("TransferFragment")
|
||||
if (tfView != null) {
|
||||
var _eta = loc["eta"].asInt;
|
||||
var _leftDistance = loc["leftDistance"].asString
|
||||
|
||||
val currentTime = SimpleDateFormat("HH:mm:ss").format(Date())
|
||||
val updateTimeTxt = tfView.findViewById<TextView>(R.id.infoUpdateTime)
|
||||
updateTimeTxt?.text = currentTime;
|
||||
|
||||
var _hospInfo = _GET_HOSPINFO()
|
||||
//#region eta 업데이트
|
||||
if (_eta != -1 && _eta != null) {
|
||||
val etaTxt = tfView.findViewById<TextView>(R.id.tvLeftTimeVal)
|
||||
val _etaStrSec = API_Helper.ETA_SEC_TO_STRING(_eta);
|
||||
etaTxt?.text = _etaStrSec
|
||||
if (_hospInfo != null) { _hospInfo.addProperty("eta", _etaStrSec) }
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region etd 업데이트
|
||||
if (_leftDistance != "" && _leftDistance != null) {
|
||||
val etdTxt = tfView.findViewById<TextView>(R.id.tvLeftDistVal)
|
||||
val _etdStrKM = API_Helper.DISTANCE_FORMAT_METER_TO_KM(_leftDistance);
|
||||
etdTxt?.text = _etdStrKM;
|
||||
if (_hospInfo != null) { _hospInfo.addProperty("leftDistance", _etdStrKM) }
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
}
|
||||
|
||||
private fun UpdateTransferInfomation_TIME() {
|
||||
var tfView = FragmentHandler.getView("TransferFragment")
|
||||
if (tfView != null) {
|
||||
val currentTime = SimpleDateFormat("HH:mm:ss").format(Date())
|
||||
val updateTimeTxt = tfView.findViewById<TextView>(R.id.infoUpdateTime)
|
||||
updateTimeTxt?.text = currentTime
|
||||
}
|
||||
}
|
||||
|
||||
private fun UpdateTransferInfomation() {
|
||||
try {
|
||||
var tfView = FragmentHandler.getView("TransferFragment")
|
||||
if (tfView != null) {
|
||||
//병원 이름, 혼잡도
|
||||
var hosp_info = _GET_HOSPINFO();
|
||||
if (hosp_info != null) {
|
||||
println(hosp_info)
|
||||
var levelState = hosp_info["levelState"].asString
|
||||
var hospName = hosp_info["title"].asString
|
||||
|
||||
val hospNameTxt = tfView.findViewById<TextView>(R.id.tvTFHospName)
|
||||
hospNameTxt?.text = hospName
|
||||
val lidarValTxt = tfView.findViewById<TextView>(R.id.tvTFLidarValue)
|
||||
lidarValTxt?.text = levelState
|
||||
|
||||
val lLidarView : View = tfView.findViewById(R.id.tvTFLidarColor)
|
||||
lLidarView?.setBackgroundColor(
|
||||
Color.parseColor(API_Helper.lidar_levelState_Color(levelState))
|
||||
)
|
||||
|
||||
val tfStateTxt = tfView.findViewById<TextView>(R.id.tfState)
|
||||
when (currentState) {
|
||||
TransferState.IDLE -> tfStateTxt.text = "유휴 상태"
|
||||
TransferState.STARTED -> tfStateTxt.text = "이송 시작"
|
||||
TransferState.CANCELED -> tfStateTxt.text = "이송 취소"
|
||||
TransferState.COMPLETED -> tfStateTxt.text = "이송 완료"
|
||||
TransferState.END -> tfStateTxt.text = "이송 종료"
|
||||
else -> tfStateTxt.text = "-"
|
||||
}
|
||||
|
||||
println()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
}
|
||||
fun SetLastHospitalInfo() {
|
||||
try {
|
||||
var tfView = FragmentHandler.getView("TransferFragment")
|
||||
if (tfView != null) {
|
||||
//병원 이름, 혼잡도
|
||||
var hosp_info = _GET_HOSPINFO();
|
||||
if (hosp_info != null) {
|
||||
println(hosp_info)
|
||||
var levelState = hosp_info["levelState"].asString
|
||||
var hospName = hosp_info["title"].asString
|
||||
|
||||
val hospNameTxt = tfView.findViewById<TextView>(R.id.tvTFHospName)
|
||||
hospNameTxt?.text = hospName
|
||||
val lidarValTxt = tfView.findViewById<TextView>(R.id.tvTFLidarValue)
|
||||
lidarValTxt?.text = levelState
|
||||
val lLidarView : View = tfView.findViewById(R.id.tvTFLidarColor)
|
||||
lLidarView?.setBackgroundColor(
|
||||
Color.parseColor(API_Helper.lidar_levelState_Color(levelState))
|
||||
)
|
||||
|
||||
val tfStateTxt = tfView.findViewById<TextView>(R.id.tfState)
|
||||
when (currentState) {
|
||||
TransferState.IDLE -> tfStateTxt.text = "유휴 상태"
|
||||
TransferState.STARTED -> tfStateTxt.text = "이송 시작"
|
||||
TransferState.CANCELED -> tfStateTxt.text = "이송 취소"
|
||||
TransferState.COMPLETED -> tfStateTxt.text = "이송 완료"
|
||||
TransferState.END -> tfStateTxt.text = "이송 종료"
|
||||
else -> tfStateTxt.text = "-"
|
||||
}
|
||||
|
||||
var last_eta = "-";
|
||||
var last_etd = "-";
|
||||
//#region last eta 업데이트
|
||||
val etaTxt = tfView.findViewById<TextView>(R.id.tvLeftTimeVal)
|
||||
if (hosp_info["eta"] != null) {
|
||||
last_eta = hosp_info["eta"].asString
|
||||
etaTxt?.text = last_eta
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region last etd 업데이트
|
||||
val etdTxt = tfView.findViewById<TextView>(R.id.tvLeftDistVal)
|
||||
if (hosp_info["leftDistance"] != null) {
|
||||
last_etd = hosp_info["leftDistance"].asString
|
||||
etdTxt?.text = last_etd;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
UpdateTransferInfomation_TIME();
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
}
|
||||
|
||||
private fun API_STARTEMG(): Boolean {
|
||||
val selectedData = HospitalSearch.getSelectedData()
|
||||
if (selectedData != null) {
|
||||
var hpid = selectedData["hpid"].toString().trim('"')
|
||||
var reqBody = JsonObject().apply {
|
||||
addProperty("hpid", hpid)
|
||||
addProperty("hosp_name", selectedData.asJsonObject["title"].asString)
|
||||
}
|
||||
RetrofitClient.transferInstance.startEMG(reqBody).enqueue(startTransferResponse())
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
// 업데이트 ETA API 함수
|
||||
private fun API_UPDATEETA(reqBody:JsonObject): Boolean {
|
||||
// API URL : /updateETDDuration
|
||||
RetrofitClient.transferInstance.updateHospETA(reqBody).enqueue(updateETAResponse())
|
||||
return false;
|
||||
}
|
||||
|
||||
private fun API_CHANGE_HOSPITAL(): Boolean {
|
||||
val selectedData = HospitalSearch.getSelectedData()
|
||||
if (selectedData != null) {
|
||||
var _sel_hpid = selectedData["hpid"].asString
|
||||
var _updateETDhospId_body = JsonObject().apply {
|
||||
addProperty("hpid", _sel_hpid)
|
||||
addProperty("hosp_name", selectedData.asJsonObject["title"].asString)
|
||||
}
|
||||
RetrofitClient.transferInstance.changeHospital(_updateETDhospId_body).enqueue(changeHospitalResponse())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private fun API_END_TRANSFER(): Boolean {
|
||||
RetrofitClient.transferInstance.endEMG().enqueue(endTransferResponse())
|
||||
return true;
|
||||
}
|
||||
|
||||
private fun startTransferResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) { //200 ok
|
||||
val resBody = response.body();
|
||||
if (resBody != null) {
|
||||
var _status = resBody.get("status")?.asString;
|
||||
//response.status = "success" or "duplicate"
|
||||
if (_status == "success") {
|
||||
UpdateTransferInfomation()
|
||||
FindPath_ETA();
|
||||
println("이송 시작 [onResponse - Success] : ${response.message()}")
|
||||
}
|
||||
else {
|
||||
println("이송 시작 [onResponse - Fail] : ${response.message()}")
|
||||
//검색창, 다시 환자 정보 전송
|
||||
SendDialogMsg("동일한 환자정보가 이미 존재합니다",
|
||||
"같은 차량으로 동일한 환자정보가 이미 전송되어 있습니다.")
|
||||
// nav_to_hospsearch();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
} else { //200 아닌 코드들
|
||||
println("이송 시작 [onResponse - Fail] : ${response.message()}")
|
||||
val parseBody = JsonParser.parseString(response.errorBody()?.string())
|
||||
if (parseBody != null) {
|
||||
val resStatus = parseBody.asJsonObject["status"].asString
|
||||
if (resStatus == "duplicate") {
|
||||
SendDialogMsg("환자정보 전송 실패",
|
||||
"같은 차량으로 동일한 환자정보가 이미 전송되어 있습니다.")
|
||||
clear_state();
|
||||
}
|
||||
else {
|
||||
SendDialogMsg("환자정보 전송 실패",
|
||||
"알수없는 오류로 전송에 실패하였습니다. 담당자에게 문의해주세요.")
|
||||
clear_state();
|
||||
}
|
||||
}
|
||||
else {
|
||||
SendDialogMsg("환자정보 전송 실패",
|
||||
"알수없는 오류로 전송에 실패하였습니다. 담당자에게 문의해주세요.")
|
||||
clear_state();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
println("이송 시작 [onFailure] ${t.message}")
|
||||
SendDialogMsg("환자 정보 전송 실패",
|
||||
"알수없는 오류로 전송에 실패하였습니다. 담당자에게 문의해주세요.")
|
||||
clear_state();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 업데이트 ETA API 결과
|
||||
private fun updateETAResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
var resBody = response.body()
|
||||
var _status = resBody?.get("status")?.asString;
|
||||
if (_status == "continue") {
|
||||
FindPath_ETA();
|
||||
println("API_ETA_TRANSFER[onResponse - Success] : ${response.message()}")
|
||||
}
|
||||
else {
|
||||
//이송 종료 처리
|
||||
if (currentState != TransferState.END) setEnd()
|
||||
}
|
||||
} else {
|
||||
println("API_ETA_TRANSFER[onResponse - Fail] : ${response.message()}")
|
||||
isKeepFindPath.set(false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
//대부분 네트워크 문제
|
||||
println("API_ETA_TRANSFER[OnFailure] : ${t.message}")
|
||||
isKeepFindPath.set(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 업데이트 ETA API 결과
|
||||
private fun changeHospitalResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
try {
|
||||
_SET_HOSPINFO(HospitalSearch.getSelectedData())
|
||||
UpdateTransferInfomation();
|
||||
}
|
||||
catch (e:Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
println("API_CHANGE_HOSPITAL[onResponse - Success] : ${response.message()}")
|
||||
} else {
|
||||
println("API_CHANGE_HOSPITAL[onResponse - Fail] : ${response.message()}")
|
||||
isKeepFindPath.set(false)
|
||||
SendDialogMsg("병원 정보 변경 실패",
|
||||
"알수없는 오류로 전송에 실패하였습니다. 담당자에게 문의해주세요.")
|
||||
clear_state();
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
// ETA_STATE = ETAState.END //?
|
||||
println("API_CHANGE_HOSPITAL[onFailure] : ${t.message}")
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 업데이트 ETA API 결과
|
||||
private fun endTransferResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
var resBody = response.body()
|
||||
var _status = resBody?.get("status")?.asString;
|
||||
setCancel()
|
||||
} else {
|
||||
// ETA_STATE = ETAState.END //?
|
||||
println("API_END_TRANSFER[onResponse - Fail] : ${response.message()}")
|
||||
isKeepFindPath.set(false)
|
||||
clear_state()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
// ETA_STATE = ETAState.END //?
|
||||
//대부분 네트워크 문제
|
||||
// println("API_END_TRANSFER[OnFailure] : ${t.message}")
|
||||
isKeepFindPath.set(false)
|
||||
clear_state()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//길찾기 API 결과
|
||||
private fun findPathResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
try {
|
||||
var resBody = response.body()
|
||||
var routes = resBody?.get("routes")?.asJsonArray
|
||||
if (routes != null && routes.size() > 0) {
|
||||
var f_route = routes[0].asJsonObject;
|
||||
var res_code = f_route["result_code"].asString
|
||||
when(res_code) {
|
||||
"0" -> {
|
||||
var f_summary = f_route["summary"].asJsonObject
|
||||
var _distance = f_summary["distance"].asString;
|
||||
var _duration = f_summary["duration"].asString;
|
||||
var _updateETA = JsonObject().apply {
|
||||
addProperty("leftDistance", _distance)
|
||||
addProperty("eta", _duration)
|
||||
}
|
||||
|
||||
//duration : 초, distance : 미터
|
||||
println("distance : ${_distance}km, duration : ${_duration}sec")
|
||||
UpdateTransferInfomation_ETA(_updateETA)
|
||||
|
||||
var _updateETA_body = JsonObject().apply {
|
||||
addProperty("duration", _duration)
|
||||
}
|
||||
API_UPDATEETA(_updateETA_body)
|
||||
}
|
||||
"1" -> FindPath_ETA() // 길찾기 결과를 찾을 수 없음, 종료
|
||||
"101" -> FindPath_ETA() // 경유지 지점 주변의 도로를 탐색할 수 없음, 계속 찾기
|
||||
"102" -> FindPath_ETA() // 시작 지점 주변의 도로를 탐색할 수 없음, 계속 찾기
|
||||
"103" -> FindPath_ETA() // 도착 지점 주변의 도로를 탐색할 수 없음, 계속 찾기
|
||||
"104" -> isKeepFindPath.set(false) // 출발지와 도착지가 5 m 이내로 설정된 경우 경로를 탐색할 수 없음, 이 경우엔 패스
|
||||
"105" -> FindPath_ETA() // 시작 지점 주변의 도로에 유고 정보(교통 장애)가 있음, 계속 찾기
|
||||
"106" -> FindPath_ETA() // 도착 지점 주변의 도로에 유고 정보(교통 장애)가 있음, 계속 찾기
|
||||
"107" -> FindPath_ETA() // 경유지 주변의 도로에 유고 정보(교통 장애)가 있음, 계속 찾기
|
||||
else -> FindPath_ETA() // 길찾기 시 알수 없는 코드가 나왔을때,
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
isKeepFindPath.set(false)
|
||||
}
|
||||
} else {
|
||||
println("길찾기 결과[Fail] : ${response.message()}")
|
||||
isKeepFindPath.set(false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
//대부분 네트워크 문제
|
||||
println("길찾기 결과[OnFailure] : ${t.message}")
|
||||
isKeepFindPath.set(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun nav_to_login() {
|
||||
val activity = AlertDialogUtil.getActivityContext()
|
||||
if (activity != null) {
|
||||
AlertDialogUtil.showAlert_OK(
|
||||
context = activity,
|
||||
title = "세션 만료",
|
||||
message = "기존 세션이 만료되었습니다. 다시 로그인 해주시기 바랍니다.\n",
|
||||
onPositiveClick = {
|
||||
SaveLogin.setLogin(false)
|
||||
LoginManager.setLoggedIn(false);
|
||||
val bottomNaviView =
|
||||
activity.findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
bottomNaviView.selectedItemId = R.id.emgLogin;
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun nav_to_hospsearch() {
|
||||
val activity = AlertDialogUtil.getActivityContext()
|
||||
val bottomNav = activity?.findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
if (bottomNav != null &&
|
||||
bottomNav.selectedItemId != R.id.hospSearch
|
||||
){
|
||||
bottomNav.selectedItemId = R.id.hospSearch
|
||||
}
|
||||
}
|
||||
|
||||
fun clear_state() {
|
||||
currentState = TransferState.IDLE
|
||||
isRunning.set(false)
|
||||
isKeepFindPath.set(false)
|
||||
transferThread?.interrupt()
|
||||
transferThread = null
|
||||
println("Logout, Clear Transfer State.")
|
||||
}
|
||||
}
|
20
app/src/main/java/com/example/smart119/ViewPagerAdapter.kt
Normal file
@ -0,0 +1,20 @@
|
||||
package com.example.smart119
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import com.example.smart119.views.AddressSearchFragment
|
||||
import com.example.smart119.views.LocationSearchFragment
|
||||
|
||||
class ViewPagerAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
|
||||
override fun getItemCount(): Int = 2 // 탭 개수
|
||||
|
||||
override fun createFragment(position: Int): Fragment {
|
||||
return when (position) {
|
||||
0 -> AddressSearchFragment()
|
||||
1 -> LocationSearchFragment()
|
||||
else -> AddressSearchFragment()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
484
app/src/main/java/com/example/smart119/datas/HospitalSearch.kt
Normal file
@ -0,0 +1,484 @@
|
||||
package com.example.smart119.datas
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.Toast
|
||||
import com.example.smart119.R
|
||||
import com.example.smart119.interfaces.RetrofitClient
|
||||
import com.example.smart119.views.FragmentHandler
|
||||
import com.example.smart119.views.HospitalInfoPopup
|
||||
import com.example.smart119.views.HospitalSearchPopup
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
object HospitalSearch {
|
||||
private val savedHospList: MutableList<JsonObject> = mutableListOf()
|
||||
private var selectedHospitalIdx: Int = -1
|
||||
private var bUsedFilter: Boolean = false
|
||||
private var gpsAddress:String = "";
|
||||
private var hospDetail = mutableMapOf(
|
||||
"isTransfer" to false,
|
||||
"info" to mutableMapOf<String, Any>()
|
||||
)
|
||||
private val DEF_SEARCH:JsonObject = JsonObject().apply {
|
||||
addProperty("sidoName", "서울특별시")
|
||||
addProperty("sidoCode", "11")
|
||||
}
|
||||
private var prevLon:Double = 0.0;
|
||||
private var prevLat:Double = 0.0;
|
||||
private var prevTime:Long = 0;
|
||||
|
||||
private var requestBody:JsonObject = JsonObject().apply {
|
||||
addProperty("bFilter", false)
|
||||
add("reqBody", JsonObject())
|
||||
}
|
||||
|
||||
private lateinit var popupSearch: PopupWindow;
|
||||
|
||||
private var sidoInfo:JsonObject = JsonObject().apply {
|
||||
addProperty("isLoaded", false)
|
||||
}
|
||||
private var gunGuInfo:JsonObject = JsonObject().apply {
|
||||
addProperty("isLoaded", false)
|
||||
}
|
||||
private var eubMyeonDongInfo:JsonObject = JsonObject().apply {
|
||||
addProperty("isLoaded", false)
|
||||
}
|
||||
private var gunGuNameList:MutableList<String> = mutableListOf()
|
||||
|
||||
private var gunGuSelect:String = "군구선택";
|
||||
private var hospCatSelect:String = "병원분류명선택";
|
||||
private var prtSelect:String = "진료과목선택";
|
||||
|
||||
private var addrFilterSave:JsonObject = JsonObject().apply {
|
||||
addProperty("si", "")
|
||||
addProperty("gu", "")
|
||||
addProperty("relate", "")
|
||||
}
|
||||
|
||||
//true면 주소검색 사용, false면 위경도 검색 사용
|
||||
fun SET_SearchRequest(isAddress:Boolean, reqBody:JsonObject) {
|
||||
requestBody.addProperty("bFilter", isAddress)
|
||||
requestBody.add("reqBody", reqBody)
|
||||
}
|
||||
fun GET_SearchRequest():JsonObject {
|
||||
return requestBody;
|
||||
}
|
||||
|
||||
fun isAddressSearch():Boolean {
|
||||
return requestBody.get("bFilter")?.asBoolean ?: false
|
||||
}
|
||||
|
||||
fun setPrevGPSUpdate(lon:Double, lat:Double, time:Long) {
|
||||
prevLon = lon;
|
||||
prevLat = lat;
|
||||
prevTime = time;
|
||||
println("updated!!! ${prevLon}, ${prevLat}, ${prevTime}")
|
||||
}
|
||||
fun getPrevGPSInfo():JsonObject {
|
||||
return JsonObject().apply {
|
||||
addProperty("prevLon", prevLon)
|
||||
addProperty("prevLat", prevLat)
|
||||
addProperty("prevTime", prevTime)
|
||||
}
|
||||
}
|
||||
|
||||
fun itemStructure(
|
||||
hpid: String = "", // 병원 아이디
|
||||
levelState: String = "", // lidar 레벨
|
||||
distance: String = "", // 거리
|
||||
city: String = "", // 시
|
||||
district: String = "", // 구
|
||||
tel: String = "", // 전화번호
|
||||
title: String = "", // 병원 이름
|
||||
lon: String = "", // 경도
|
||||
lat: String = "" // 위도
|
||||
// name: String = "",
|
||||
// address: String = "",
|
||||
// phoneNumber: String = "",
|
||||
// lidarState: String = ""
|
||||
):JsonObject {
|
||||
return JsonObject().apply({
|
||||
addProperty("hpid", hpid)
|
||||
addProperty("levelState", levelState)
|
||||
addProperty("distance", distance)
|
||||
addProperty("city", city)
|
||||
addProperty("district", district)
|
||||
addProperty("tel", tel)
|
||||
addProperty("title", title)
|
||||
addProperty("lon", lon)
|
||||
addProperty("lat", lat)
|
||||
})
|
||||
}
|
||||
|
||||
fun init_hospital_req(context:Context) {
|
||||
var sidoData = sidoInfo.getAsJsonObject("data");
|
||||
//비어있는 경우에만 요청하여 얻기
|
||||
if (sidoData == null || sidoData.entrySet().isEmpty()) {
|
||||
//1. 시 관련 콤보박스 먼저 얻기
|
||||
RetrofitClient.locInstance.getSidoList().enqueue(sidoResponse())
|
||||
}
|
||||
}
|
||||
|
||||
fun get_gps_address():String {
|
||||
return gpsAddress
|
||||
}
|
||||
|
||||
fun set_gps_update(address:String) {
|
||||
if(gpsAddress.isEmpty()) {
|
||||
gpsAddress = address
|
||||
}
|
||||
}
|
||||
|
||||
fun set_selectGunGu(gunGu:String = "군구선택") {
|
||||
gunGuSelect = gunGu
|
||||
}
|
||||
fun get_selectGunGu():String {
|
||||
return gunGuSelect
|
||||
}
|
||||
|
||||
fun set_selectHospCatAddress(hospCat:String = "병원분류명선택") {
|
||||
hospCatSelect = hospCat
|
||||
}
|
||||
fun get_selectHospCatAddress():String {
|
||||
return hospCatSelect
|
||||
}
|
||||
|
||||
fun set_selectPrtAddress(prt:String = "진료과목선택") {
|
||||
prtSelect = prt
|
||||
}
|
||||
fun get_selectPrtAddress():String {
|
||||
return prtSelect
|
||||
}
|
||||
|
||||
fun set_popup_search(searchPopup:PopupWindow) {
|
||||
popupSearch = searchPopup
|
||||
}
|
||||
fun get_popup_search(): PopupWindow {
|
||||
return popupSearch
|
||||
}
|
||||
|
||||
fun req_gun_list(si:String) {
|
||||
RetrofitClient.locInstance.getSiGunGuList(JsonObject().apply {
|
||||
addProperty("code", get_si_code(si) ?: "")
|
||||
}).enqueue(siGunGuResponse())
|
||||
}
|
||||
|
||||
private fun get_si_code(si:String): String {
|
||||
return sidoInfo["data"].asJsonObject["${si}"].asString
|
||||
}
|
||||
|
||||
private fun _itemStructure_IDX(
|
||||
idx: Int = 0,
|
||||
hpid: String = "", // 병원 아이디
|
||||
levelState: String = "", // lidar 레벨
|
||||
distance: String = "", // 거리
|
||||
city: String = "", // 시
|
||||
district: String = "", // 구
|
||||
tel: String = "", // 전화번호
|
||||
title: String = "", // 병원 이름
|
||||
lon: String = "", // 경도
|
||||
lat: String = "" // 위도
|
||||
):JsonObject {
|
||||
return JsonObject().apply({
|
||||
addProperty("idx", idx)
|
||||
addProperty("hpid", hpid)
|
||||
addProperty("levelState", levelState)
|
||||
addProperty("distance", distance)
|
||||
addProperty("city", city)
|
||||
addProperty("district", district)
|
||||
addProperty("tel", tel)
|
||||
addProperty("title", title)
|
||||
addProperty("lon", lon)
|
||||
addProperty("lat", lat)
|
||||
})
|
||||
}
|
||||
// JsonObject 추가
|
||||
fun addData(jsonObject: JsonObject) {
|
||||
savedHospList.add(jsonObject)
|
||||
}
|
||||
|
||||
fun setSearchFilter(si:String, gu:String, relate:String) {
|
||||
addrFilterSave.addProperty("si", when(si) {"시도선택" -> "" else -> si })
|
||||
addrFilterSave.addProperty("gu", when(gu){"구군선택" -> "" else -> gu })
|
||||
addrFilterSave.addProperty("relate", relate)
|
||||
}
|
||||
|
||||
fun setFiltered(bFiltered:Boolean) {
|
||||
bUsedFilter = bFiltered;
|
||||
}
|
||||
|
||||
fun getSearchInfo():JsonObject {
|
||||
return addrFilterSave;
|
||||
}
|
||||
|
||||
fun getIsFiltered():Boolean {
|
||||
return bUsedFilter
|
||||
}
|
||||
|
||||
fun addDataHospitalItems(hospList:List<JsonObject>) {
|
||||
var idx = 0;
|
||||
hospList.forEach{
|
||||
hosp ->
|
||||
var rebuild = _itemStructure_IDX(
|
||||
idx++,
|
||||
hosp["hpid"].toString().trim('"'),
|
||||
hosp["levelState"].toString().trim('"'),
|
||||
hosp["distance"].toString().trim('"'),
|
||||
hosp["city"].toString().trim('"'),
|
||||
hosp["district"].toString().trim('"'),
|
||||
hosp["tel"].toString().trim('"'),
|
||||
hosp["title"].toString().trim('"'),
|
||||
hosp["lon"].toString().trim('"'),
|
||||
hosp["lat"].toString().trim('"')
|
||||
)
|
||||
savedHospList.add(rebuild)
|
||||
}
|
||||
// println(savedHospList);
|
||||
}
|
||||
|
||||
// 인덱스로 JsonObject 가져오기
|
||||
fun getData(index: Int): JsonObject? {
|
||||
return if (index in savedHospList.indices) savedHospList[index] else null
|
||||
}
|
||||
|
||||
fun setIdx(idx:Int) {
|
||||
selectedHospitalIdx = idx
|
||||
}
|
||||
|
||||
fun getSelectedData(): JsonObject? {
|
||||
if (selectedHospitalIdx != -1) {
|
||||
// var returnData = JsonObject().apply { }
|
||||
val returnData = savedHospList.getOrNull(selectedHospitalIdx)
|
||||
return returnData
|
||||
}
|
||||
else return null
|
||||
}
|
||||
|
||||
//region hospital detail용 함수
|
||||
fun getHospitalID():String {
|
||||
if (selectedHospitalIdx != -1) {
|
||||
val returnData = savedHospList.getOrNull(selectedHospitalIdx)
|
||||
return returnData?.get("hpid")?.asString ?: "";
|
||||
}
|
||||
else return ""
|
||||
}
|
||||
fun setHospitalDetail(info:JsonObject) {
|
||||
hospDetail["info"] = info;
|
||||
}
|
||||
fun getHospitalDetail():Any? {
|
||||
return hospDetail["info"]
|
||||
}
|
||||
//endregion
|
||||
|
||||
fun getAllData(withIndex:Boolean = false):List<List<String>> {
|
||||
val setDataList:MutableList<List<String>> = mutableListOf()
|
||||
savedHospList.forEach {
|
||||
json ->
|
||||
if(withIndex) {
|
||||
val address =
|
||||
json["city"].toString().replace("\"", "") + " " +
|
||||
json["district"].toString().replace("\"", "")
|
||||
setDataList.apply {
|
||||
add(
|
||||
listOf(
|
||||
json["idx"].toString().replace("\"", ""),
|
||||
json["title"].toString().replace("\"", ""),
|
||||
address,
|
||||
json["tel"].toString().replace("\"", ""),
|
||||
json["levelState"].toString().replace("\"", ""),
|
||||
json["distance"].toString().replace("\"", "") + "km"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
else {
|
||||
val address =
|
||||
json["city"].toString().replace("\"", "") + " " +
|
||||
json["district"].toString().replace("\"", "")
|
||||
setDataList.apply {
|
||||
add(
|
||||
listOf(
|
||||
json["title"].toString().replace("\"", ""),
|
||||
address,
|
||||
json["tel"].toString().replace("\"", ""),
|
||||
json["levelState"].toString().replace("\"", ""),
|
||||
json["distance"].toString().replace("\"", "") + "km"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return setDataList
|
||||
}
|
||||
|
||||
fun clearAllData() {
|
||||
selectedHospitalIdx = 0;
|
||||
savedHospList.clear()
|
||||
}
|
||||
|
||||
private fun sidoResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
val jsonObject = response.body();
|
||||
var dataSet = JsonObject()
|
||||
// println("sido response success ${jsonObject}");
|
||||
if (jsonObject != null) {
|
||||
val resDatas = jsonObject["resData"].asJsonArray;
|
||||
resDatas.forEach { data ->
|
||||
val _sicode = data.asJsonObject["sidoCode"].asString
|
||||
val _siname = data.asJsonObject["sidoName"].asString
|
||||
dataSet.addProperty(_siname, _sicode)
|
||||
}
|
||||
}
|
||||
//loaded true, data set
|
||||
sidoInfo.addProperty("isLoaded", true)
|
||||
sidoInfo.add("data", dataSet)
|
||||
|
||||
//#region 현재 서울시를 중점으로 하기 때문에, 기본 코드 API요청
|
||||
req_gun_list(DEF_SEARCH["sidoName"].asString)
|
||||
//#endregion
|
||||
|
||||
} else {
|
||||
println("sido response but fail");
|
||||
sidoDeafult()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
println("sido response fail ${t.message}");
|
||||
sidoDeafult()
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun sidoDeafult() {
|
||||
|
||||
var dataSet = JsonObject()
|
||||
val default_si = DEF_SEARCH["sidoName"].asString;
|
||||
val default_siCode = DEF_SEARCH["sidoCode"].asString;
|
||||
dataSet.addProperty(default_si, default_siCode)
|
||||
|
||||
sidoInfo.addProperty("isLoaded", false)
|
||||
sidoInfo.add("data", dataSet)
|
||||
|
||||
req_gun_list(default_si)
|
||||
}
|
||||
fun GET_SIDO_DEFAULT_NAME():String {
|
||||
return DEF_SEARCH["sidoName"].asString
|
||||
}
|
||||
fun GET_SIDO_DEFAULT_CODE():String {
|
||||
return DEF_SEARCH["sidoCode"].asString
|
||||
}
|
||||
|
||||
fun getSidoList():List<String> {
|
||||
var returnList: List<String> = mutableListOf()
|
||||
if (sidoInfo["isLoaded"].asBoolean) {
|
||||
var sidoJsonObject = sidoInfo.getAsJsonObject("data")
|
||||
returnList = sidoJsonObject.entrySet().map { it.key }
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
fun getGunGuNameList():MutableList<String> {
|
||||
return gunGuNameList.toMutableList();
|
||||
}
|
||||
|
||||
private fun siGunGuResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
val jsonObject = response.body();
|
||||
var dataSet = JsonObject();
|
||||
// println("sido response success ${jsonObject}");
|
||||
if (jsonObject != null) {
|
||||
val resDatas = jsonObject["resData"].asJsonArray;
|
||||
resDatas.forEach { data ->
|
||||
val _guguncode = data.asJsonObject["code"].asString
|
||||
val _gugunName = data.asJsonObject["name"].asString
|
||||
dataSet.addProperty(_gugunName, _guguncode)
|
||||
gunGuNameList.add(_gugunName)
|
||||
}
|
||||
}
|
||||
//loaded true, data set
|
||||
|
||||
gunGuInfo.addProperty("isLoaded", true)
|
||||
gunGuInfo.add("data", dataSet)
|
||||
|
||||
//세팅 구군 리스트
|
||||
// var hsfView = FragmentHandler.getView("HospitalSearchFragment")
|
||||
// if (hsfView != null) {
|
||||
// nameList.add(0, "구군선택")
|
||||
// HospitalSearchPopup.set_POPUP_GUGUN_COMBO(popupSearch, hsfView.context, nameList)
|
||||
// }
|
||||
} else {
|
||||
println("gugun response but fail");
|
||||
SEOUL_DEFAULT_GUNGU()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
println("gugun response fail ${t.message}");
|
||||
SEOUL_DEFAULT_GUNGU()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun siEubMyeonDongResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun SEOUL_DEFAULT_GUNGU() {
|
||||
var dataSet = JsonObject();
|
||||
var nameList:MutableList<String> = mutableListOf()
|
||||
|
||||
dataSet.addProperty("11680","강남구")
|
||||
dataSet.addProperty("11740","강동구")
|
||||
dataSet.addProperty("11305","강북구")
|
||||
dataSet.addProperty("11500","강서구")
|
||||
dataSet.addProperty("11620","관악구")
|
||||
dataSet.addProperty("11215","광진구")
|
||||
dataSet.addProperty("11530","구로구")
|
||||
dataSet.addProperty("11545","금천구")
|
||||
dataSet.addProperty("11350","노원구")
|
||||
dataSet.addProperty("11320","도봉구")
|
||||
dataSet.addProperty("11230","동대문구")
|
||||
dataSet.addProperty("11590","동작구")
|
||||
dataSet.addProperty("11440","마포구")
|
||||
dataSet.addProperty("11410","서대문구")
|
||||
dataSet.addProperty("11650","서초구")
|
||||
dataSet.addProperty("11200","성동구")
|
||||
dataSet.addProperty("11290","성북구")
|
||||
dataSet.addProperty("11710","송파구")
|
||||
dataSet.addProperty("11470","양천구")
|
||||
dataSet.addProperty("11560","영등포구")
|
||||
dataSet.addProperty("11170","용산구")
|
||||
dataSet.addProperty("11380","은평구")
|
||||
dataSet.addProperty("11110","종로구")
|
||||
dataSet.addProperty("11140","중구")
|
||||
dataSet.addProperty("11260","중랑구")
|
||||
|
||||
for((key, value) in dataSet.entrySet()) {
|
||||
gunGuNameList.add(value.asString)
|
||||
}
|
||||
|
||||
gunGuInfo.addProperty("isLoaded", false)
|
||||
gunGuInfo.add("data", dataSet)
|
||||
|
||||
println();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package com.example.smart119.datas
|
||||
|
||||
object SampleLocation {
|
||||
}
|
38
app/src/main/java/com/example/smart119/datas/SaveLogin.kt
Normal file
@ -0,0 +1,38 @@
|
||||
package com.example.smart119.datas
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
|
||||
object SaveLogin {
|
||||
private const val PREF_119_NAME = "SMART119_LOGIN"
|
||||
private const val KEY_IS_LOGGED_IN = "isLoggedIn"
|
||||
private const val KEY_STR_USER_ID = "strUserId"
|
||||
private const val KEY_STR_CAR_NO = "strCarNo"
|
||||
|
||||
private lateinit var preferences: SharedPreferences
|
||||
|
||||
fun init(context: Context) {
|
||||
preferences = context.getSharedPreferences(PREF_119_NAME, Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
fun setLogin(isLoggedIn:Boolean) {
|
||||
preferences.edit().putBoolean(KEY_IS_LOGGED_IN, isLoggedIn).apply()
|
||||
}
|
||||
fun setUserId(strUserId:String) {
|
||||
preferences.edit().putString(KEY_STR_USER_ID, strUserId).apply()
|
||||
}
|
||||
fun setCarNo(strCarNo:String) {
|
||||
preferences.edit().putString(KEY_STR_CAR_NO, strCarNo).apply()
|
||||
}
|
||||
|
||||
fun getUserId(): String? {
|
||||
return preferences.getString(KEY_STR_USER_ID, null)
|
||||
}
|
||||
fun getCarNo(): String? {
|
||||
return preferences.getString(KEY_STR_CAR_NO, null)
|
||||
}
|
||||
|
||||
fun isLoggedIn(): Boolean {
|
||||
return preferences.getBoolean(KEY_IS_LOGGED_IN, false)
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.example.smart119.interfaces
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.QueryMap
|
||||
|
||||
interface apiFindPath {
|
||||
@GET("/findPath")
|
||||
fun findPath(
|
||||
@QueryMap params: Map<String, String>
|
||||
) : Call<JsonObject>
|
||||
|
||||
@GET("/getAddr")
|
||||
fun getAddr(
|
||||
@QueryMap params: Map<String, String>
|
||||
) : Call<JsonObject>
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.example.smart119.interfaces
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
|
||||
interface apiHospital {
|
||||
@POST("hospitalDetail.do")
|
||||
fun getDetail(
|
||||
@Body requestBody: JsonObject
|
||||
) : Call<JsonObject>
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.example.smart119.interfaces
|
||||
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import com.google.gson.JsonObject
|
||||
import retrofit2.http.Body
|
||||
|
||||
interface apiLocation {
|
||||
@POST("/selectSidoList.do")
|
||||
fun getSidoList() : Call<JsonObject>
|
||||
|
||||
@POST("/selectSiGunGuList.do")
|
||||
fun getSiGunGuList(
|
||||
@Body requestBody: JsonObject
|
||||
) : Call<JsonObject>
|
||||
|
||||
//body
|
||||
//SIDO_CODE
|
||||
//SI_GUN_GU_CODE
|
||||
@POST("/selectEubMyeonDongList.do")
|
||||
fun getEubMyeonDongList(
|
||||
@Body requestBody: JsonObject
|
||||
) : Call<JsonObject>
|
||||
|
||||
@POST("/radiusSearchHospital2.do")
|
||||
fun getAroundHospitalList(
|
||||
@Body requestBody: JsonObject
|
||||
) : Call<JsonObject>
|
||||
|
||||
@POST("/searchHospital.do")
|
||||
fun getAddressHospitalList(
|
||||
@Body requestBody: JsonObject
|
||||
) : Call<JsonObject>
|
||||
|
||||
|
||||
/*
|
||||
//유연하게 사용할 때 아래와 같이 사용
|
||||
@GET("path/to/endpoint")
|
||||
|
||||
//param 날리는 방식 1
|
||||
fun getSiGunGuList(
|
||||
@QueryMap options: Map<String, String>
|
||||
): Call<JsonObject>
|
||||
|
||||
|
||||
//param 날리는 방식 2
|
||||
fun getSiGunGuList(
|
||||
@Query("SIDO_CODE") param1: String
|
||||
) : Call<JsonObject>
|
||||
|
||||
val params = mapOf(
|
||||
"key1" to "value1",
|
||||
"key2" to "123"
|
||||
)
|
||||
RetrofitClient.apiService.getSiGunGuList(params).enqueue(/* Callback */)
|
||||
*/
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.example.smart119.interfaces
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.POST
|
||||
|
||||
interface apiLogin {
|
||||
@POST("mobileLogin.do")
|
||||
fun mLogin(
|
||||
@Body requestBody: JsonObject
|
||||
) : Call<JsonObject>
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.example.smart119.interfaces
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
|
||||
interface apiTransfer {
|
||||
@POST("startEmergency.do")
|
||||
fun startEMG(
|
||||
@Body requestBody: JsonObject
|
||||
) : Call<JsonObject>
|
||||
|
||||
@POST("updateETDHospId.do")
|
||||
fun changeHospital(
|
||||
@Body requestBody: JsonObject
|
||||
) : Call<JsonObject>
|
||||
|
||||
@POST("updateETDDuration.do")
|
||||
fun updateHospETA(
|
||||
@Body requestBody: JsonObject
|
||||
) : Call<JsonObject>
|
||||
|
||||
@GET("endEmergency.do")
|
||||
fun endEMG() : Call<JsonObject>
|
||||
|
||||
@POST("cookie")
|
||||
fun cookieSend() : Call<JsonObject>
|
||||
|
||||
@GET("currentInAction.do")
|
||||
fun currentAction() : Call<JsonObject>
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.example.smart119.interfaces
|
||||
|
||||
import com.example.smart119.MyCookieJar
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
|
||||
object CookieInterCeptor : Interceptor {
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
var request = chain.request()
|
||||
|
||||
// 요청 헤더에서 Cookie 확인
|
||||
val cookies = request.header("Cookie")
|
||||
|
||||
println("Request URL: ${request.url()}")
|
||||
if (cookies != null) {
|
||||
println("Cookies in Request: $cookies")
|
||||
} else {
|
||||
println("No cookies in Request.")
|
||||
|
||||
// val cookies = listOf(
|
||||
// "sessionId=abc123",
|
||||
// "csrfToken=xyz456",
|
||||
// "userId=789"
|
||||
// )
|
||||
val cookies = MyCookieJar.getCustomCookies()
|
||||
|
||||
if(cookies.size > 0) {
|
||||
request = request.newBuilder()
|
||||
// .addHeader("Cookie", "sessionId=abc123")
|
||||
.addHeader("Cookie", cookies.joinToString("; ")) // 수동으로 쿠키 추가
|
||||
.build()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// request = request.newBuilder()
|
||||
// .addHeader("Cookie", "sessionId=abc123")
|
||||
//// .addHeader("Cookie", cookies.joinToString("; ")) // 수동으로 쿠키 추가
|
||||
// .build()
|
||||
|
||||
return chain.proceed(request)
|
||||
}
|
||||
}
|
@ -0,0 +1,166 @@
|
||||
package com.example.smart119.interfaces
|
||||
|
||||
import com.example.smart119.MyCookieJar
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import okhttp3.Cookie
|
||||
import okhttp3.OkHttpClient
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import javax.net.ssl.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
object RetrofitClient {
|
||||
private const val HOST_IP_TEST = "192.168.0.20"
|
||||
private const val HOST_PORT_TEST = "8080"
|
||||
private const val BASE_URL_HTTP_TEST = "http://${HOST_IP_TEST}:${HOST_PORT_TEST}"
|
||||
|
||||
//#region 테스트용 ip
|
||||
|
||||
|
||||
//#region 일반 백엔드 api 설정
|
||||
private const val HOST_IP = "112.219.147.186"
|
||||
private const val HOST_PORT = "8085"
|
||||
private const val BASE_URL = "http://${HOST_IP}:${HOST_PORT}"
|
||||
//#endregion
|
||||
//#region nginx url 설정
|
||||
private const val NGINX_PORT = "1000"
|
||||
private const val NGINX_BASE_URL = "http://${HOST_IP}:${NGINX_PORT}"
|
||||
//#endregion
|
||||
//#endregion
|
||||
|
||||
/*
|
||||
//#region 소방본부 서버용 ip
|
||||
//#region 일반 백엔드 api 설정
|
||||
private const val HOST_IP = "210.104.143.125"
|
||||
private const val HOST_PORT = "8085"
|
||||
private const val BASE_URL = "http://${HOST_IP}:${HOST_PORT}"
|
||||
//#endregion
|
||||
//#region nginx url 설정
|
||||
private const val NGINX_IP = "210.104.143.125"
|
||||
private const val NGINX_PORT = "1000"
|
||||
private const val NGINX_BASE_URL = "http://${NGINX_IP}:${NGINX_PORT}"
|
||||
//#endregion
|
||||
//http://210.104.143.125:8085/
|
||||
//#endregion
|
||||
*/
|
||||
|
||||
private const val BASE_URL_HTTP = "http://${HOST_IP}:${HOST_PORT}"
|
||||
private const val HTTP_URL_COOKIE = "http://192.168.0.20:3000"
|
||||
|
||||
// 신뢰할 수 없는 인증서를 허용하는 OkHttpClient
|
||||
private fun getUnsafeOkHttpClient(): OkHttpClient {
|
||||
return try {
|
||||
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
|
||||
override fun checkClientTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {}
|
||||
override fun checkServerTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {}
|
||||
override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> = arrayOf()
|
||||
})
|
||||
|
||||
val sslContext = SSLContext.getInstance("TLS")
|
||||
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
|
||||
val sslSocketFactory = sslContext.socketFactory
|
||||
|
||||
OkHttpClient.Builder()
|
||||
.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
|
||||
.hostnameVerifier { _, _ -> true } // 모든 호스트 이름 허용
|
||||
.addInterceptor(CookieInterCeptor)
|
||||
.connectTimeout(10, TimeUnit.SECONDS) // 서버 연결 Timeout (기본 10초 → 30초)
|
||||
.readTimeout(10, TimeUnit.SECONDS) // 서버 응답 Timeout (기본 10초 → 30초)
|
||||
.writeTimeout(10, TimeUnit.SECONDS) // 서버 요청 Timeout (기본 10초 → 30초)
|
||||
.build()
|
||||
} catch (e: Exception) {
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getUnsafeOkHttpClient_http(): OkHttpClient {
|
||||
return try {
|
||||
OkHttpClient.Builder()
|
||||
.addInterceptor(CookieInterCeptor)
|
||||
.connectTimeout(10, TimeUnit.SECONDS) // 서버 연결 Timeout (기본 10초 → 30초)
|
||||
.readTimeout(10, TimeUnit.SECONDS) // 서버 응답 Timeout (기본 10초 → 30초)
|
||||
.writeTimeout(10, TimeUnit.SECONDS) // 서버 요청 Timeout (기본 10초 → 30초)
|
||||
.build()
|
||||
} catch (e: Exception) {
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
}
|
||||
|
||||
private val retrofit: Retrofit by lazy {
|
||||
Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
// .client(getUnsafeOkHttpClient()) // 신뢰할 수 없는 인증서 허용 https
|
||||
.client(getUnsafeOkHttpClient_http())
|
||||
.addConverterFactory(GsonConverterFactory.create()) // Gson Converter 추가
|
||||
.build()
|
||||
}
|
||||
|
||||
private val retrofit_NGINX: Retrofit by lazy {
|
||||
Retrofit.Builder()
|
||||
.baseUrl(NGINX_BASE_URL)
|
||||
.client(getUnsafeOkHttpClient()) // 신뢰할 수 없는 인증서 허용
|
||||
.addConverterFactory(GsonConverterFactory.create()) // Gson Converter 추가
|
||||
.build()
|
||||
}
|
||||
|
||||
private val retrofit_HTTP: Retrofit by lazy {
|
||||
Retrofit.Builder()
|
||||
.baseUrl(BASE_URL_HTTP)
|
||||
.client(getUnsafeOkHttpClient()) // 신뢰할 수 없는 인증서 허용
|
||||
.addConverterFactory(GsonConverterFactory.create()) // Gson Converter 추가
|
||||
.build()
|
||||
}
|
||||
|
||||
private val retrofit_HTTP_TEST: Retrofit by lazy {
|
||||
Retrofit.Builder()
|
||||
.baseUrl(BASE_URL_HTTP_TEST)
|
||||
.client(getUnsafeOkHttpClient()) // 신뢰할 수 없는 인증서 허용
|
||||
.addConverterFactory(GsonConverterFactory.create()) // Gson Converter 추가
|
||||
.build()
|
||||
}
|
||||
|
||||
//cookie 테스트용 retrofit
|
||||
private val retrofit_COOKIE: Retrofit by lazy {
|
||||
Retrofit.Builder()
|
||||
.baseUrl(HTTP_URL_COOKIE)
|
||||
.client(getUnsafeOkHttpClient()) // 신뢰할 수 없는 인증서 허용
|
||||
.addConverterFactory(GsonConverterFactory.create()) // Gson Converter 추가
|
||||
.build()
|
||||
}
|
||||
|
||||
val locInstance: apiLocation by lazy {
|
||||
retrofit.create(apiLocation::class.java)
|
||||
}
|
||||
|
||||
val loginInstance: apiLogin by lazy {
|
||||
retrofit.create(apiLogin::class.java)
|
||||
// retrofit_HTTP.create(apiLogin::class.java)
|
||||
// retrofit_HTTP_TEST.create(apiLogin::class.java)
|
||||
}
|
||||
|
||||
val transferInstance: apiTransfer by lazy {
|
||||
retrofit.create(apiTransfer::class.java)
|
||||
// retrofit_HTTP.create(apiTransfer::class.java)
|
||||
// retrofit_HTTP_TEST.create(apiTransfer::class.java)
|
||||
}
|
||||
|
||||
val pathInstance: apiFindPath by lazy {
|
||||
retrofit_NGINX.create(apiFindPath::class.java)
|
||||
}
|
||||
|
||||
// val cookieInstance: apiTransfer by lazy {
|
||||
// retrofit_COOKIE.create(apiTransfer::class.java)
|
||||
// }
|
||||
|
||||
val hospitalInstance:apiHospital by lazy {
|
||||
retrofit.create(apiHospital::class.java)
|
||||
}
|
||||
|
||||
fun parseJsonFromBuffer(buffer: ByteArray): JsonObject {
|
||||
val jsonString = buffer.toString(Charsets.UTF_8)
|
||||
val jsonElement = JsonParser.parseString(jsonString)
|
||||
return jsonElement.asJsonObject
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.example.smart119.viewModel
|
||||
|
||||
import android.security.identity.ResultData
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class TransferViewModel: ViewModel() {
|
||||
private val _someLiveData = MutableLiveData<ResultData>()
|
||||
val someLiveData:LiveData<ResultData> = _someLiveData
|
||||
|
||||
fun requestData() {
|
||||
viewModelScope.launch {
|
||||
// try {
|
||||
// val result = TransferRepository.getData()
|
||||
// _someLiveData.value = result
|
||||
// } catch (e: Exception) {
|
||||
// // 에러 처리
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,690 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.StyleSpan
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Button
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.smart119.API_Helper
|
||||
import com.example.smart119.AlertDialogUtil
|
||||
import com.example.smart119.ListItem
|
||||
import com.example.smart119.LoginManager
|
||||
import com.example.smart119.MedicalInfo
|
||||
import com.example.smart119.R
|
||||
import com.example.smart119.SpreadsheetAdapter
|
||||
import com.example.smart119.TransferManager
|
||||
import com.example.smart119.TransferState
|
||||
import com.example.smart119.datas.HospitalSearch
|
||||
import com.example.smart119.datas.SaveLogin
|
||||
import com.example.smart119.interfaces.RetrofitClient
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.gson.JsonObject
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import java.util.*
|
||||
|
||||
class AddressSearchFragment : Fragment() {
|
||||
|
||||
private lateinit var asAdapter: SpreadsheetAdapter
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
return inflater.inflate(R.layout.address_search_page, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
FragmentHandler.registerView("AddressSearchFragment", view)
|
||||
|
||||
hospitalInit(view);
|
||||
HospitalSearch.clearAllData()
|
||||
|
||||
//#region 광역시/도 콤보박스 설정
|
||||
val siItems = mutableListOf(HospitalSearch.GET_SIDO_DEFAULT_NAME())
|
||||
val siSpinner: Spinner = view.findViewById(R.id.siSelectSpinner)
|
||||
val arrAdapterSi =
|
||||
ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, siItems)
|
||||
siSpinner.adapter = arrAdapterSi;
|
||||
//#endregion
|
||||
// //#region 시/군/구 콤보박스 설정
|
||||
// val gunGuItems = HospitalSearch.getGunGuNameList()
|
||||
// val guGunSpinner: Spinner = view.findViewById(R.id.guGunSelectSpinner)
|
||||
// val arrAdapterGuGun = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, gunGuItems)
|
||||
// guGunSpinner.adapter = arrAdapterGuGun;
|
||||
// //#endregion
|
||||
|
||||
val searchButtonAS = view.findViewById<Button>(R.id.hospSearchButtonAS)
|
||||
searchButtonAS.setOnClickListener {
|
||||
address_hospital_search(view);
|
||||
}
|
||||
|
||||
val gugunSelectorTV = view.findViewById<TextView>(R.id.gunGuSelectText)
|
||||
gugunSelectorTV.setOnClickListener {
|
||||
GunGuSelector_Dialog.show(requireContext())
|
||||
}
|
||||
|
||||
val hospCatTV = view.findViewById<TextView>(R.id.hospCatText)
|
||||
hospCatTV.setOnClickListener {
|
||||
HospitalCategoryAddress_Dialog.show(requireContext())
|
||||
}
|
||||
|
||||
val prtTV = view.findViewById<TextView>(R.id.prtText)
|
||||
prtTV.setOnClickListener {
|
||||
DepartmentAddress_Dialog.show(requireContext())
|
||||
}
|
||||
|
||||
val prevASButton = view.findViewById<Button>(R.id.pagePrevAS)
|
||||
prevASButton.setOnClickListener {
|
||||
if (HospitalSearch.getAllData().size > 0) {
|
||||
var bChanged = PaginationHelper.prevPage(requireView(), { page ->
|
||||
page_onclick_listener(page)
|
||||
})
|
||||
//request page
|
||||
if (bChanged) {
|
||||
var currPage = PaginationHelper.currentPage;
|
||||
// println("prev request number ${PaginationHelper.currentPage}")
|
||||
page_onclick_listener(currPage)
|
||||
}
|
||||
// else println("no request prev")
|
||||
}
|
||||
}
|
||||
|
||||
val nextASButton = view.findViewById<Button>(R.id.pageNextAS)
|
||||
nextASButton.setOnClickListener {
|
||||
if (HospitalSearch.getAllData().size > 0) {
|
||||
var bChanged = PaginationHelper.nextPage(requireView(), { page ->
|
||||
page_onclick_listener(page)
|
||||
})
|
||||
//request page
|
||||
if (bChanged) {
|
||||
var currPage = PaginationHelper.currentPage;
|
||||
// println("next request number ${PaginationHelper.currentPage}")
|
||||
page_onclick_listener(currPage)
|
||||
}
|
||||
// else println("no request next")
|
||||
}
|
||||
}
|
||||
|
||||
GunGuSelector_Dialog.registerCallback { evtString ->
|
||||
println("군구 선택 이벤트!! ${evtString}")
|
||||
address_hospital_search(view);
|
||||
}
|
||||
|
||||
HospitalCategoryAddress_Dialog.registerCallback { evtString ->
|
||||
println("병원분류명 선택 이벤트!! ${evtString}")
|
||||
}
|
||||
|
||||
DepartmentAddress_Dialog.registerCallback { evtString ->
|
||||
println("진료과목 선택 이벤트!! ${evtString}")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun address_hospital_search(view: View) {
|
||||
asAdapter.clearHospitalList();
|
||||
HospitalSearch.clearAllData();
|
||||
|
||||
var filter_si = "서울특별시";//searchObject["si"].asString;
|
||||
var filter_gu = "";//searchObject["gu"].asString;
|
||||
var filter_relate = "";//searchObject["relate"].asString;
|
||||
var sPage = "1";
|
||||
var sRow = "4";
|
||||
var filter_qd = ""; // 병원분류코드
|
||||
var filter_qz = ""; // 진료과목코드
|
||||
|
||||
val siSpin = view.findViewById<Spinner>(R.id.siSelectSpinner);
|
||||
val gunSpin = view.findViewById<Spinner>(R.id.guGunSelectSpinner);
|
||||
val editText = view.findViewById<TextInputEditText>(R.id.relateInput)
|
||||
filter_si = siSpin.selectedItem.toString()
|
||||
filter_gu =
|
||||
view.findViewById<TextView>(R.id.gunGuSelectText).text.toString()//HospitalSearch.get_selectGunGu()//gunSpin.selectedItem.toString()
|
||||
filter_qz =
|
||||
view.findViewById<TextView>(R.id.hospCatText).text.toString()//HospitalSearch.get_selectHospCatAddress()
|
||||
filter_qd =
|
||||
view.findViewById<TextView>(R.id.prtText).text.toString()//HospitalSearch.get_selectPrtAddress()
|
||||
filter_relate = editText.text.toString()
|
||||
|
||||
//#region 항목별 코드 변환
|
||||
filter_qz = MedicalInfo.get_addressQZ_code(filter_qz).toString()
|
||||
filter_qd = MedicalInfo.get_prt_code(filter_qd).toString()
|
||||
//#endregion
|
||||
|
||||
if (filter_gu == "null" || filter_gu == "군구선택") {
|
||||
filter_gu = ""
|
||||
}
|
||||
if (filter_qz == "null" || filter_qz == "병원분류명선택") {
|
||||
filter_qz = ""
|
||||
}
|
||||
if (filter_qd == "null" || filter_qd == "진료과목선택") {
|
||||
filter_qd = ""
|
||||
}
|
||||
if (filter_relate == "null") {
|
||||
filter_relate = ""
|
||||
}
|
||||
|
||||
println("${filter_si}, ${filter_gu}, ${filter_qz}, ${filter_qd}, ${filter_relate}")
|
||||
|
||||
var reqBody: JsonObject = API_Helper.make_addressHosp_param(
|
||||
filter_si, filter_gu, filter_qd, filter_qz, filter_relate,
|
||||
sPage, sRow
|
||||
);
|
||||
try {
|
||||
LoadingDialog.showDlg(requireContext())
|
||||
HospitalSearch.SET_SearchRequest(true, reqBody)
|
||||
RetrofitClient.locInstance.getAddressHospitalList(reqBody)
|
||||
.enqueue(getAddressResponse())
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
LoadingDialog.hideDlg()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
// Toast.makeText(requireContext(), "위치기반 탭 활성화!", Toast.LENGTH_SHORT).show()
|
||||
// println("주소기반 탭 활성화!")
|
||||
|
||||
//#region 서남병원으로 요청 고정
|
||||
try {
|
||||
// RetrofitClient.transferInstance.currentAction().enqueue(currentActionResponse())
|
||||
|
||||
LoadingDialog.showDlg(requireContext())
|
||||
var reqBody: JsonObject = API_Helper.make_addressHosp_param(
|
||||
"서울특별시", "", "", "", "서남병원",
|
||||
"1", "4"
|
||||
);
|
||||
RetrofitClient.locInstance.getAddressHospitalList(reqBody)
|
||||
.enqueue(getAddressResponse())
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
LoadingDialog.hideDlg()
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
// println("주소기반 탭 비 활성화!")
|
||||
asAdapter.clearHospitalList()
|
||||
HospitalSearch.clearAllData()
|
||||
PaginationHelper.setupPaginationLayout(
|
||||
requireView(),
|
||||
0, 0, { page ->
|
||||
page_onclick_listener(page)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun getAddressResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
LoadingDialog.hideDlg()
|
||||
if (response.isSuccessful) {
|
||||
val resBody = response.body();
|
||||
if (resBody != null) {
|
||||
set_hospital_list(resBody)
|
||||
} else {
|
||||
nav_to_login();
|
||||
}
|
||||
} else {
|
||||
nav_to_login();
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
LoadingDialog.hideDlg()
|
||||
println(t.message)
|
||||
nav_to_login();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hospitalInit(view: View) {
|
||||
var items = listOf(
|
||||
ListItem.Header(listOf("병원이름")), // 헤더 열 정의
|
||||
ListItem.Header(listOf("주소")),
|
||||
ListItem.Header(listOf("전화번호")),
|
||||
ListItem.Header(listOf("라이다 혼잡도")),
|
||||
ListItem.Header(listOf("거리")),
|
||||
ListItem.Header(listOf("병원별 이송 시작"))
|
||||
)
|
||||
val recyclerViewLS: RecyclerView = view.findViewById(R.id.reCyclerViewLS)
|
||||
|
||||
val spanCount = 6;
|
||||
asAdapter = SpreadsheetAdapter(
|
||||
items,
|
||||
onButtonClick = { row, pos ->
|
||||
//row.values[0]
|
||||
asAdapter.setSelectedHospitalPos(pos)
|
||||
HospitalSearch.setIdx(asAdapter.getSelectedPosition())
|
||||
var selectedHospital = asAdapter.getSelectedHospital()
|
||||
var getSelData = HospitalSearch.getSelectedData()
|
||||
if (selectedHospital is ListItem.Row) {
|
||||
var hospitalName = selectedHospital.values[0];
|
||||
var hospitalAddress = selectedHospital.values[1];
|
||||
var hospitalCallNumber = selectedHospital.values[2];
|
||||
var hospitalLiDAR = selectedHospital.values[3];
|
||||
var hospitalDistance = selectedHospital.values[4];
|
||||
if (TransferManager.getState() == TransferState.STARTED) {
|
||||
//이송 변경
|
||||
//변경된 병원 정보 설정
|
||||
val spannableMessage = SpannableStringBuilder().apply {
|
||||
val preText = "병원 이름 : ${hospitalName}" + "\n" +
|
||||
"주소 : ${hospitalAddress}" + "\n" +
|
||||
"전화번호 : ${hospitalCallNumber}" + "\n" +
|
||||
"라이다혼잡도 : ${hospitalLiDAR}" + "\n"
|
||||
append(preText)
|
||||
|
||||
val boldText = "확인"
|
||||
append(boldText)
|
||||
setSpan(
|
||||
StyleSpan(Typeface.BOLD), preText.length,
|
||||
preText.length + boldText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
append(" 선택시 환자정보가 전송됩니다.(변경 시 기존 이송 병원이 변경됩니다.)\n")
|
||||
}
|
||||
|
||||
AlertDialogUtil.showAlert_CUSTOM(
|
||||
context = requireActivity(),
|
||||
title = "이송 병원 정보",
|
||||
sppStr = spannableMessage,
|
||||
onPositiveClick = {
|
||||
AlertDialogUtil.showAlert_OK(
|
||||
context = requireActivity(),
|
||||
title = "진행 전 확인사항",
|
||||
message = "진행하시기 전에, 구급활동일지 임시저장을 하셨는지 확인해 주세요\n",
|
||||
onPositiveClick = {
|
||||
val bottomNaviView =
|
||||
requireActivity().findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
bottomNaviView.selectedItemId = R.id.hospTransfer;
|
||||
TransferManager.changeTransfer()
|
||||
}
|
||||
)
|
||||
|
||||
},
|
||||
onNegativeClick = {}
|
||||
)
|
||||
} else {
|
||||
val spannableMessage = SpannableStringBuilder().apply {
|
||||
val preText = "병원 이름 : ${hospitalName}" + "\n" +
|
||||
"주소 : ${hospitalAddress}" + "\n" +
|
||||
"전화번호 : ${hospitalCallNumber}" + "\n" +
|
||||
"라이다혼잡도 : ${hospitalLiDAR}" + "\n"
|
||||
append(preText)
|
||||
|
||||
val boldText = "확인"
|
||||
append(boldText)
|
||||
setSpan(
|
||||
StyleSpan(Typeface.BOLD), preText.length,
|
||||
preText.length + boldText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
append(" 선택시 환자정보가 전송됩니다.\n")
|
||||
}
|
||||
AlertDialogUtil.showAlert_CUSTOM(
|
||||
context = requireActivity(),
|
||||
title = "이송 병원 정보",
|
||||
sppStr = spannableMessage,
|
||||
onPositiveClick = {
|
||||
AlertDialogUtil.showAlert_OK(
|
||||
context = requireActivity(),
|
||||
title = "진행 전 확인사항",
|
||||
message = "진행하시기 전에, 구급활동일지 임시저장을 하셨는지 확인해 주세요\n",
|
||||
onPositiveClick = {
|
||||
if (TransferManager.startTransfer()) {
|
||||
val bottomNaviView =
|
||||
requireActivity().findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
bottomNaviView.selectedItemId = R.id.hospTransfer;
|
||||
} else {
|
||||
// 시작되지 않았습니다.
|
||||
Toast.makeText(
|
||||
requireActivity(), "이송이 시작되지 않았습니다. 다시 전송해주세요.",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
onNegativeClick = {}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "선택된 병원 정보",
|
||||
message = "병원 검색 후 선택해주세요!"
|
||||
)
|
||||
}
|
||||
//pos, row(ListItem상 선택 위치, 선택한 row 정보) -> hpid는?
|
||||
},
|
||||
onRowClick = { row ->
|
||||
// Toast.makeText(requireActivity(), "${row.values[0]}이 선택되었습니다.", Toast.LENGTH_SHORT)
|
||||
// .show()
|
||||
}
|
||||
)
|
||||
asAdapter.setColumnCount(spanCount)
|
||||
recyclerViewLS.adapter = asAdapter
|
||||
|
||||
// GridLayoutManager 설정
|
||||
val layoutManager = GridLayoutManager(requireActivity(), spanCount)
|
||||
layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
// return if (adapter.getItemViewType(position) == SpreadsheetAdapter.VIEW_TYPE_HEADER) 3 else 1
|
||||
return if (asAdapter.getItemViewType(position) == SpreadsheetAdapter.VIEW_TYPE_ROW) {
|
||||
spanCount // Row가 전체 열을 차지하도록 설정
|
||||
} else {
|
||||
1 // 기본적으로 각 항목은 한 열을 차지
|
||||
}
|
||||
}
|
||||
}
|
||||
recyclerViewLS.layoutManager = layoutManager
|
||||
}
|
||||
|
||||
fun set_hospital_list(resobj: JsonObject?) {
|
||||
var totPages = resobj?.get("totalPages") // 총 페이지
|
||||
var totRows = resobj?.get("totalRows") // 총 행 개수
|
||||
var searchRows = resobj?.get("row") // 검색 페이지 행 개수
|
||||
var searchPage = resobj?.get("page") // 검색 페이지 번호
|
||||
var resData = resobj?.getAsJsonArray("resData")
|
||||
var dataSize = resData?.size() ?: 0;
|
||||
|
||||
var hospitalSearchRes: List<List<String>> = mutableListOf()
|
||||
var hpidList: MutableList<String> = mutableListOf()
|
||||
if (dataSize > 0) {
|
||||
// region 검색 결과 리스트에 세팅
|
||||
try {
|
||||
resData?.forEach { item ->
|
||||
val itemObj = item.asJsonObject;
|
||||
var levelState =
|
||||
API_Helper.lidar_levelState(itemObj.get("levelState").asInt)
|
||||
var itemHpid = itemObj.get("hpid").toString().trim('"');
|
||||
hpidList.add(itemHpid)
|
||||
var itemDistance = ""
|
||||
var itemTel = ""
|
||||
var itemTitle = ""
|
||||
itemTel = itemObj.get("dutyTel1").toString().trim('"')
|
||||
itemTitle = itemObj.get("dutyName").toString().trim('"')
|
||||
|
||||
var itemLon = itemObj.get("wgs84Lon").toString().trim('"');
|
||||
var itemLat = itemObj.get("wgs84Lat").toString().trim('"');
|
||||
|
||||
HospitalSearch.addDataHospitalItems(
|
||||
listOf(
|
||||
HospitalSearch.itemStructure(
|
||||
itemHpid, levelState, itemDistance,
|
||||
itemObj.get("city").toString().trim('"'),
|
||||
itemObj.get("district").toString().trim('"'),
|
||||
itemTel, itemTitle, itemLon, itemLat
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
var total_Page = totPages?.asInt;
|
||||
if (total_Page == null) total_Page = 0;
|
||||
var total_Row = totRows?.asInt;
|
||||
if (total_Row == null) total_Row = 0;
|
||||
PaginationHelper.setupPaginationLayout(
|
||||
requireView(),
|
||||
total_Page,
|
||||
total_Row,
|
||||
{ page ->
|
||||
page_onclick_listener(page)
|
||||
})
|
||||
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(requireActivity(), "${e.message}", Toast.LENGTH_LONG)
|
||||
.show()
|
||||
} finally {
|
||||
}
|
||||
|
||||
hospitalSearchRes = HospitalSearch.getAllData();
|
||||
} else {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "병원 검색 결과",
|
||||
message = "병원이 검색되지 않았습니다. 다시 시도해주세요."
|
||||
)
|
||||
|
||||
if (!PaginationHelper.pageRequest) PaginationHelper.setupPaginationLayout(
|
||||
requireView(),
|
||||
0, 0, { page ->
|
||||
page_onclick_listener(page)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
//병원 검색 결과 설정
|
||||
if (hospitalSearchRes.size > 0) asAdapter.hospitalListUpdate(hospitalSearchRes, hpidList)
|
||||
// endregion
|
||||
}
|
||||
|
||||
private fun page_onclick_listener(page: Int) {
|
||||
// println("clicked page ${page}")
|
||||
var reqBody = HospitalSearch.GET_SearchRequest()
|
||||
if (reqBody != null) {
|
||||
try {
|
||||
// if (HospitalSearch.isAddressSearch()) {
|
||||
LoadingDialog.showDlg(requireContext())
|
||||
reqBody = reqBody.getAsJsonObject("reqBody")
|
||||
reqBody.addProperty("page", "${page}")
|
||||
RetrofitClient.locInstance.getAddressHospitalList(reqBody).enqueue(
|
||||
getAddress_Paging_Response()
|
||||
)
|
||||
// } else {
|
||||
// LoadingDialog.showDlg(requireContext())
|
||||
// reqBody = reqBody.getAsJsonObject("reqBody")
|
||||
// reqBody.addProperty("page", "${page}")
|
||||
// RetrofitClient.locInstance.getAroundHospitalList(reqBody)
|
||||
// .enqueue(arroundHospital_Paging_Response())
|
||||
// }
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
LoadingDialog.hideDlg()
|
||||
} finally {
|
||||
// LoadingDialog.hideDlg()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAddress_Paging_Response(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
LoadingDialog.hideDlg()
|
||||
if (response.isSuccessful) {
|
||||
val resBody = response.body();
|
||||
if (resBody != null) {
|
||||
set_hospital_list_page(resBody)
|
||||
} else {
|
||||
nav_to_login();
|
||||
}
|
||||
|
||||
} else {
|
||||
nav_to_login();
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
LoadingDialog.hideDlg()
|
||||
println(t.message)
|
||||
nav_to_login();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun set_hospital_list_page(resobj: JsonObject?) {
|
||||
// region 현재 병원 리스트 초기화
|
||||
asAdapter.clearHospitalList();
|
||||
HospitalSearch.clearAllData();
|
||||
// endregion
|
||||
|
||||
var totPages = resobj?.get("totalPages") // 총 페이지
|
||||
var totRows = resobj?.get("totalRows") // 총 행 개수
|
||||
var searchRows = resobj?.get("row") // 검색 페이지 행 개수
|
||||
var searchPage = resobj?.get("page") // 검색 페이지 번호
|
||||
var resData = resobj?.getAsJsonArray("resData")
|
||||
var dataSize = resData?.size() ?: 0;
|
||||
|
||||
var hospitalSearchRes: List<List<String>> = mutableListOf()
|
||||
var hpidList: MutableList<String> = mutableListOf()
|
||||
if (dataSize > 0) {
|
||||
// region 검색 결과 리스트에 세팅
|
||||
try {
|
||||
resData?.forEach { item ->
|
||||
val itemObj = item.asJsonObject;
|
||||
var levelState =
|
||||
API_Helper.lidar_levelState(itemObj.get("levelState").asInt)
|
||||
var itemHpid = itemObj.get("hpid").toString().trim('"');
|
||||
hpidList.add(itemHpid)
|
||||
var itemDistance = ""
|
||||
var itemTel = ""
|
||||
var itemTitle = ""
|
||||
///주소 검색 시 사용하는 곳
|
||||
itemTel = itemObj.get("dutyTel1").toString().trim('"')
|
||||
itemTitle = itemObj.get("dutyName").toString().trim('"')
|
||||
var itemLon = itemObj.get("wgs84Lon").toString().trim('"');
|
||||
var itemLat = itemObj.get("wgs84Lat").toString().trim('"');
|
||||
|
||||
HospitalSearch.addDataHospitalItems(
|
||||
listOf(
|
||||
HospitalSearch.itemStructure(
|
||||
itemHpid, levelState, itemDistance,
|
||||
itemObj.get("city").toString().trim('"'),
|
||||
itemObj.get("district").toString().trim('"'),
|
||||
itemTel, itemTitle, itemLon, itemLat
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
var total_Page = totPages?.asInt;
|
||||
if (total_Page == null) total_Page = 0;
|
||||
var total_Row = totRows?.asInt;
|
||||
if (total_Row == null) total_Row = 0;
|
||||
|
||||
// PaginationHelper.rePaginationLayout(requireView(), { page ->
|
||||
// page_onclick_listener(page)
|
||||
// })
|
||||
// PaginationHelper.setupPaginationLayout(requireView(), total_Page, total_Row, { page ->
|
||||
// page_onclick_listener(page)
|
||||
// })
|
||||
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(requireActivity(), "${e.message}", Toast.LENGTH_LONG)
|
||||
.show()
|
||||
} finally {
|
||||
}
|
||||
|
||||
hospitalSearchRes = HospitalSearch.getAllData();
|
||||
} else {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "병원 검색 결과",
|
||||
message = "병원이 검색되지 않았습니다. 다시 시도해주세요."
|
||||
)
|
||||
|
||||
if (!PaginationHelper.pageRequest) PaginationHelper.setupPaginationLayout(
|
||||
requireView(),
|
||||
0, 0, { page ->
|
||||
page_onclick_listener(page)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
//병원 검색 결과 설정
|
||||
if (hospitalSearchRes.size > 0) asAdapter.hospitalListUpdate(hospitalSearchRes, hpidList)
|
||||
// endregion
|
||||
}
|
||||
|
||||
// fun req_gun_list(si:String) {
|
||||
// RetrofitClient.locInstance.getSiGunGuList(JsonObject().apply {
|
||||
// addProperty("code", get_si_code(si) ?: "")
|
||||
// }).enqueue(siGunGuResponse())
|
||||
// }
|
||||
|
||||
fun nav_to_login() {
|
||||
AlertDialogUtil.showAlert_OK(
|
||||
context = requireActivity(),
|
||||
title = "세션 만료",
|
||||
message = "기존 세션이 만료되었습니다. 다시 로그인 해주시기 바랍니다.\n",
|
||||
onPositiveClick = {
|
||||
SaveLogin.setLogin(false)
|
||||
LoginManager.setLoggedIn(false);
|
||||
val bottomNaviView =
|
||||
requireActivity().findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
bottomNaviView.selectedItemId = R.id.emgLogin;
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun get_default_seonam(): JsonObject {
|
||||
var seonam: JsonObject = JsonObject().apply {
|
||||
addProperty("userId", "")
|
||||
addProperty("carNo", "")
|
||||
addProperty("ver", "")
|
||||
}
|
||||
|
||||
return seonam;
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
FragmentHandler.unregisterView("AddressSearchFragment")
|
||||
}
|
||||
|
||||
private fun currentActionResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
try {
|
||||
val resBody = response.body();
|
||||
val status = resBody?.get("status")?.asString;
|
||||
if (status == "true") {
|
||||
TransferManager.serverState.set(true);
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireContext(),
|
||||
title = "진행 중인 전송 정보",
|
||||
message = "현재 접속 정보로 진행중인 이송 건이 있습니다. 취소하시겠습니까?",
|
||||
onPositiveClick = {
|
||||
TransferManager.cancelTransfer()
|
||||
},
|
||||
onNegativeClick = {}
|
||||
)
|
||||
//시작된 상황
|
||||
}
|
||||
else {
|
||||
println();
|
||||
TransferManager.serverState.set(false);
|
||||
//시작 아닌 상황
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
|
||||
} else {
|
||||
println();
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
println();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.GridView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import com.example.smart119.MedicalInfo
|
||||
import com.example.smart119.R
|
||||
import com.example.smart119.datas.HospitalSearch
|
||||
|
||||
object DepartmentAddress_Dialog {
|
||||
private var dialog: Dialog? = null
|
||||
private var selectCallback: ((String) -> Unit)? = null
|
||||
|
||||
fun show(context: Context) {
|
||||
dialog?.dismiss() // 기존 다이얼로그가 있으면 닫기 (중복 방지)
|
||||
dialog = Dialog(context)
|
||||
|
||||
val dialogView = LayoutInflater.from(context).inflate(R.layout.department_address, null)
|
||||
dialog?.setContentView(dialogView)
|
||||
|
||||
dialog?.window?.setLayout(1000, 800) // width, height (픽셀 단위)
|
||||
|
||||
|
||||
// val gridView: GridView = dialogView.findViewById(R.id.gridViewOptions)
|
||||
// val closeButton: Button = dialogView.findViewById(R.id.dialogCloseButton)
|
||||
|
||||
// 그리드에 표시할 데이터
|
||||
// var options = MedicalInfo.get_prt_list()
|
||||
// options.add(0, "진료과목선택")
|
||||
|
||||
val itemClickListener: (String) -> Unit = { item ->
|
||||
HospitalSearch.set_selectPrtAddress(item)
|
||||
var addrView = FragmentHandler.getView("AddressSearchFragment")
|
||||
if (addrView != null) {
|
||||
val prtTV = addrView.findViewById<TextView>(R.id.prtText)
|
||||
prtTV.text = item;
|
||||
}
|
||||
Toast.makeText(context, "선택된 항목: $item", Toast.LENGTH_SHORT).show()
|
||||
|
||||
triggerEvent(item)
|
||||
}
|
||||
|
||||
val getGroups = MedicalInfo.get_prt_group_map();
|
||||
if (getGroups.size > 0) {
|
||||
getGroups.forEach { key, value ->
|
||||
val group_name = key;
|
||||
val group_list = value;
|
||||
addGroup(
|
||||
dialogView, context,
|
||||
group_name, group_list,
|
||||
itemClickListener
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// val adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, options)
|
||||
// gridView.adapter = adapter
|
||||
//
|
||||
// // 아이템 클릭 이벤트 (선택 시 다이얼로그 닫기)
|
||||
// gridView.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ ->
|
||||
// try {
|
||||
// val selectedOption = options[position]
|
||||
// HospitalSearch.set_selectPrtAddress(selectedOption)
|
||||
// var addrView = FragmentHandler.getView("AddressSearchFragment")
|
||||
// if (addrView != null) {
|
||||
// val prtTV = addrView.findViewById<TextView>(R.id.prtText)
|
||||
// prtTV.text = selectedOption;
|
||||
// }
|
||||
// Toast.makeText(context, "선택된 항목: $selectedOption", Toast.LENGTH_SHORT).show()
|
||||
//
|
||||
// triggerEvent(selectedOption)
|
||||
// } catch (e: Exception) {
|
||||
// println(e.message)
|
||||
// }
|
||||
// dismiss() // 아이템 선택 즉시 다이얼로그 닫기
|
||||
// }
|
||||
|
||||
dialog?.setOnCancelListener {
|
||||
//진료과 선택
|
||||
var addrView = FragmentHandler.getView("AddressSearchFragment")
|
||||
if (addrView != null) {
|
||||
val prtTV = addrView.findViewById<TextView>(R.id.prtText)
|
||||
prtTV.text = "진료과목선택";
|
||||
}
|
||||
}
|
||||
|
||||
dialog?.show()
|
||||
}
|
||||
private fun addGroup(
|
||||
view: View, context: Context, groupName: String, items: List<String>, callback: (String) -> Unit
|
||||
) {
|
||||
val container = view.findViewById<LinearLayout>(R.id.departGroupContainer)
|
||||
|
||||
// 그룹 레이아웃 생성 (LinearLayout)
|
||||
val groupLayout = LinearLayout(context).apply {
|
||||
layoutParams = LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
orientation = LinearLayout.VERTICAL
|
||||
setPadding(0, 4, 0, 4)
|
||||
}
|
||||
|
||||
// 그룹명 (TextView)
|
||||
val textView = TextView(context).apply {
|
||||
text = groupName
|
||||
textSize = 25f
|
||||
setTypeface(null, Typeface.BOLD)
|
||||
setPadding(0, 0, 0, 4)
|
||||
}
|
||||
|
||||
// 구분선 (View)
|
||||
val divider = View(context).apply {
|
||||
layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
2 // 두께
|
||||
)
|
||||
setBackgroundColor(Color.GRAY)
|
||||
}
|
||||
|
||||
// GridView 생성
|
||||
val gridView = GridView(context).apply {
|
||||
layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
stretchMode = GridView.STRETCH_COLUMN_WIDTH
|
||||
gravity = Gravity.CENTER
|
||||
this.numColumns = GridView.AUTO_FIT
|
||||
verticalSpacing = 8
|
||||
horizontalSpacing = 8
|
||||
}
|
||||
|
||||
// GridView 어댑터 설정
|
||||
// val adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, items)
|
||||
val adapter = object : ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, items) {
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val view = super.getView(position, convertView, parent) as TextView
|
||||
view.textSize = 20f // 텍스트 크기 조정
|
||||
return view
|
||||
}
|
||||
}
|
||||
gridView.adapter = adapter
|
||||
|
||||
gridView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
|
||||
val selectedItem = parent.getItemAtPosition(position) as String
|
||||
callback(selectedItem)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
// GridView 높이 자동 조절 함수
|
||||
fun setGridViewHeight(gridView: GridView) {
|
||||
val listAdapter = gridView.adapter ?: return
|
||||
val totalItems = listAdapter.count
|
||||
val numColumns = gridView.numColumns
|
||||
val rows = Math.ceil(totalItems / numColumns.toDouble()).toInt()
|
||||
|
||||
val itemHeight = 80 // px 단위 (아이템 하나의 높이)
|
||||
val params = gridView.layoutParams
|
||||
params.height = rows * itemHeight
|
||||
gridView.layoutParams = params
|
||||
}
|
||||
|
||||
// 그룹 레이아웃에 추가
|
||||
groupLayout.addView(textView)
|
||||
groupLayout.addView(divider)
|
||||
groupLayout.addView(gridView)
|
||||
container.addView(groupLayout)
|
||||
|
||||
// GridView 높이 조정
|
||||
gridView.post { setGridViewHeight(gridView) }
|
||||
}
|
||||
|
||||
fun registerCallback(callback: (String) -> Unit) {
|
||||
this.selectCallback = callback
|
||||
}
|
||||
|
||||
fun triggerEvent(data: String) {
|
||||
selectCallback?.invoke(data)
|
||||
}
|
||||
|
||||
fun dismiss() {
|
||||
dialog?.dismiss()
|
||||
dialog = null
|
||||
}
|
||||
}
|
@ -0,0 +1,169 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.GridView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import com.example.smart119.MedicalInfo
|
||||
import com.example.smart119.R
|
||||
import com.example.smart119.datas.HospitalSearch
|
||||
|
||||
object DepartmentLocation_Dialog {
|
||||
private var dialog: Dialog? = null
|
||||
private var selectCallback: ((String) -> Unit)? = null
|
||||
|
||||
fun show(context: Context) {
|
||||
dialog?.dismiss() // 기존 다이얼로그가 있으면 닫기 (중복 방지)
|
||||
dialog = Dialog(context)
|
||||
|
||||
val dialogView = LayoutInflater.from(context).inflate(R.layout.department_address, null)
|
||||
dialog?.setContentView(dialogView)
|
||||
|
||||
dialog?.window?.setLayout(1000, 800) // width, height (픽셀 단위)
|
||||
|
||||
val itemClickListener: (String) -> Unit = { item ->
|
||||
HospitalSearch.set_selectPrtAddress(item)
|
||||
var locView = FragmentHandler.getView("LocationSearchFragment")
|
||||
if (locView != null) {
|
||||
val prtTV = locView.findViewById<TextView>(R.id.hospPrtLocText)
|
||||
prtTV.text = item;
|
||||
}
|
||||
Toast.makeText(context, "선택된 항목: $item", Toast.LENGTH_SHORT).show()
|
||||
|
||||
triggerEvent(item)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
val getGroups = MedicalInfo.get_prt_group_map();
|
||||
if (getGroups.size > 0) {
|
||||
getGroups.forEach { key, value ->
|
||||
val group_name = key;
|
||||
val group_list = value;
|
||||
addGroup(
|
||||
dialogView, context,
|
||||
group_name, group_list,
|
||||
itemClickListener
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
dialog?.setOnCancelListener {
|
||||
//진료과 선택
|
||||
var locView = FragmentHandler.getView("LocationSearchFragment")
|
||||
if (locView != null) {
|
||||
val prtTV = locView.findViewById<TextView>(R.id.hospPrtLocText)
|
||||
prtTV.text = "진료과 선택";
|
||||
}
|
||||
}
|
||||
|
||||
dialog?.show()
|
||||
}
|
||||
|
||||
private fun addGroup(
|
||||
view: View, context: Context, groupName: String, items: List<String>, callback: (String) -> Unit
|
||||
) {
|
||||
val container = view.findViewById<LinearLayout>(R.id.departGroupContainer)
|
||||
|
||||
// 그룹 레이아웃 생성 (LinearLayout)
|
||||
val groupLayout = LinearLayout(context).apply {
|
||||
layoutParams = LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
orientation = LinearLayout.VERTICAL
|
||||
setPadding(0, 4, 0, 4)
|
||||
}
|
||||
|
||||
// 그룹명 (TextView)
|
||||
val textView = TextView(context).apply {
|
||||
text = groupName
|
||||
textSize = 25f
|
||||
setTypeface(null, Typeface.BOLD)
|
||||
setPadding(0, 0, 0, 4)
|
||||
}
|
||||
|
||||
// 구분선 (View)
|
||||
val divider = View(context).apply {
|
||||
layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
2 // 두께
|
||||
)
|
||||
setBackgroundColor(Color.GRAY)
|
||||
}
|
||||
|
||||
// GridView 생성
|
||||
val gridView = GridView(context).apply {
|
||||
layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
stretchMode = GridView.STRETCH_COLUMN_WIDTH
|
||||
gravity = Gravity.CENTER
|
||||
this.numColumns = GridView.AUTO_FIT
|
||||
verticalSpacing = 8
|
||||
horizontalSpacing = 8
|
||||
}
|
||||
|
||||
// GridView 어댑터 설정
|
||||
// val adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, items)
|
||||
val adapter = object : ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, items) {
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val view = super.getView(position, convertView, parent) as TextView
|
||||
view.textSize = 20f // 텍스트 크기 조정
|
||||
return view
|
||||
}
|
||||
}
|
||||
gridView.adapter = adapter
|
||||
|
||||
gridView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
|
||||
val selectedItem = parent.getItemAtPosition(position) as String
|
||||
callback(selectedItem)
|
||||
DepartmentAddress_Dialog.dismiss()
|
||||
}
|
||||
|
||||
// GridView 높이 자동 조절 함수
|
||||
fun setGridViewHeight(gridView: GridView) {
|
||||
val listAdapter = gridView.adapter ?: return
|
||||
val totalItems = listAdapter.count
|
||||
val numColumns = gridView.numColumns
|
||||
val rows = Math.ceil(totalItems / numColumns.toDouble()).toInt()
|
||||
|
||||
val itemHeight = 80 // px 단위 (아이템 하나의 높이)
|
||||
val params = gridView.layoutParams
|
||||
params.height = rows * itemHeight
|
||||
gridView.layoutParams = params
|
||||
}
|
||||
|
||||
// 그룹 레이아웃에 추가
|
||||
groupLayout.addView(textView)
|
||||
groupLayout.addView(divider)
|
||||
groupLayout.addView(gridView)
|
||||
container.addView(groupLayout)
|
||||
|
||||
// GridView 높이 조정
|
||||
gridView.post { setGridViewHeight(gridView) }
|
||||
}
|
||||
|
||||
fun registerCallback(callback: (String) -> Unit) {
|
||||
this.selectCallback = callback
|
||||
}
|
||||
|
||||
fun triggerEvent(data: String) {
|
||||
selectCallback?.invoke(data)
|
||||
}
|
||||
|
||||
fun dismiss() {
|
||||
dialog?.dismiss()
|
||||
dialog = null
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.view.View
|
||||
|
||||
object FragmentHandler {
|
||||
|
||||
private val fragmentViews = mutableMapOf<String, View?>()
|
||||
|
||||
// View 등록
|
||||
fun registerView(tag: String, view: View?) {
|
||||
fragmentViews[tag] = view
|
||||
}
|
||||
|
||||
// View 가져오기
|
||||
fun getView(tag: String): View? {
|
||||
return fragmentViews[tag]
|
||||
}
|
||||
|
||||
// View 제거
|
||||
fun unregisterView(tag: String) {
|
||||
fragmentViews.remove(tag)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.AutoCompleteTextView
|
||||
import android.widget.Button
|
||||
import android.widget.GridView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import com.example.smart119.R
|
||||
import com.example.smart119.datas.HospitalSearch
|
||||
|
||||
object GunGuSelector_Dialog {
|
||||
private var dialog: Dialog? = null
|
||||
private var selectCallback: ((String) -> Unit)? = null
|
||||
|
||||
fun show(context: Context) {
|
||||
dialog?.dismiss() // 기존 다이얼로그가 있으면 닫기 (중복 방지)
|
||||
dialog = Dialog(context)
|
||||
|
||||
val dialogView = LayoutInflater.from(context).inflate(R.layout.gungu_selector, null)
|
||||
dialog?.setContentView(dialogView)
|
||||
|
||||
val gridView: GridView = dialogView.findViewById(R.id.gridViewOptions)
|
||||
// val closeButton: Button = dialogView.findViewById(R.id.dialogCloseButton)
|
||||
|
||||
// 그리드에 표시할 데이터
|
||||
var options = HospitalSearch.getGunGuNameList()
|
||||
options.add(0, "군구선택")
|
||||
/*
|
||||
listOf(
|
||||
"군구선택", "강남구", "강동구", "강북구", "강서구",
|
||||
"관악구", "광진구", "구로구", "금천구",
|
||||
"노원구", "도봉구", "동대문구", "동작구",
|
||||
"마포구", "서대문구", "서초구", "성동구",
|
||||
"성북구", "송파구", "양천구", "영등포구",
|
||||
"용산구", "은평구", "종로구", "중구", "중랑구"
|
||||
)
|
||||
*/
|
||||
val adapter = object : ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, options) {
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val view = super.getView(position, convertView, parent) as TextView
|
||||
view.textSize = 20f // 텍스트 크기 조정
|
||||
return view
|
||||
}
|
||||
}
|
||||
gridView.adapter = adapter
|
||||
|
||||
// 아이템 클릭 이벤트 (선택 시 다이얼로그 닫기)
|
||||
gridView.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ ->
|
||||
try {
|
||||
val selectedOption = options[position]
|
||||
HospitalSearch.set_selectGunGu(selectedOption)
|
||||
var addrView = FragmentHandler.getView("AddressSearchFragment")
|
||||
if (addrView != null) {
|
||||
val gugunSelectorTV = addrView.findViewById<TextView>(R.id.gunGuSelectText)
|
||||
gugunSelectorTV.text = selectedOption;
|
||||
}
|
||||
Toast.makeText(context, "선택된 항목: $selectedOption", Toast.LENGTH_SHORT).show()
|
||||
|
||||
triggerEvent(selectedOption)
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
dismiss() // 아이템 선택 즉시 다이얼로그 닫기
|
||||
}
|
||||
|
||||
// 닫기 버튼 클릭 이벤트
|
||||
// closeButton.setOnClickListener {
|
||||
// dismiss()
|
||||
// }
|
||||
|
||||
dialog?.show()
|
||||
}
|
||||
|
||||
fun registerCallback(callback: (String) -> Unit) {
|
||||
this.selectCallback = callback
|
||||
}
|
||||
|
||||
fun triggerEvent(data: String) {
|
||||
selectCallback?.invoke(data)
|
||||
}
|
||||
|
||||
fun dismiss() {
|
||||
dialog?.dismiss()
|
||||
dialog = null
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.GridView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import com.example.smart119.MedicalInfo
|
||||
import com.example.smart119.R
|
||||
import com.example.smart119.datas.HospitalSearch
|
||||
|
||||
object HospitalCategoryAddress_Dialog {
|
||||
private var dialog: Dialog? = null
|
||||
private var selectCallback: ((String) -> Unit)? = null
|
||||
|
||||
fun show(context: Context) {
|
||||
dialog?.dismiss() // 기존 다이얼로그가 있으면 닫기 (중복 방지)
|
||||
dialog = Dialog(context)
|
||||
|
||||
val dialogView = LayoutInflater.from(context).inflate(R.layout.hospital_category_address, null)
|
||||
dialog?.setContentView(dialogView)
|
||||
|
||||
val gridView: GridView = dialogView.findViewById(R.id.gridViewOptions)
|
||||
// val closeButton: Button = dialogView.findViewById(R.id.dialogCloseButton)
|
||||
|
||||
// 그리드에 표시할 데이터
|
||||
var options = MedicalInfo.get_addressQZ_list()
|
||||
options.add(0, "병원분류명선택")
|
||||
val adapter = object : ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, options) {
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val view = super.getView(position, convertView, parent) as TextView
|
||||
view.textSize = 20f // 텍스트 크기 조정
|
||||
return view
|
||||
}
|
||||
}
|
||||
gridView.adapter = adapter
|
||||
|
||||
// 아이템 클릭 이벤트 (선택 시 다이얼로그 닫기)
|
||||
gridView.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ ->
|
||||
try {
|
||||
val selectedOption = options[position]
|
||||
HospitalSearch.set_selectHospCatAddress(selectedOption)
|
||||
var addrView = FragmentHandler.getView("AddressSearchFragment")
|
||||
if (addrView != null) {
|
||||
val hospCatTV = addrView.findViewById<TextView>(R.id.hospCatText)
|
||||
hospCatTV.text = selectedOption;
|
||||
}
|
||||
Toast.makeText(context, "선택된 항목: $selectedOption", Toast.LENGTH_SHORT).show()
|
||||
|
||||
triggerEvent(selectedOption)
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
dismiss() // 아이템 선택 즉시 다이얼로그 닫기
|
||||
}
|
||||
|
||||
// 닫기 버튼 클릭 이벤트
|
||||
// closeButton.setOnClickListener {
|
||||
// dismiss()
|
||||
// }
|
||||
|
||||
dialog?.show()
|
||||
}
|
||||
|
||||
fun registerCallback(callback: (String) -> Unit) {
|
||||
this.selectCallback = callback
|
||||
}
|
||||
|
||||
fun triggerEvent(data: String) {
|
||||
selectCallback?.invoke(data)
|
||||
}
|
||||
|
||||
fun dismiss() {
|
||||
dialog?.dismiss()
|
||||
dialog = null
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.GridView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import com.example.smart119.MedicalInfo
|
||||
import com.example.smart119.R
|
||||
import com.example.smart119.datas.HospitalSearch
|
||||
|
||||
object HospitalCategoryLocation_Dialog {
|
||||
private var dialog: Dialog? = null
|
||||
private var selectCallback: ((String) -> Unit)? = null
|
||||
|
||||
fun show(context: Context) {
|
||||
dialog?.dismiss() // 기존 다이얼로그가 있으면 닫기 (중복 방지)
|
||||
dialog = Dialog(context)
|
||||
|
||||
val dialogView = LayoutInflater.from(context).inflate(R.layout.hospital_category_location, null)
|
||||
dialog?.setContentView(dialogView)
|
||||
|
||||
val gridView: GridView = dialogView.findViewById(R.id.gridViewOptions)
|
||||
// val closeButton: Button = dialogView.findViewById(R.id.dialogCloseButton)
|
||||
|
||||
// 그리드에 표시할 데이터
|
||||
var options = MedicalInfo.get_emogemdv_list()
|
||||
options.add(0, "의료기관 선택")
|
||||
val adapter = object : ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, options) {
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val view = super.getView(position, convertView, parent) as TextView
|
||||
view.textSize = 20f // 텍스트 크기 조정
|
||||
return view
|
||||
}
|
||||
}
|
||||
gridView.adapter = adapter
|
||||
|
||||
// 아이템 클릭 이벤트 (선택 시 다이얼로그 닫기)
|
||||
gridView.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ ->
|
||||
try {
|
||||
val selectedOption = options[position]
|
||||
HospitalSearch.set_selectHospCatAddress(selectedOption)
|
||||
var addrView = FragmentHandler.getView("LocationSearchFragment")
|
||||
if (addrView != null) {
|
||||
val hospCatTV = addrView.findViewById<TextView>(R.id.hospCatLocText)
|
||||
hospCatTV.text = selectedOption;
|
||||
}
|
||||
Toast.makeText(context, "선택된 항목: $selectedOption", Toast.LENGTH_SHORT).show()
|
||||
|
||||
triggerEvent(selectedOption)
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
dismiss() // 아이템 선택 즉시 다이얼로그 닫기
|
||||
}
|
||||
|
||||
// 닫기 버튼 클릭 이벤트
|
||||
// closeButton.setOnClickListener {
|
||||
// dismiss()
|
||||
// }
|
||||
|
||||
dialog?.show()
|
||||
}
|
||||
|
||||
fun registerCallback(callback: (String) -> Unit) {
|
||||
this.selectCallback = callback
|
||||
}
|
||||
|
||||
fun triggerEvent(data: String) {
|
||||
selectCallback?.invoke(data)
|
||||
}
|
||||
|
||||
fun dismiss() {
|
||||
dialog?.dismiss()
|
||||
dialog = null
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.content.Context
|
||||
import android.provider.Settings.Global.getString
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import com.example.smart119.R
|
||||
import android.view.Gravity
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Spinner
|
||||
import android.widget.Toast
|
||||
import com.example.smart119.datas.HospitalSearch
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
|
||||
object HospitalInfoPopup {
|
||||
|
||||
private var popupWindow: PopupWindow? = null
|
||||
|
||||
fun showPopupTransfer(view: View) {
|
||||
// 기존 팝업이 존재하면 닫음
|
||||
dismissPopup()
|
||||
|
||||
// PopupView 레이아웃을 인플레이트
|
||||
val inflater = LayoutInflater.from(view.context)
|
||||
val popupView = inflater.inflate(R.layout.popup_detail, null)
|
||||
|
||||
val displayMetrics = view.resources.displayMetrics
|
||||
val screenWidth = displayMetrics.widthPixels
|
||||
val screenHeight = displayMetrics.heightPixels
|
||||
|
||||
// PopupWindow 생성
|
||||
popupWindow = PopupWindow(
|
||||
popupView,
|
||||
(screenWidth * 0.4).toInt(), // 너비: 화면의 40%
|
||||
(screenHeight * 0.6).toInt(), // 높이: 화면의 60%
|
||||
true // 외부 클릭으로 닫기 가능
|
||||
).apply {
|
||||
// 팝업 표시 (뷰 기준 위치)
|
||||
showAsDropDown(view, 220, -220)
|
||||
|
||||
var closeBtn = popupView.findViewById<Button>(R.id.closePopup)
|
||||
closeBtn.setOnClickListener {
|
||||
dismissPopup()
|
||||
}
|
||||
// 외부 터치 시 닫기
|
||||
// popupView.setOnTouchListener { _, _ ->
|
||||
// dismissPopup()
|
||||
// true
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 팝업 닫기 함수
|
||||
fun dismissPopup() {
|
||||
popupWindow?.dismiss()
|
||||
popupWindow = null
|
||||
}
|
||||
|
||||
|
||||
// fun showPopupTransfer(view: View) {
|
||||
// // PopupView 레이아웃을 인플레이트 (단순 XML 로드)
|
||||
// val inflater = LayoutInflater.from(view.context)
|
||||
// val popupView = inflater.inflate(R.layout.popup_detail, null)
|
||||
//
|
||||
// val displayMetrics = view.resources.displayMetrics
|
||||
// val screenWidth = displayMetrics.widthPixels
|
||||
// val screenHeight = displayMetrics.heightPixels
|
||||
//
|
||||
// // PopupWindow 생성
|
||||
// val popupWindow = PopupWindow(
|
||||
// popupView,
|
||||
// (screenWidth * 0.4).toInt(), // 너비: 화면의 40%
|
||||
// (screenHeight * 0.6).toInt(), // 높이: 화면의 60%
|
||||
// true // 외부 클릭으로 닫기 가능
|
||||
// )
|
||||
//
|
||||
// // PopupWindow 표시 (뷰 기준 위치)
|
||||
// popupWindow.showAsDropDown(view, 220, -220) // 기준 뷰 아래에 표시
|
||||
// }
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,753 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Button
|
||||
import android.widget.GridView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RadioButton
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.example.smart119.API_Helper
|
||||
import com.example.smart119.AlertDialogUtil
|
||||
import com.example.smart119.ListItem
|
||||
import com.example.smart119.LocationHelper
|
||||
import com.example.smart119.LoginManager
|
||||
import com.example.smart119.MedicalInfo
|
||||
import com.example.smart119.MyCookieJar
|
||||
import com.example.smart119.R
|
||||
import com.example.smart119.SpreadsheetAdapter
|
||||
import com.example.smart119.ViewPagerAdapter
|
||||
import com.example.smart119.databinding.FragmentSecondBinding
|
||||
import com.example.smart119.datas.HospitalSearch
|
||||
import com.example.smart119.interfaces.RetrofitClient
|
||||
import com.example.smart119.views.PaginationHelper.pageRequest
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.google.gson.JsonObject
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import kotlin.math.log
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass as the second destination in the navigation.
|
||||
*/
|
||||
class HospitalSearchFragment : Fragment() {
|
||||
|
||||
private var _binding: FragmentSecondBinding? = null
|
||||
private var _listAdapterInit: Boolean? = false
|
||||
private lateinit var adapter: SpreadsheetAdapter
|
||||
// private val
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
|
||||
_binding = FragmentSecondBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
//창이 보여질때 실행되는 함수
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
FragmentHandler.registerView("HospitalSearchFragment", view)
|
||||
|
||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
// 뒤로 가기 동작 막음
|
||||
// println("Hospital 뒤로가기클릭!!")
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
//#region 탭 레이아웃 설정
|
||||
val tabLayout: TabLayout = view.findViewById(R.id.tabLayout)
|
||||
val viewPager: ViewPager2 = view.findViewById(R.id.viewPager)
|
||||
|
||||
// ViewPager 어댑터 설정
|
||||
val vpAdapter = ViewPagerAdapter(requireActivity())
|
||||
viewPager.adapter = vpAdapter
|
||||
|
||||
// TabLayout과 ViewPager 연결
|
||||
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
|
||||
tab.text = when (position) {
|
||||
0 -> "주소 기반 검색"
|
||||
1 -> "위치 기반 검색"
|
||||
else -> "주소 기반 검색"
|
||||
}
|
||||
}.attach()
|
||||
//#endregion
|
||||
|
||||
//hospitalInit(view);
|
||||
// HospitalSearch.clearAllData()
|
||||
|
||||
if (HospitalSearch.get_gps_address().isEmpty()) {
|
||||
println("hospital search address updated!")
|
||||
// Hospital_UIUpdate()
|
||||
}
|
||||
else {
|
||||
// Hospital_UIUpdate_SET()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//병원검색 버튼 이벤트
|
||||
binding.hospSearchButton.setOnClickListener {
|
||||
|
||||
var _sel_medical = view.findViewById<Spinner>(R.id.spMedical).selectedItem as String;
|
||||
var _sel_depart = view.findViewById<Spinner>(R.id.spDepart).selectedItem as String;
|
||||
var _sel_emg_yn = view.findViewById<Spinner>(R.id.spEmgYN).selectedItem as String;
|
||||
|
||||
adapter.clearHospitalList();
|
||||
HospitalSearch.clearAllData();
|
||||
|
||||
if (HospitalSearch.getIsFiltered()) {
|
||||
var searchObject = HospitalSearch.getSearchInfo()
|
||||
var filter_si = searchObject["si"].asString;
|
||||
var filter_gu = searchObject["gu"].asString;
|
||||
var filter_relate = searchObject["relate"].asString;
|
||||
|
||||
var reqBody: JsonObject = API_Helper.make_addressHosp_param(
|
||||
filter_si, filter_gu, "", filter_relate
|
||||
);
|
||||
try {
|
||||
LoadingDialog.showDlg(requireContext())
|
||||
HospitalSearch.SET_SearchRequest(true, reqBody)
|
||||
RetrofitClient.locInstance.getAddressHospitalList(reqBody).enqueue(getAddressResponse())
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
} finally {
|
||||
LoadingDialog.hideDlg()
|
||||
}
|
||||
} else {
|
||||
LocationHelper.getLastKnownLocation({ res ->
|
||||
//success
|
||||
val resObj = res.getAsJsonObject();
|
||||
val callResult = resObj["isSuccess"]?.asBoolean ?: true;
|
||||
val lon = resObj["lon"]?.asDouble ?: 0.0;
|
||||
val lat = resObj["lat"]?.asDouble ?: 0.0;
|
||||
|
||||
var page = "1"
|
||||
var row = "4"
|
||||
var dg_list = emptyList<String>()//listOf("","")
|
||||
|
||||
var _code_medical = MedicalInfo.get_emogemdv_code(_sel_medical);
|
||||
var _code_depart = MedicalInfo.get_prt_code(_sel_depart);
|
||||
var _emg_yn = _sel_emg_yn;
|
||||
var _relate = ""
|
||||
|
||||
try {
|
||||
_relate = HospitalSearch.getSearchInfo()["relate"].asString;
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
|
||||
if (_code_medical == null) _code_medical = ""
|
||||
if (_code_depart == null) _code_depart = ""
|
||||
if (_emg_yn == "응급실 포함여부 선택") _emg_yn = "Y"
|
||||
|
||||
// println("의료기관:${_sel_medical}|${_code_medical}, 진료과:${_sel_depart}|${_code_depart}, 응급실:${_emg_yn}")
|
||||
|
||||
var reqBody :JsonObject = API_Helper.make_arroundHosp_param2(
|
||||
lon = lon.toString(),
|
||||
lat = lat.toString(),
|
||||
emogemdv = "${_code_medical}",
|
||||
prtcode = "${_code_depart}",
|
||||
emergency = "${_emg_yn}",
|
||||
emogdesc = "${_relate}",
|
||||
page = "${page}",
|
||||
row = "${row}"
|
||||
);
|
||||
|
||||
try {
|
||||
LoadingDialog.showDlg(requireContext())
|
||||
HospitalSearch.SET_SearchRequest(false, reqBody)
|
||||
RetrofitClient.locInstance.getAroundHospitalList(reqBody).enqueue(arroundHospitalResponse())
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
} finally {
|
||||
LoadingDialog.hideDlg()
|
||||
}
|
||||
}, { res ->
|
||||
//fail
|
||||
val resObj = res.getAsJsonObject();
|
||||
val callResult = resObj["isSuccess"]?.asBoolean ?: false;
|
||||
val lon = resObj["lon"]?.asDouble ?: 0.0;
|
||||
val lat = resObj["lat"]?.asDouble ?: 0.0;
|
||||
println("[FAIL] last location ${lon}, ${lat}");
|
||||
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "병원 검색 결과",
|
||||
message = "현재 위치를 알수 없어 검색 되지 않았습니다, 다시 시도해주세요."
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
// binding.searchAddressButton.setOnClickListener {
|
||||
// val inflater = LayoutInflater.from(requireActivity())
|
||||
// val popupView = inflater.inflate(R.layout.popup_search, null)
|
||||
//
|
||||
// var itemSido = HospitalSearch.getSidoList();
|
||||
// var itemSidoAlpha:MutableList<String> = itemSido.toMutableList()
|
||||
// itemSidoAlpha.add(0, "시도선택")
|
||||
//
|
||||
// var newPopup = HospitalSearchPopup.showPopupHospitalSearch(popupView, requireActivity())
|
||||
// HospitalSearchPopup.set_POPUP_SIDO_COMBO(newPopup, requireActivity(), itemSidoAlpha)
|
||||
//
|
||||
// HospitalSearch.set_popup_search(newPopup)
|
||||
// }
|
||||
// binding.cbActiveAddresss.setOnCheckedChangeListener { _, isChecked ->
|
||||
// if (isChecked) {
|
||||
// HospitalSearch.setFiltered(true)
|
||||
// } else {
|
||||
// HospitalSearch.setFiltered(false)
|
||||
// }
|
||||
// }
|
||||
binding.pagePrev.setOnClickListener {
|
||||
if (HospitalSearch.getAllData().size > 0) {
|
||||
var bChanged = PaginationHelper.prevPage(requireView(), { page ->
|
||||
page_onclick_listener(page)
|
||||
})
|
||||
//request page
|
||||
if (bChanged) {
|
||||
var currPage = PaginationHelper.currentPage;
|
||||
// println("prev request number ${PaginationHelper.currentPage}")
|
||||
page_onclick_listener(currPage)
|
||||
}
|
||||
// else println("no request prev")
|
||||
}
|
||||
}
|
||||
binding.pageNext.setOnClickListener {
|
||||
if (HospitalSearch.getAllData().size > 0) {
|
||||
var bChanged = PaginationHelper.nextPage(requireView(), { page ->
|
||||
page_onclick_listener(page)
|
||||
})
|
||||
//request page
|
||||
if (bChanged) {
|
||||
var currPage = PaginationHelper.currentPage;
|
||||
// println("next request number ${PaginationHelper.currentPage}")
|
||||
page_onclick_listener(currPage)
|
||||
}
|
||||
// else println("no request next")
|
||||
}
|
||||
}
|
||||
binding.gpsRefresh.setOnClickListener {
|
||||
Hospital_UIUpdate()
|
||||
}
|
||||
*/
|
||||
|
||||
//HospitalSearch.init_hospital_req(requireActivity())
|
||||
}
|
||||
|
||||
private fun arroundHospitalResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
var resBody = response.body();
|
||||
set_hospital_list(resBody)
|
||||
} else {
|
||||
Toast.makeText(
|
||||
requireActivity(),
|
||||
"Error: ${response.code()}",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
Toast.makeText(
|
||||
requireActivity(),
|
||||
"Request Failed: ${t.message}",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
|
||||
/*
|
||||
|
||||
var hospitalSearchRes: List<List<String>> = mutableListOf()
|
||||
var hpidList: MutableList<String> = mutableListOf()
|
||||
HospitalSearch.addDataHospitalItems(
|
||||
listOf(
|
||||
HospitalSearch.itemStructure(
|
||||
"A1100223", API_Helper.lidar_levelState(3), "1.11",
|
||||
"서울특별시", "양천구", "1566-6688", "서울특별시서남병원"
|
||||
),// 126.8371889, 37.5124604
|
||||
HospitalSearch.itemStructure(
|
||||
"A1100055", API_Helper.lidar_levelState(-1), "2.22",
|
||||
"서울특별시", "영등포구", "02-829-5114", "한림대학교 강남성심병원"
|
||||
),
|
||||
HospitalSearch.itemStructure(
|
||||
"A1100004", API_Helper.lidar_levelState(-1), "3.33",
|
||||
"서울특별시", "용산구", "02-709-9114", "순천향대학교 부속 서울병원"
|
||||
)
|
||||
//용산 주변 좌표
|
||||
//lon 126.9984597, lat 37.5287920
|
||||
)
|
||||
)
|
||||
hospitalSearchRes = HospitalSearch.getAllData();
|
||||
|
||||
hpidList.add("A1100223")
|
||||
hpidList.add("A1100055")
|
||||
hpidList.add("A1100004")
|
||||
|
||||
if (hospitalSearchRes.size > 0)
|
||||
adapter.hospitalListUpdate(hospitalSearchRes, hpidList)
|
||||
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hospitalInit(view: View) {
|
||||
|
||||
/*
|
||||
var items = listOf(
|
||||
ListItem.Header(listOf("병원이름")), // 헤더 열 정의
|
||||
ListItem.Header(listOf("주소")),
|
||||
ListItem.Header(listOf("전화번호")),
|
||||
ListItem.Header(listOf("라이다 혼잡도")),
|
||||
ListItem.Header(listOf("거리")),
|
||||
ListItem.Header(listOf("병원별 이송 시작"))
|
||||
)
|
||||
val recyclerView: RecyclerView = view.findViewById(R.id.reCyclerView)
|
||||
|
||||
val spanCount = 6;
|
||||
adapter = SpreadsheetAdapter(
|
||||
items,
|
||||
onButtonClick = { row, pos ->
|
||||
//row.values[0]
|
||||
|
||||
adapter.setSelectedHospitalPos(pos)
|
||||
HospitalSearch.setIdx(adapter.getSelectedPosition())
|
||||
var selectedHospital = adapter.getSelectedHospital()
|
||||
var getSelData = HospitalSearch.getSelectedData()
|
||||
if (selectedHospital is ListItem.Row) {
|
||||
var hospitalName = selectedHospital.values[0];
|
||||
var hospitalAddress = selectedHospital.values[1];
|
||||
var hospitalCallNumber = selectedHospital.values[2];
|
||||
var hospitalLiDAR = selectedHospital.values[3];
|
||||
var hospitalDistance = selectedHospital.values[4];
|
||||
if (TransferManager.getState() == TransferState.STARTED) {
|
||||
//이송 변경
|
||||
//변경된 병원 정보 설정
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "변경 이송 병원 정보",
|
||||
message = "병원 이름 : ${hospitalName}" + "\n" +
|
||||
"주소 : ${hospitalAddress}" + "\n" +
|
||||
"전화번호 : ${hospitalCallNumber}" + "\n" +
|
||||
"거리 : ${hospitalDistance}" + "\n" +
|
||||
"라이다혼잡도 : ${hospitalLiDAR}" + "\n\n" +
|
||||
"확인 선택시 진행(변경 시 기존 이송 정보가 변경됩니다.)",
|
||||
onPositiveClick = {
|
||||
val bottomNaviView =
|
||||
requireActivity().findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
bottomNaviView.selectedItemId = R.id.hospTransfer;
|
||||
TransferManager.changeTransfer()
|
||||
},
|
||||
onNegativeClick = {}
|
||||
)
|
||||
|
||||
} else {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "이송 병원 정보",
|
||||
message = "병원 이름 : ${hospitalName}" + "\n" +
|
||||
"주소 : ${hospitalAddress}" + "\n" +
|
||||
"전화번호 : ${hospitalCallNumber}" + "\n" +
|
||||
"라이다혼잡도 : ${hospitalLiDAR}" + "\n\n" +
|
||||
"확인 선택시 진행",
|
||||
onPositiveClick = {
|
||||
if (TransferManager.startTransfer()) {
|
||||
val bottomNaviView =
|
||||
requireActivity().findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
bottomNaviView.selectedItemId = R.id.hospTransfer;
|
||||
} else {
|
||||
// 시작되지 않았습니다.
|
||||
Toast.makeText(
|
||||
requireActivity(), "이송이 시작되지 않았습니다. 다시 전송해주세요.",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
},
|
||||
onNegativeClick = {}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "선택된 병원 정보",
|
||||
message = "병원 검색 후 선택해주세요!"
|
||||
)
|
||||
}
|
||||
//이송시작
|
||||
println(row)
|
||||
|
||||
//pos, row(ListItem상 선택 위치, 선택한 row 정보) -> hpid는?
|
||||
},
|
||||
onRowClick = { row ->
|
||||
// Toast.makeText(requireActivity(), "${row.values[0]}이 선택되었습니다.", Toast.LENGTH_SHORT)
|
||||
// .show()
|
||||
}
|
||||
)
|
||||
adapter.setColumnCount(spanCount)
|
||||
recyclerView.adapter = adapter
|
||||
|
||||
// GridLayoutManager 설정
|
||||
val layoutManager = GridLayoutManager(requireActivity(), spanCount)
|
||||
layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
// return if (adapter.getItemViewType(position) == SpreadsheetAdapter.VIEW_TYPE_HEADER) 3 else 1
|
||||
return if (adapter.getItemViewType(position) == SpreadsheetAdapter.VIEW_TYPE_ROW) {
|
||||
spanCount // Row가 전체 열을 차지하도록 설정
|
||||
} else {
|
||||
1 // 기본적으로 각 항목은 한 열을 차지
|
||||
}
|
||||
}
|
||||
}
|
||||
recyclerView.layoutManager = layoutManager
|
||||
*/
|
||||
}
|
||||
|
||||
private fun Hospital_UIUpdate_SET() {
|
||||
var hsfView = FragmentHandler.getView("HospitalSearchFragment")
|
||||
if (hsfView != null) {
|
||||
var addrString = HospitalSearch.get_gps_address()
|
||||
var geoTv = hsfView.findViewById<TextView>(R.id.tvGeoLocation)
|
||||
geoTv.text = addrString;
|
||||
}
|
||||
}
|
||||
|
||||
private fun Hospital_UIUpdate() {
|
||||
|
||||
}
|
||||
|
||||
//길찾기 API 결과
|
||||
private fun getPathAddressResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
val resObj = response.body();
|
||||
val metaObj = resObj?.get("meta");
|
||||
if (metaObj != null) {
|
||||
val tot_count = metaObj.asJsonObject["total_count"].asInt
|
||||
if (tot_count > 0) {
|
||||
var hsfView = FragmentHandler.getView("HospitalSearchFragment")
|
||||
if (hsfView != null) {
|
||||
|
||||
val docus = resObj.getAsJsonArray("documents")
|
||||
val addObj = docus[0].asJsonObject["address"];
|
||||
val add_full = addObj.asJsonObject["address_name"]
|
||||
val add_si = addObj.asJsonObject["region_1depth_name"]
|
||||
val add_gu = addObj.asJsonObject["region_2depth_name"]
|
||||
val add_dong = addObj.asJsonObject["region_3depth_name"]
|
||||
|
||||
var geoTv = hsfView.findViewById<TextView>(R.id.tvGeoLocation)
|
||||
geoTv.text = add_full.asString;
|
||||
|
||||
HospitalSearch.set_gps_update(add_full.asString)
|
||||
}
|
||||
}
|
||||
}
|
||||
//response.body()["meta"].asJsonObject["total_count"]
|
||||
println(response)
|
||||
} else {
|
||||
println("address not found")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
println(t.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAddressResponse(): Callback<JsonObject>{
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
val resObj = response.body();
|
||||
set_hospital_list(resObj, true)
|
||||
} else {
|
||||
println("hospital not found")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
println(t.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun set_hospital_list(resobj:JsonObject?, isAddress:Boolean = false) {
|
||||
var totPages = resobj?.get("totalPages") // 총 페이지
|
||||
var totRows = resobj?.get("totalRows") // 총 행 개수
|
||||
var searchRows = resobj?.get("row") // 검색 페이지 행 개수
|
||||
var searchPage = resobj?.get("page") // 검색 페이지 번호
|
||||
var resData = resobj?.getAsJsonArray("resData")
|
||||
var dataSize = resData?.size() ?: 0;
|
||||
|
||||
var hospitalSearchRes: List<List<String>> = mutableListOf()
|
||||
var hpidList: MutableList<String> = mutableListOf()
|
||||
if (dataSize > 0) {
|
||||
// region 검색 결과 리스트에 세팅
|
||||
try {
|
||||
resData?.forEach { item ->
|
||||
val itemObj = item.asJsonObject;
|
||||
var levelState =
|
||||
API_Helper.lidar_levelState(itemObj.get("levelState").asInt)
|
||||
var itemHpid = itemObj.get("hpid").toString().trim('"');
|
||||
hpidList.add(itemHpid)
|
||||
var itemDistance = ""
|
||||
var itemTel = ""
|
||||
var itemTitle = ""
|
||||
if (!isAddress) {
|
||||
itemObj.get("distance").toString().trim('"')
|
||||
itemTel = itemObj.get("tel").toString().trim('"')
|
||||
itemTitle = itemObj.get("title").toString().trim('"')
|
||||
}
|
||||
else {
|
||||
itemTel = itemObj.get("dutyTel1").toString().trim('"')
|
||||
itemTitle = itemObj.get("dutyName").toString().trim('"')
|
||||
}
|
||||
|
||||
HospitalSearch.addDataHospitalItems(
|
||||
listOf(
|
||||
HospitalSearch.itemStructure(
|
||||
itemHpid, levelState, itemDistance,
|
||||
itemObj.get("city").toString().trim('"'),
|
||||
itemObj.get("district").toString().trim('"'),
|
||||
itemTel, itemTitle
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
var total_Page = totPages?.asInt;
|
||||
if (total_Page == null) total_Page = 0;
|
||||
var total_Row = totRows?.asInt;
|
||||
if (total_Row == null) total_Row = 0;
|
||||
PaginationHelper.setupPaginationLayout(requireView(), total_Page, total_Row, { page ->
|
||||
page_onclick_listener(page)
|
||||
})
|
||||
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(requireActivity(), "${e.message}", Toast.LENGTH_LONG)
|
||||
.show()
|
||||
} finally {}
|
||||
|
||||
hospitalSearchRes = HospitalSearch.getAllData();
|
||||
} else {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "병원 검색 결과",
|
||||
message = "병원이 검색되지 않았습니다. 다시 시도해주세요."
|
||||
)
|
||||
|
||||
if (!PaginationHelper.pageRequest) PaginationHelper.setupPaginationLayout(
|
||||
requireView(),
|
||||
0, 0, { page ->
|
||||
page_onclick_listener(page)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
//병원 검색 결과 설정
|
||||
if (hospitalSearchRes.size > 0) adapter.hospitalListUpdate(hospitalSearchRes, hpidList)
|
||||
// endregion
|
||||
}
|
||||
|
||||
private fun page_onclick_listener(page:Int) {
|
||||
// println("clicked page ${page}")
|
||||
var reqBody = HospitalSearch.GET_SearchRequest()
|
||||
if (reqBody != null) {
|
||||
try {
|
||||
if (HospitalSearch.isAddressSearch()) {
|
||||
LoadingDialog.showDlg(requireContext())
|
||||
reqBody = reqBody.getAsJsonObject("reqBody")
|
||||
reqBody.addProperty("page", "${page}")
|
||||
RetrofitClient.locInstance.getAddressHospitalList(reqBody).enqueue(getAddress_Paging_Response())
|
||||
} else {
|
||||
LoadingDialog.showDlg(requireContext())
|
||||
reqBody = reqBody.getAsJsonObject("reqBody")
|
||||
reqBody.addProperty("page", "${page}")
|
||||
RetrofitClient.locInstance.getAroundHospitalList(reqBody).enqueue(arroundHospital_Paging_Response())
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
} finally {
|
||||
LoadingDialog.hideDlg()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun arroundHospital_Paging_Response(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
LoadingDialog.hideDlg()
|
||||
if (response.isSuccessful) {
|
||||
var resBody = response.body();
|
||||
set_hospital_list_page(resBody)
|
||||
} else {
|
||||
Toast.makeText(
|
||||
requireActivity(),
|
||||
"Error: ${response.code()}",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
LoadingDialog.hideDlg()
|
||||
Toast.makeText(
|
||||
requireActivity(),
|
||||
"Request Failed: ${t.message}",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAddress_Paging_Response(): Callback<JsonObject>{
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
LoadingDialog.hideDlg()
|
||||
if (response.isSuccessful) {
|
||||
val resObj = response.body();
|
||||
set_hospital_list_page(resObj, true)
|
||||
} else {
|
||||
println("hospital not found")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
LoadingDialog.hideDlg()
|
||||
println(t.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun set_hospital_list_page(resobj:JsonObject?, isAddress:Boolean = false) {
|
||||
// region 현재 병원 리스트 초기화
|
||||
adapter.clearHospitalList();
|
||||
HospitalSearch.clearAllData();
|
||||
// endregion
|
||||
|
||||
var totPages = resobj?.get("totalPages") // 총 페이지
|
||||
var totRows = resobj?.get("totalRows") // 총 행 개수
|
||||
var searchRows = resobj?.get("row") // 검색 페이지 행 개수
|
||||
var searchPage = resobj?.get("page") // 검색 페이지 번호
|
||||
var resData = resobj?.getAsJsonArray("resData")
|
||||
var dataSize = resData?.size() ?: 0;
|
||||
|
||||
var hospitalSearchRes: List<List<String>> = mutableListOf()
|
||||
var hpidList: MutableList<String> = mutableListOf()
|
||||
if (dataSize > 0) {
|
||||
// region 검색 결과 리스트에 세팅
|
||||
try {
|
||||
resData?.forEach { item ->
|
||||
val itemObj = item.asJsonObject;
|
||||
var levelState =
|
||||
API_Helper.lidar_levelState(itemObj.get("levelState").asInt)
|
||||
var itemHpid = itemObj.get("hpid").toString().trim('"');
|
||||
hpidList.add(itemHpid)
|
||||
var itemDistance = ""
|
||||
var itemTel = ""
|
||||
var itemTitle = ""
|
||||
if (!isAddress) {
|
||||
itemObj.get("distance").toString().trim('"')
|
||||
itemTel = itemObj.get("tel").toString().trim('"')
|
||||
itemTitle = itemObj.get("title").toString().trim('"')
|
||||
}
|
||||
else {
|
||||
itemTel = itemObj.get("dutyTel1").toString().trim('"')
|
||||
itemTitle = itemObj.get("dutyName").toString().trim('"')
|
||||
}
|
||||
|
||||
HospitalSearch.addDataHospitalItems(
|
||||
listOf(
|
||||
HospitalSearch.itemStructure(
|
||||
itemHpid, levelState, itemDistance,
|
||||
itemObj.get("city").toString().trim('"'),
|
||||
itemObj.get("district").toString().trim('"'),
|
||||
itemTel, itemTitle
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
var total_Page = totPages?.asInt;
|
||||
if (total_Page == null) total_Page = 0;
|
||||
var total_Row = totRows?.asInt;
|
||||
if (total_Row == null) total_Row = 0;
|
||||
|
||||
// PaginationHelper.rePaginationLayout(requireView(), { page ->
|
||||
// page_onclick_listener(page)
|
||||
// })
|
||||
// PaginationHelper.setupPaginationLayout(requireView(), total_Page, total_Row, { page ->
|
||||
// page_onclick_listener(page)
|
||||
// })
|
||||
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(requireActivity(), "${e.message}", Toast.LENGTH_LONG)
|
||||
.show()
|
||||
} finally {}
|
||||
|
||||
hospitalSearchRes = HospitalSearch.getAllData();
|
||||
} else {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "병원 검색 결과",
|
||||
message = "병원이 검색되지 않았습니다. 다시 시도해주세요."
|
||||
)
|
||||
|
||||
// if (!PaginationHelper.pageRequest) PaginationHelper.setupPaginationLayout(
|
||||
// requireView(),
|
||||
// 0, 0, { page ->
|
||||
// page_onclick_listener(page)
|
||||
// }
|
||||
// )
|
||||
}
|
||||
|
||||
//병원 검색 결과 설정
|
||||
if (hospitalSearchRes.size > 0) adapter.hospitalListUpdate(hospitalSearchRes, hpidList)
|
||||
// endregion
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
FragmentHandler.unregisterView("HospitalSearchFragment")
|
||||
println("hospital search On destroy view")
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.content.Context
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Button
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import com.example.smart119.R
|
||||
import com.example.smart119.datas.HospitalSearch
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
|
||||
object HospitalSearchPopup {
|
||||
|
||||
fun showPopupHospitalSearch(view: View, context: Context): PopupWindow {
|
||||
// PopupView 레이아웃을 인플레이트
|
||||
val inflater = LayoutInflater.from(view.context)
|
||||
val popupView = inflater.inflate(R.layout.popup_search, null)
|
||||
|
||||
val displayMetrics = view.resources.displayMetrics
|
||||
val screenWidth = displayMetrics.widthPixels
|
||||
val screenHeight = displayMetrics.heightPixels
|
||||
|
||||
// PopupWindow 생성
|
||||
val popupWindow = PopupWindow(
|
||||
popupView,
|
||||
// LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
// LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
(screenWidth * 0.4).toInt(), // 너비를 화면 너비의 80%로 설정
|
||||
(screenHeight * 0.4).toInt(), // 높이를 화면 높이의 60%로 설정
|
||||
true // 외부 클릭으로 닫기 가능
|
||||
)
|
||||
|
||||
// PopupWindow 표시 (뷰 기준 위치)
|
||||
// popupWindow.showAsDropDown(view, 220, -220) // 기준 뷰 아래에 표시
|
||||
|
||||
// 화면의 중앙에 표시
|
||||
popupWindow.showAtLocation(
|
||||
view, // 기준이 되는 뷰 (보통은 최상위 뷰)
|
||||
Gravity.END, // 중앙 정렬
|
||||
250, // xOffset
|
||||
-95 // yOffset
|
||||
)
|
||||
// PopupView 내의 컴포넌트 제어
|
||||
val popupText = popupView.findViewById<TextView>(R.id.popupText)
|
||||
val saveButton = popupView.findViewById<Button>(R.id.savePopup)
|
||||
// saveButton.position
|
||||
|
||||
// 닫기 버튼 클릭 시 PopupWindow 닫기
|
||||
saveButton.setOnClickListener {
|
||||
val popupView = popupWindow.contentView
|
||||
val siSpin = popupView.findViewById<Spinner>(R.id.siSelectSpinner);
|
||||
val gunSpin = popupView.findViewById<Spinner>(R.id.guGunSelectSpinner);
|
||||
|
||||
val editText = popupView.findViewById<TextInputEditText>(R.id.relateInput)
|
||||
HospitalSearch.setSearchFilter(
|
||||
siSpin.selectedItem.toString(),
|
||||
gunSpin.selectedItem.toString(),
|
||||
editText.text.toString()
|
||||
)
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
|
||||
val siSpinner: Spinner = popupView.findViewById(R.id.siSelectSpinner)
|
||||
val guGunSpinner: Spinner = popupView.findViewById(R.id.guGunSelectSpinner)
|
||||
|
||||
// val sidefault = getString(R.string.si_spinner_prompt)
|
||||
// val siItems = mutableListOf("시도선택")
|
||||
// val arrAdapterSi = ArrayAdapter(context, android.R.layout.simple_spinner_dropdown_item, siItems)
|
||||
// siSpinner.adapter = arrAdapterSi;
|
||||
|
||||
siSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
|
||||
val selectedItem = parent.getItemAtPosition(position).toString()
|
||||
// Toast.makeText(context, "선택된 항목: $selectedItem", Toast.LENGTH_SHORT).show()
|
||||
|
||||
if (selectedItem != "" && selectedItem != "시도선택") {
|
||||
Toast.makeText(context, "선택된 항목: $selectedItem", Toast.LENGTH_SHORT).show()
|
||||
HospitalSearch.req_gun_list(selectedItem)
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>) {
|
||||
// 아무것도 선택되지 않았을 때의 동작 (필요 없으면 빈 상태로 둬도 됨)
|
||||
Toast.makeText(context, "선택되지 않음", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
guGunSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
|
||||
val selectedItem = parent.getItemAtPosition(position).toString()
|
||||
// Toast.makeText(context, "선택된 항목: $selectedItem", Toast.LENGTH_SHORT).show()
|
||||
|
||||
if (selectedItem != "" && selectedItem != "구군선택") {
|
||||
Toast.makeText(context, "선택된 항목: $selectedItem", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>) {
|
||||
// 아무것도 선택되지 않았을 때의 동작 (필요 없으면 빈 상태로 둬도 됨)
|
||||
Toast.makeText(context, "선택되지 않음", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
val guGunItems = mutableListOf("구군선택")
|
||||
val arrAdapterguGun = ArrayAdapter(context, android.R.layout.simple_spinner_dropdown_item, guGunItems)
|
||||
guGunSpinner.adapter = arrAdapterguGun;
|
||||
|
||||
return popupWindow
|
||||
}
|
||||
|
||||
fun set_POPUP_SIDO_COMBO(view: PopupWindow, context: Context, items:List<String>) {
|
||||
val popupView = view.contentView
|
||||
|
||||
val siSpinner: Spinner = popupView.findViewById(R.id.siSelectSpinner)
|
||||
val arrAdapterSi = ArrayAdapter(context, android.R.layout.simple_spinner_dropdown_item, items)
|
||||
siSpinner.adapter = arrAdapterSi;
|
||||
|
||||
arrAdapterSi.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun set_POPUP_GUGUN_COMBO(view: PopupWindow, context: Context, items:List<String>) {
|
||||
val popupView = view.contentView
|
||||
|
||||
val guGunSpinner: Spinner = popupView.findViewById(R.id.guGunSelectSpinner)
|
||||
val arrAdapterGuGun = ArrayAdapter(context, android.R.layout.simple_spinner_dropdown_item, items)
|
||||
guGunSpinner.adapter = arrAdapterGuGun;
|
||||
|
||||
arrAdapterGuGun.notifyDataSetChanged()
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.navigation.NavDestination
|
||||
import androidx.navigation.NavOptions
|
||||
import androidx.navigation.Navigator
|
||||
import androidx.navigation.fragment.FragmentNavigator
|
||||
|
||||
|
||||
@Navigator.Name("keep_state_fragment")
|
||||
class KeepStateFragment(
|
||||
private val context: Context,
|
||||
private val manager: FragmentManager,
|
||||
private val containerId: Int
|
||||
): FragmentNavigator(context, manager, containerId) {
|
||||
override fun navigate(
|
||||
destination: Destination,
|
||||
args: Bundle?,
|
||||
navOptions: NavOptions?,
|
||||
navigatorExtras: Navigator.Extras?
|
||||
): NavDestination? {
|
||||
val tag = destination.id.toString()
|
||||
|
||||
val transaction = manager.beginTransaction()
|
||||
|
||||
var initialNavigate = false
|
||||
val currentFragment = manager.primaryNavigationFragment
|
||||
|
||||
if (currentFragment != null) {
|
||||
transaction.hide(currentFragment)
|
||||
} else {
|
||||
initialNavigate = true
|
||||
}
|
||||
|
||||
var fragment = manager.findFragmentByTag(tag)
|
||||
|
||||
if (fragment == null) {
|
||||
// add로 fragment 최초 생성 (add)
|
||||
val className = destination.className
|
||||
fragment = manager.fragmentFactory.instantiate(context.classLoader, className)
|
||||
transaction.add(containerId, fragment, tag)
|
||||
} else {
|
||||
transaction.show(fragment)
|
||||
}
|
||||
|
||||
// destination fragment를 primary로 설정
|
||||
transaction.setPrimaryNavigationFragment(fragment)
|
||||
|
||||
// transaction 관련 fragment 상태 변경 최적화
|
||||
transaction.setReorderingAllowed(true)
|
||||
transaction.commitNow()
|
||||
|
||||
return if (initialNavigate) {
|
||||
destination
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Path
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
|
||||
class LidarCustomView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : View(context, attrs, defStyleAttr) {
|
||||
|
||||
private var paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||
color = 0xFFFF0000.toInt() // 줄무늬 색상
|
||||
style = Paint.Style.FILL
|
||||
}
|
||||
|
||||
private val lineWidth = 2f // 줄 두께
|
||||
private val gap = 4f// 줄 사이 간격
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
|
||||
// View 전체 영역
|
||||
val width = width.toFloat()
|
||||
val height = height.toFloat()
|
||||
|
||||
// 세로 줄무늬 그리기
|
||||
var x = 0f
|
||||
while (x < width) {
|
||||
canvas.drawRect(x, 0f, x + lineWidth, height, paint)
|
||||
x += lineWidth + gap
|
||||
}
|
||||
|
||||
// 마지막 세로 줄 추가
|
||||
// if (x - gap < width) {
|
||||
// canvas.drawRect(x - gap, 0f, width, height, paint)
|
||||
// }
|
||||
|
||||
// 가로 줄무늬 그리기
|
||||
var y = 0f
|
||||
while (y < height) {
|
||||
canvas.drawRect(0f, y, width, y + lineWidth, paint)
|
||||
y += lineWidth + gap
|
||||
}
|
||||
//
|
||||
// // 마지막 가로 줄 추가
|
||||
// if (y - gap < height) {
|
||||
// canvas.drawRect(0f, y - gap, width, height, paint)
|
||||
// }
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import com.example.smart119.App
|
||||
import com.example.smart119.R
|
||||
|
||||
object LoadingDialog : Dialog(App.instance) {
|
||||
private var dialog: Dialog? = null
|
||||
|
||||
fun showDlg(context: Context) {
|
||||
// Context가 유효한지 확인
|
||||
if (dialog?.isShowing == true) return
|
||||
|
||||
|
||||
// Context가 유효하지 않다면 종료
|
||||
if (context !is android.app.Activity || context.isFinishing || context.isDestroyed) return
|
||||
|
||||
dialog = Dialog(context).apply {
|
||||
setContentView(R.layout.dialog_loading)
|
||||
setCancelable(false)
|
||||
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
show()
|
||||
}
|
||||
|
||||
println("show Loading dialog")
|
||||
}
|
||||
|
||||
fun hideDlg() {
|
||||
dialog?.hide()
|
||||
}
|
||||
|
||||
fun dismissDlg() {
|
||||
dialog?.dismiss()
|
||||
dialog = null
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,745 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.location.Location
|
||||
import android.os.Bundle
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.StyleSpan
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.ImageButton
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.smart119.API_Helper
|
||||
import com.example.smart119.AlertDialogUtil
|
||||
import com.example.smart119.HelpUtility
|
||||
import com.example.smart119.ListItem
|
||||
import com.example.smart119.LocationHelper
|
||||
import com.example.smart119.LoginManager
|
||||
import com.example.smart119.MedicalInfo
|
||||
import com.example.smart119.R
|
||||
import com.example.smart119.SpreadsheetAdapter
|
||||
import com.example.smart119.TransferManager
|
||||
import com.example.smart119.TransferState
|
||||
import com.example.smart119.datas.HospitalSearch
|
||||
import com.example.smart119.datas.SaveLogin
|
||||
import com.example.smart119.interfaces.RetrofitClient
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.google.gson.JsonObject
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
class LocationSearchFragment : Fragment() {
|
||||
private lateinit var lsAdapter: SpreadsheetAdapter
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
return inflater.inflate(R.layout.location_search_page, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
FragmentHandler.registerView("LocationSearchFragment", view)
|
||||
|
||||
hospitalInit(view);
|
||||
HospitalSearch.clearAllData()
|
||||
|
||||
val searchButton = view.findViewById<Button>(R.id.hospSearchButton)
|
||||
searchButton.setOnClickListener {
|
||||
var _sel_medical = view.findViewById<Spinner>(R.id.spMedical).selectedItem as String;
|
||||
var _sel_depart = view.findViewById<Spinner>(R.id.spDepart).selectedItem as String;
|
||||
var _sel_emg_yn = view.findViewById<Spinner>(R.id.spEmgYN).selectedItem as String;
|
||||
|
||||
lsAdapter.clearHospitalList();
|
||||
HospitalSearch.clearAllData();
|
||||
|
||||
//success
|
||||
// val resObj = res.getAsJsonObject();
|
||||
// val callResult = resObj["isSuccess"]?.asBoolean ?: true;
|
||||
val lon = LocationHelper.getCurrentLon();
|
||||
val lat = LocationHelper.getCurrentLat();
|
||||
|
||||
var page = "1"
|
||||
var row = "4"
|
||||
var dg_list = emptyList<String>()//listOf("","")
|
||||
|
||||
val hospCatTV = view.findViewById<TextView>(R.id.hospCatLocText)
|
||||
val hospPrtTV = view.findViewById<TextView>(R.id.hospPrtLocText)
|
||||
|
||||
var _code_medical = MedicalInfo.get_emogemdv_code(hospCatTV.text.toString());
|
||||
var _code_depart = MedicalInfo.get_prt_code(hospPrtTV.text.toString());
|
||||
var _emg_yn = _sel_emg_yn;
|
||||
var _relate = ""
|
||||
|
||||
try {
|
||||
_relate = HospitalSearch.getSearchInfo()["relate"].asString;
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
|
||||
if (_code_medical == null) _code_medical = ""
|
||||
if (_code_depart == null) _code_depart = ""
|
||||
if (_emg_yn.indexOf("응급실 포함여부") != -1) _emg_yn = "Y"
|
||||
|
||||
// println("의료기관:${_sel_medical}|${_code_medical}, 진료과:${_sel_depart}|${_code_depart}, 응급실:${_emg_yn}")
|
||||
|
||||
var reqBody: JsonObject = API_Helper.make_arroundHosp_param2(
|
||||
lon = lon.toString(),
|
||||
lat = lat.toString(),
|
||||
emogemdv = "${_code_medical}",
|
||||
prtcode = "${_code_depart}",
|
||||
emergency = "${_emg_yn}",
|
||||
emogdesc = "${_relate}",
|
||||
page = "${page}",
|
||||
row = "${row}"
|
||||
);
|
||||
|
||||
try {
|
||||
LoadingDialog.showDlg(requireContext())
|
||||
HospitalSearch.SET_SearchRequest(false, reqBody)
|
||||
RetrofitClient.locInstance.getAroundHospitalList(reqBody)
|
||||
.enqueue(arroundHospitalResponse())
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
LoadingDialog.hideDlg()
|
||||
}
|
||||
|
||||
/*
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "병원 검색 결과",
|
||||
message = "현재 위치를 알수 없어 검색 되지 않았습니다, 다시 시도해주세요."
|
||||
)
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
val prevLSButton = view.findViewById<Button>(R.id.pagePrevLS)
|
||||
prevLSButton.setOnClickListener {
|
||||
if (HospitalSearch.getAllData().size > 0) {
|
||||
var bChanged = PaginationHelper.prevPage(requireView(), { page ->
|
||||
page_onclick_listener(page)
|
||||
})
|
||||
//request page
|
||||
if (bChanged) {
|
||||
var currPage = PaginationHelper.currentPage;
|
||||
// println("prev request number ${PaginationHelper.currentPage}")
|
||||
page_onclick_listener(currPage)
|
||||
}
|
||||
// else println("no request prev")
|
||||
}
|
||||
}
|
||||
|
||||
val nextLSButton = view.findViewById<Button>(R.id.pageNextLS)
|
||||
nextLSButton.setOnClickListener {
|
||||
if (HospitalSearch.getAllData().size > 0) {
|
||||
var bChanged = PaginationHelper.nextPage(requireView(), { page ->
|
||||
page_onclick_listener(page)
|
||||
})
|
||||
//request page
|
||||
if (bChanged) {
|
||||
var currPage = PaginationHelper.currentPage;
|
||||
// println("next request number ${PaginationHelper.currentPage}")
|
||||
page_onclick_listener(currPage)
|
||||
}
|
||||
// else println("no request next")
|
||||
}
|
||||
}
|
||||
|
||||
val gpsRefreshButton = view.findViewById<ImageButton>(R.id.gpsRefresh)
|
||||
gpsRefreshButton.setOnClickListener {
|
||||
Hospital_UIUpdate(true)
|
||||
}
|
||||
|
||||
val hospCatLocTV = view.findViewById<TextView>(R.id.hospCatLocText)
|
||||
hospCatLocTV.setOnClickListener {
|
||||
HospitalCategoryLocation_Dialog.show(requireContext())
|
||||
}
|
||||
|
||||
HospitalCategoryLocation_Dialog.registerCallback { evtString ->
|
||||
println("의료기관 선택 이벤트!! ${evtString}")
|
||||
}
|
||||
|
||||
val hospPrtLocTV = view.findViewById<TextView>(R.id.hospPrtLocText)
|
||||
hospPrtLocTV.setOnClickListener {
|
||||
DepartmentLocation_Dialog.show(requireContext())
|
||||
}
|
||||
|
||||
DepartmentLocation_Dialog.registerCallback { evtString ->
|
||||
println("진료과 선택 이벤트!! ${evtString}")
|
||||
}
|
||||
|
||||
try {
|
||||
if (!HospitalSearch.get_gps_address().isEmpty()) {
|
||||
Hospital_UIUpdate_SET(view)
|
||||
}
|
||||
Hospital_UIUpdate()
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
// Toast.makeText(requireContext(), "위치기반 탭 활성화!", Toast.LENGTH_SHORT).show()
|
||||
// println("위치기반 탭 활성화!")
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
// println("위치기반 탭 비 활성화!")
|
||||
lsAdapter.clearHospitalList()
|
||||
HospitalSearch.clearAllData()
|
||||
PaginationHelper.setupPaginationLayout(
|
||||
requireView(),
|
||||
0, 0, { page ->
|
||||
page_onclick_listener(page)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
FragmentHandler.unregisterView("LocationSearchFragment")
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun hospitalInit(view: View) {
|
||||
var items = listOf(
|
||||
ListItem.Header(listOf("병원이름")), // 헤더 열 정의
|
||||
ListItem.Header(listOf("주소")),
|
||||
ListItem.Header(listOf("전화번호")),
|
||||
ListItem.Header(listOf("라이다 혼잡도")),
|
||||
ListItem.Header(listOf("거리")),
|
||||
ListItem.Header(listOf("병원별 이송 시작"))
|
||||
)
|
||||
val recyclerViewLS: RecyclerView = view.findViewById(R.id.reCyclerViewLS)
|
||||
|
||||
val spanCount = 6;
|
||||
lsAdapter = SpreadsheetAdapter(
|
||||
items,
|
||||
onButtonClick = { row, pos ->
|
||||
//row.values[0]
|
||||
|
||||
lsAdapter.setSelectedHospitalPos(pos)
|
||||
HospitalSearch.setIdx(lsAdapter.getSelectedPosition())
|
||||
var selectedHospital = lsAdapter.getSelectedHospital()
|
||||
var getSelData = HospitalSearch.getSelectedData()
|
||||
if (selectedHospital is ListItem.Row) {
|
||||
var hospitalName = selectedHospital.values[0];
|
||||
var hospitalAddress = selectedHospital.values[1];
|
||||
var hospitalCallNumber = selectedHospital.values[2];
|
||||
var hospitalLiDAR = selectedHospital.values[3];
|
||||
var hospitalDistance = selectedHospital.values[4];
|
||||
if (TransferManager.getState() == TransferState.STARTED) {
|
||||
//이송 변경
|
||||
//변경된 병원 정보 설정
|
||||
val spannableMessage = SpannableStringBuilder().apply {
|
||||
val preText = "병원 이름 : ${hospitalName}" + "\n" +
|
||||
"주소 : ${hospitalAddress}" + "\n" +
|
||||
"전화번호 : ${hospitalCallNumber}" + "\n" +
|
||||
"거리 : ${hospitalDistance}" + "\n" +
|
||||
"라이다혼잡도 : ${hospitalLiDAR}" + "\n"
|
||||
append(preText)
|
||||
|
||||
val boldText = "확인"
|
||||
append(boldText)
|
||||
setSpan(
|
||||
StyleSpan(Typeface.BOLD), preText.length,
|
||||
preText.length + boldText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
append(" 선택시 환자정보가 전송됩니다.(변경 시 기존 이송 병원이 변경됩니다.)\n")
|
||||
}
|
||||
|
||||
AlertDialogUtil.showAlert_CUSTOM(
|
||||
context = requireActivity(),
|
||||
title = "이송 병원 정보",
|
||||
sppStr = spannableMessage,
|
||||
onPositiveClick = {
|
||||
AlertDialogUtil.showAlert_OK(
|
||||
context = requireActivity(),
|
||||
title = "진행 전 확인사항",
|
||||
message = "진행하시기 전에, 구급활동일지 임시저장을 하셨는지 확인해 주세요\n",
|
||||
onPositiveClick = {
|
||||
val bottomNaviView =
|
||||
requireActivity().findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
bottomNaviView.selectedItemId = R.id.hospTransfer;
|
||||
TransferManager.changeTransfer()
|
||||
}
|
||||
)
|
||||
},
|
||||
onNegativeClick = {}
|
||||
)
|
||||
|
||||
} else {
|
||||
val spannableMessage = SpannableStringBuilder().apply {
|
||||
val preText = "병원 이름 : ${hospitalName}" + "\n" +
|
||||
"주소 : ${hospitalAddress}" + "\n" +
|
||||
"전화번호 : ${hospitalCallNumber}" + "\n" +
|
||||
"거리 : ${hospitalDistance}" + "\n" +
|
||||
"라이다혼잡도 : ${hospitalLiDAR}" + "\n"
|
||||
append(preText)
|
||||
|
||||
val boldText = "확인"
|
||||
append(boldText)
|
||||
setSpan(
|
||||
StyleSpan(Typeface.BOLD), preText.length,
|
||||
preText.length + boldText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
append(" 선택시 환자정보가 전송됩니다.\n")
|
||||
}
|
||||
|
||||
AlertDialogUtil.showAlert_CUSTOM(
|
||||
context = requireActivity(),
|
||||
title = "이송 병원 정보",
|
||||
sppStr = spannableMessage,
|
||||
onPositiveClick = {
|
||||
|
||||
AlertDialogUtil.showAlert_OK(
|
||||
context = requireActivity(),
|
||||
title = "진행 전 확인사항",
|
||||
message = "진행하시기 전에, 구급활동일지 임시저장을 하셨는지 확인해 주세요\n",
|
||||
onPositiveClick = {
|
||||
if (TransferManager.startTransfer()) {
|
||||
val bottomNaviView =
|
||||
requireActivity().findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
bottomNaviView.selectedItemId = R.id.hospTransfer;
|
||||
} else {
|
||||
// 시작되지 않았습니다.
|
||||
Toast.makeText(
|
||||
requireActivity(), "이송이 시작되지 않았습니다. 다시 전송해주세요.",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
onNegativeClick = {}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "선택된 병원 정보",
|
||||
message = "병원 검색 후 선택해주세요!"
|
||||
)
|
||||
}
|
||||
//이송시작
|
||||
println(row)
|
||||
|
||||
//pos, row(ListItem상 선택 위치, 선택한 row 정보) -> hpid는?
|
||||
},
|
||||
onRowClick = { row ->
|
||||
// Toast.makeText(requireActivity(), "${row.values[0]}이 선택되었습니다.", Toast.LENGTH_SHORT)
|
||||
// .show()
|
||||
}
|
||||
)
|
||||
lsAdapter.setColumnCount(spanCount)
|
||||
recyclerViewLS.adapter = lsAdapter
|
||||
|
||||
// GridLayoutManager 설정
|
||||
val layoutManager = GridLayoutManager(requireActivity(), spanCount)
|
||||
layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
// return if (adapter.getItemViewType(position) == SpreadsheetAdapter.VIEW_TYPE_HEADER) 3 else 1
|
||||
return if (lsAdapter.getItemViewType(position) == SpreadsheetAdapter.VIEW_TYPE_ROW) {
|
||||
spanCount // Row가 전체 열을 차지하도록 설정
|
||||
} else {
|
||||
1 // 기본적으로 각 항목은 한 열을 차지
|
||||
}
|
||||
}
|
||||
}
|
||||
recyclerViewLS.layoutManager = layoutManager
|
||||
}
|
||||
|
||||
private fun Hospital_UIUpdate(bForceUpdate:Boolean = false) {
|
||||
val lon = LocationHelper.getCurrentLon();
|
||||
val lat = LocationHelper.getCurrentLat();
|
||||
val currentTime = System.currentTimeMillis()
|
||||
val _prev_gps = HospitalSearch.getPrevGPSInfo()
|
||||
// println("lon:${lon}, lat:${lat}, prev lon:${_prev_gps["prevLon"].asDouble}, prev lat:${_prev_gps["prevLat"].asDouble}")
|
||||
|
||||
//이전 업데이트가 1km 이내에서 한 경우, 업데이트 하지 않음
|
||||
if (shouldUpdateLocation(
|
||||
_prev_gps["prevLat"].asDouble,
|
||||
_prev_gps["prevLon"].asDouble,
|
||||
_prev_gps["prevTime"].asLong,
|
||||
lat,
|
||||
lon,
|
||||
currentTime
|
||||
) || bForceUpdate
|
||||
) {
|
||||
RetrofitClient.pathInstance.getAddr(
|
||||
API_Helper.make_getAddr_param(lon.toString(), lat.toString())
|
||||
).enqueue(getPathAddressResponse())
|
||||
HospitalSearch.setPrevGPSUpdate(lon, lat, System.currentTimeMillis())
|
||||
println("카카오 위치 -> 주소 변환 API 요청");
|
||||
} else {
|
||||
println("카카오 위치 -> 주소 변환 API 요청 안함");
|
||||
}
|
||||
}
|
||||
private fun Hospital_UIUpdate_SET(view:View) {
|
||||
var addrString = HospitalSearch.get_gps_address()
|
||||
var geoTv = view.findViewById<TextView>(R.id.tvGeoLocation)
|
||||
geoTv.text = addrString;
|
||||
}
|
||||
|
||||
private fun getPathAddressResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
val resObj = response.body();
|
||||
val metaObj = resObj?.get("meta");
|
||||
if (metaObj != null) {
|
||||
val tot_count = metaObj.asJsonObject["total_count"].asInt
|
||||
if (tot_count > 0) {
|
||||
val lsfView = requireView()
|
||||
if (lsfView != null) {
|
||||
|
||||
val docus = resObj.getAsJsonArray("documents")
|
||||
val addObj = docus[0].asJsonObject["address"];
|
||||
val add_full = addObj.asJsonObject["address_name"]
|
||||
// val add_si = addObj.asJsonObject["region_1depth_name"]
|
||||
// val add_gu = addObj.asJsonObject["region_2depth_name"]
|
||||
// val add_dong = addObj.asJsonObject["region_3depth_name"]
|
||||
|
||||
var geoTv = lsfView.findViewById<TextView>(R.id.tvGeoLocation)
|
||||
geoTv.text = add_full.asString;
|
||||
|
||||
HospitalSearch.set_gps_update(add_full.asString)
|
||||
}
|
||||
}
|
||||
}
|
||||
//response.body()["meta"].asJsonObject["total_count"]
|
||||
println(response)
|
||||
} else {
|
||||
println("address not found")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
println(t.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun arroundHospitalResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
LoadingDialog.hideDlg()
|
||||
if (response.isSuccessful) {
|
||||
val resBody = response.body();
|
||||
if (resBody != null) {
|
||||
set_hospital_list(resBody)
|
||||
}
|
||||
else {
|
||||
nav_to_login();
|
||||
}
|
||||
} else {
|
||||
nav_to_login();
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
LoadingDialog.hideDlg()
|
||||
println(t.message)
|
||||
nav_to_login();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun set_hospital_list(resobj:JsonObject?, isAddress:Boolean = false) {
|
||||
var totPages = resobj?.get("totalPages") // 총 페이지
|
||||
var totRows = resobj?.get("totalRows") // 총 행 개수
|
||||
var searchRows = resobj?.get("row") // 검색 페이지 행 개수
|
||||
var searchPage = resobj?.get("page") // 검색 페이지 번호
|
||||
var resData = resobj?.getAsJsonArray("resData")
|
||||
var dataSize = resData?.size() ?: 0;
|
||||
|
||||
var hospitalSearchRes: List<List<String>> = mutableListOf()
|
||||
var hpidList: MutableList<String> = mutableListOf()
|
||||
if (dataSize > 0) {
|
||||
// region 검색 결과 리스트에 세팅
|
||||
try {
|
||||
resData?.forEach { item ->
|
||||
val itemObj = item.asJsonObject;
|
||||
var levelState =
|
||||
API_Helper.lidar_levelState(itemObj.get("levelState").asInt)
|
||||
var itemHpid = itemObj.get("hpid").toString().trim('"');
|
||||
hpidList.add(itemHpid)
|
||||
var itemDistance = ""
|
||||
var itemTel = ""
|
||||
var itemTitle = ""
|
||||
if (!isAddress) {
|
||||
itemDistance = itemObj.get("distance").toString().trim('"')
|
||||
itemTel = itemObj.get("tel").toString().trim('"')
|
||||
itemTitle = itemObj.get("title").toString().trim('"')
|
||||
}
|
||||
else {
|
||||
itemTel = itemObj.get("dutyTel1").toString().trim('"')
|
||||
itemTitle = itemObj.get("dutyName").toString().trim('"')
|
||||
}
|
||||
|
||||
HospitalSearch.addDataHospitalItems(
|
||||
listOf(
|
||||
HospitalSearch.itemStructure(
|
||||
itemHpid, levelState, itemDistance,
|
||||
itemObj.get("city").toString().trim('"'),
|
||||
itemObj.get("district").toString().trim('"'),
|
||||
itemTel, itemTitle
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
var total_Page = totPages?.asInt;
|
||||
if (total_Page == null) total_Page = 0;
|
||||
var total_Row = totRows?.asInt;
|
||||
if (total_Row == null) total_Row = 0;
|
||||
PaginationHelper.setupPaginationLayout(requireView(), total_Page, total_Row, { page ->
|
||||
page_onclick_listener(page)
|
||||
})
|
||||
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(requireActivity(), "${e.message}", Toast.LENGTH_LONG)
|
||||
.show()
|
||||
} finally {}
|
||||
|
||||
hospitalSearchRes = HospitalSearch.getAllData();
|
||||
} else {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "병원 검색 결과",
|
||||
message = "병원이 검색되지 않았습니다. 다시 시도해주세요."
|
||||
)
|
||||
|
||||
if (!PaginationHelper.pageRequest) PaginationHelper.setupPaginationLayout(
|
||||
requireView(),
|
||||
0, 0, { page ->
|
||||
page_onclick_listener(page)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
//병원 검색 결과 설정
|
||||
if (hospitalSearchRes.size > 0) lsAdapter.hospitalListUpdate(hospitalSearchRes, hpidList)
|
||||
// endregion
|
||||
}
|
||||
|
||||
private fun page_onclick_listener(page:Int) {
|
||||
// println("clicked page ${page}")
|
||||
var reqBody = HospitalSearch.GET_SearchRequest()
|
||||
if (reqBody != null) {
|
||||
try {
|
||||
// if (HospitalSearch.isAddressSearch()) {
|
||||
// LoadingDialog.showDlg(requireContext())
|
||||
// reqBody = reqBody.getAsJsonObject("reqBody")
|
||||
// reqBody.addProperty("page", "${page}")
|
||||
// RetrofitClient.locInstance.getAddressHospitalList(reqBody).enqueue(getAddress_Paging_Response())
|
||||
// } else {
|
||||
LoadingDialog.showDlg(requireContext())
|
||||
reqBody = reqBody.getAsJsonObject("reqBody")
|
||||
reqBody.addProperty("page", "${page}")
|
||||
RetrofitClient.locInstance.getAroundHospitalList(reqBody)
|
||||
.enqueue(arroundHospital_Paging_Response())
|
||||
// }
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
LoadingDialog.hideDlg()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private fun getAddress_Paging_Response(): Callback<JsonObject>{
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
LoadingDialog.hideDlg()
|
||||
if (response.isSuccessful) {
|
||||
val resObj = response.body();
|
||||
set_hospital_list_page(resObj, true)
|
||||
} else {
|
||||
println("hospital not found")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
LoadingDialog.hideDlg()
|
||||
println(t.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
private fun arroundHospital_Paging_Response(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
LoadingDialog.hideDlg()
|
||||
if (response.isSuccessful) {
|
||||
val resBody = response.body();
|
||||
if (resBody != null) {
|
||||
set_hospital_list_page(resBody)
|
||||
}
|
||||
else {
|
||||
nav_to_login();
|
||||
}
|
||||
} else {
|
||||
nav_to_login();
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
LoadingDialog.hideDlg()
|
||||
println(t.message)
|
||||
nav_to_login();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun set_hospital_list_page(resobj:JsonObject?) {
|
||||
// region 현재 병원 리스트 초기화
|
||||
lsAdapter.clearHospitalList();
|
||||
HospitalSearch.clearAllData();
|
||||
// endregion
|
||||
|
||||
var totPages = resobj?.get("totalPages") // 총 페이지
|
||||
var totRows = resobj?.get("totalRows") // 총 행 개수
|
||||
var searchRows = resobj?.get("row") // 검색 페이지 행 개수
|
||||
var searchPage = resobj?.get("page") // 검색 페이지 번호
|
||||
var resData = resobj?.getAsJsonArray("resData")
|
||||
var dataSize = resData?.size() ?: 0;
|
||||
|
||||
var hospitalSearchRes: List<List<String>> = mutableListOf()
|
||||
var hpidList: MutableList<String> = mutableListOf()
|
||||
if (dataSize > 0) {
|
||||
// region 검색 결과 리스트에 세팅
|
||||
try {
|
||||
resData?.forEach { item ->
|
||||
val itemObj = item.asJsonObject;
|
||||
var levelState =
|
||||
API_Helper.lidar_levelState(itemObj.get("levelState").asInt)
|
||||
var itemHpid = itemObj.get("hpid").toString().trim('"');
|
||||
hpidList.add(itemHpid)
|
||||
var itemDistance = ""
|
||||
var itemTel = ""
|
||||
var itemTitle = ""
|
||||
// if (!isAddress) {
|
||||
//위치기반 검색 시 사용하는 곳
|
||||
itemDistance = itemObj.get("distance").toString().trim('"')
|
||||
itemTel = itemObj.get("tel").toString().trim('"')
|
||||
itemTitle = itemObj.get("title").toString().trim('"')
|
||||
// }
|
||||
// else {
|
||||
///주소 검색 시 사용하는 곳
|
||||
// itemTel = itemObj.get("dutyTel1").toString().trim('"')
|
||||
// itemTitle = itemObj.get("dutyName").toString().trim('"')
|
||||
// }
|
||||
|
||||
HospitalSearch.addDataHospitalItems(
|
||||
listOf(
|
||||
HospitalSearch.itemStructure(
|
||||
itemHpid, levelState, itemDistance,
|
||||
itemObj.get("city").toString().trim('"'),
|
||||
itemObj.get("district").toString().trim('"'),
|
||||
itemTel, itemTitle
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
var total_Page = totPages?.asInt;
|
||||
if (total_Page == null) total_Page = 0;
|
||||
var total_Row = totRows?.asInt;
|
||||
if (total_Row == null) total_Row = 0;
|
||||
|
||||
// PaginationHelper.rePaginationLayout(requireView(), { page ->
|
||||
// page_onclick_listener(page)
|
||||
// })
|
||||
// PaginationHelper.setupPaginationLayout(requireView(), total_Page, total_Row, { page ->
|
||||
// page_onclick_listener(page)
|
||||
// })
|
||||
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(requireActivity(), "${e.message}", Toast.LENGTH_LONG)
|
||||
.show()
|
||||
} finally {}
|
||||
|
||||
hospitalSearchRes = HospitalSearch.getAllData();
|
||||
} else {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "병원 검색 결과",
|
||||
message = "병원이 검색되지 않았습니다. 다시 시도해주세요."
|
||||
)
|
||||
|
||||
if (!PaginationHelper.pageRequest) PaginationHelper.setupPaginationLayout(
|
||||
requireView(),
|
||||
0, 0, { page ->
|
||||
page_onclick_listener(page)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
//병원 검색 결과 설정
|
||||
if (hospitalSearchRes.size > 0) lsAdapter.hospitalListUpdate(hospitalSearchRes, hpidList)
|
||||
// endregion
|
||||
}
|
||||
|
||||
fun shouldUpdateLocation(
|
||||
prevLat: Double, prevLng: Double, prevTime: Long, // 이전 위도, 경도, 업데이트 시간 (ms)
|
||||
newLat: Double, newLng: Double, newTime: Long, // 새로운 위도, 경도, 현재 시간 (ms)
|
||||
intervalMs: Long = 300000 // 기본 업데이트 주기: 5분 (300,000ms)
|
||||
): Boolean {
|
||||
val prevLocation = Location("").apply {
|
||||
latitude = prevLat
|
||||
longitude = prevLng
|
||||
}
|
||||
|
||||
val newLocation = Location("").apply {
|
||||
latitude = newLat
|
||||
longitude = newLng
|
||||
}
|
||||
|
||||
val distance = prevLocation.distanceTo(newLocation) // 두 지점 간 거리 (단위: m)
|
||||
val timeDiff = newTime - prevTime // 시간 차이 (ms)
|
||||
|
||||
println("${distance}, ${timeDiff}")
|
||||
val state_dist = (distance >= 1000)
|
||||
val state_time = (timeDiff >= intervalMs)
|
||||
val state_lonlat = (prevLat != newLat || prevLng != newLng)
|
||||
val state_lonlatDist = ((prevLat != newLat || prevLng != newLng) && distance >= 1000)
|
||||
println("${state_dist}, ${state_time}, ${state_lonlat}, ${state_lonlatDist}")
|
||||
|
||||
return ((prevLat != newLat || prevLng != newLng) && distance >= 1000) || timeDiff >= intervalMs
|
||||
}
|
||||
|
||||
fun nav_to_login() {
|
||||
AlertDialogUtil.showAlert_OK(
|
||||
context = requireActivity(),
|
||||
title = "세션 만료",
|
||||
message = "기존 세션이 만료되었습니다. 다시 로그인 해주시기 바랍니다.\n",
|
||||
onPositiveClick = {
|
||||
SaveLogin.setLogin(false)
|
||||
LoginManager.setLoggedIn(false);
|
||||
val bottomNaviView =
|
||||
requireActivity().findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
bottomNaviView.selectedItemId = R.id.emgLogin;
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
}
|
355
app/src/main/java/com/example/smart119/views/LoginFragment.kt
Normal file
@ -0,0 +1,355 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.example.smart119.API_Helper
|
||||
import com.example.smart119.AlertDialogUtil
|
||||
import com.example.smart119.BuildConfig
|
||||
import com.example.smart119.LocationHelper
|
||||
import com.example.smart119.LoginManager
|
||||
import com.example.smart119.LoginManager.tryLoginBody
|
||||
import com.example.smart119.MyCookieJar
|
||||
import com.example.smart119.R
|
||||
import com.example.smart119.TransferManager
|
||||
import com.example.smart119.databinding.FragmentFirstBinding
|
||||
import com.example.smart119.datas.SaveLogin
|
||||
|
||||
import com.example.smart119.interfaces.RetrofitClient
|
||||
import com.google.gson.JsonObject
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import okhttp3.Cookie
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass as the default destination in the navigation.
|
||||
*/
|
||||
class LoginFragment : Fragment() {
|
||||
|
||||
private var _binding: FragmentFirstBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private val cookieStore: MutableMap<String, MutableList<Cookie>> = mutableMapOf()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
|
||||
_binding = FragmentFirstBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
//현재 창이 보여질 때 호출되는 함수
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
println("login fragment!!")
|
||||
|
||||
val button: Button = view.findViewById(R.id.accessButton)
|
||||
button.setBackgroundColor(Color.parseColor("#0971B8"))
|
||||
|
||||
//#region 바로 preference로 로그인 체크
|
||||
login_check()
|
||||
//#endregion
|
||||
|
||||
binding.accessButton.setOnClickListener {
|
||||
val userIdTextInput: TextInputEditText = view.findViewById(R.id.loginIdText); //"kwonkhj01"
|
||||
val carNoTextInput: TextInputEditText = view.findViewById(R.id.carNoText);//"70보2495"
|
||||
|
||||
var _inputId = userIdTextInput.text.toString()
|
||||
var _inputCarno = carNoTextInput.text.toString()
|
||||
|
||||
var _isPass:Boolean = false;
|
||||
// debug용으로, 시작 버튼 눌렀을때 바로 자동 입력
|
||||
// region
|
||||
if(_inputId.isEmpty()) {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireContext(),
|
||||
title = "로그인 오류",
|
||||
message = "유저 아이디를 입력해주세요",
|
||||
onPositiveClick = {
|
||||
//로그아웃 처리
|
||||
},
|
||||
onNegativeClick = {
|
||||
|
||||
}
|
||||
)
|
||||
_isPass = true;
|
||||
// _inputId = "keeys1993"
|
||||
}
|
||||
else if(_inputCarno.isEmpty()) {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireContext(),
|
||||
title = "로그인 오류",
|
||||
message = "차량 번호를 입력해주세요",
|
||||
onPositiveClick = {
|
||||
//로그아웃 처리
|
||||
},
|
||||
onNegativeClick = {
|
||||
|
||||
}
|
||||
)
|
||||
_isPass = true;
|
||||
// _inputCarno = "998마2352"
|
||||
}
|
||||
// endregion
|
||||
// println("login info ${_inputId}, ${_inputCarno}")
|
||||
|
||||
|
||||
if (!_isPass) {
|
||||
LoadingDialog.showDlg(requireContext())
|
||||
|
||||
LoginManager.setLoggedInfo(_inputId, _inputCarno, BuildConfig.APP_VERSION);
|
||||
val loginBody = LoginManager.getLoggedInfo();
|
||||
println("로그인 정보 ${loginBody["userId"].asString}, ${loginBody["carNo"].asString}, ${loginBody["ver"].asString}")
|
||||
RetrofitClient.loginInstance.mLogin(loginBody)
|
||||
.enqueue(loginResponse())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
private fun login_check() {
|
||||
|
||||
if (SaveLogin.isLoggedIn()) {
|
||||
//로그인 상태면 바로 로그인 요청 후 진행
|
||||
var _inputId = SaveLogin.getUserId()
|
||||
var _inputCarno = SaveLogin.getCarNo()
|
||||
|
||||
if (_inputId == null || _inputId.isEmpty()) return;
|
||||
if (_inputCarno == null || _inputCarno.isEmpty()) return;
|
||||
|
||||
println(BuildConfig.APP_VERSION);
|
||||
|
||||
LoadingDialog.showDlg(requireContext())
|
||||
LoginManager.setLoggedInfo(_inputId, _inputCarno, BuildConfig.APP_VERSION);
|
||||
val loginBody = LoginManager.getLoggedInfo();
|
||||
println("로그인 정보 ${loginBody["userId"].asString}, ${loginBody["carNo"].asString}, ${loginBody["ver"].asString}")
|
||||
RetrofitClient.loginInstance.mLogin(loginBody).enqueue(loginResponse())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun loginResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
// println("Stored cookies: ${MyCookieJar.getCookies()}")
|
||||
try {
|
||||
val resBody = response.body();
|
||||
val status = resBody?.get("status")?.asString;
|
||||
if (status == "success") {
|
||||
val cookies = response.headers().values("Set-Cookie")
|
||||
// println("Set-Cookie Headers: $cookies")
|
||||
for (cookie in cookies) {
|
||||
val cookieValue = cookie.split(";")[0] // "sessionId=abc123"만 추출
|
||||
MyCookieJar.setCookie(cookieValue)
|
||||
// println("Cookie Value: $cookieValue")
|
||||
}
|
||||
LoginManager.setLoggedIn(true);
|
||||
|
||||
var loginInfo = LoginManager.getLoggedInfo();
|
||||
if (loginInfo != null) {
|
||||
Toast.makeText(
|
||||
requireActivity(),
|
||||
"접속 되었습니다. [${loginInfo["userId"].asString}, ${loginInfo["carNo"].asString}]",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
|
||||
LoadingDialog.hideDlg()
|
||||
|
||||
//#region 로그인 정보 저장
|
||||
SaveLogin.setLogin(true);
|
||||
SaveLogin.setUserId(loginInfo["userId"].asString);
|
||||
SaveLogin.setCarNo(loginInfo["carNo"].asString);
|
||||
//#endregion
|
||||
|
||||
RetrofitClient.transferInstance.currentAction().enqueue(currentActionResponse())
|
||||
|
||||
// moveToHospSearch();
|
||||
}
|
||||
else {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "접속 실패",
|
||||
message = "접속 아이디와 차량번호를 확인해주세요. [${status}]"
|
||||
)
|
||||
LoadingDialog.hideDlg()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
LoadingDialog.hideDlg()
|
||||
}
|
||||
|
||||
} else {
|
||||
LoginManager.setLoggedIn(false);
|
||||
var loginInfo:JsonObject = LoginManager.getLoggedInfo();
|
||||
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "접속 실패",
|
||||
message = "접속 아이디와 차량번호를 확인해주세요. [${loginInfo.get("userId").toString()}, ${loginInfo.get("carNo").toString()}]"
|
||||
)
|
||||
LoadingDialog.hideDlg()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
LoadingDialog.hideDlg()
|
||||
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "접속 실패",
|
||||
message = "네트워크 상태를 확인해주세요. \n" + "${t.message}"
|
||||
)
|
||||
|
||||
if (SaveLogin.isLoggedIn()) {
|
||||
val thisView = requireView();
|
||||
val userIdTextInput: TextInputEditText =
|
||||
thisView.findViewById(R.id.loginIdText); //"kwonkhj01"
|
||||
val carNoTextInput: TextInputEditText =
|
||||
thisView.findViewById(R.id.carNoText);//"70보2495"
|
||||
|
||||
var _inputId = SaveLogin.getUserId()
|
||||
var _inputCarno = SaveLogin.getCarNo()
|
||||
|
||||
if (_inputId == null || _inputId.isEmpty()) return;
|
||||
if (_inputCarno == null || _inputCarno.isEmpty()) return;
|
||||
|
||||
userIdTextInput.setText(_inputId)
|
||||
carNoTextInput.setText(_inputCarno)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun cookieSendResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
println("cookie 성공")
|
||||
|
||||
} else {
|
||||
println("cookie 실패!!")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
//16 println("cookie 실패!!")
|
||||
println("Request Failed: ${t.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
try {
|
||||
val thisView = requireView();
|
||||
val userIdTextInput: TextInputEditText =
|
||||
thisView.findViewById(R.id.loginIdText); //"kwonkhj01"
|
||||
val carNoTextInput: TextInputEditText =
|
||||
thisView.findViewById(R.id.carNoText);//"70보2495"
|
||||
|
||||
var _inputId = SaveLogin.getUserId()
|
||||
var _inputCarno = SaveLogin.getCarNo()
|
||||
|
||||
if (_inputId == null || _inputId.isEmpty()) return;
|
||||
if (_inputCarno == null || _inputCarno.isEmpty()) return;
|
||||
|
||||
userIdTextInput.setText(_inputId)
|
||||
carNoTextInput.setText(_inputCarno)
|
||||
} catch (e: Exception) {
|
||||
//TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
private fun moveToHospSearch() {
|
||||
|
||||
try {
|
||||
val reqView = requireActivity();
|
||||
val bottomNaviView = reqView.findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
bottomNaviView.selectedItemId = R.id.hospSearch;
|
||||
} catch (e: Exception) {
|
||||
//TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
private fun currentActionResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
if (response.isSuccessful) {
|
||||
try {
|
||||
val resBody = response.body();
|
||||
val status = resBody?.get("status")?.asString;
|
||||
if (status == "true") {
|
||||
TransferManager.serverState.set(true);
|
||||
|
||||
AlertDialogUtil.showAlert_OK(
|
||||
context = requireContext(),
|
||||
title = "진행 중인 전송 정보",
|
||||
message = "현재 접속 정보로 진행중인 이송 건이 있습니다.",
|
||||
onPositiveClick = {
|
||||
moveToHospSearch();
|
||||
}
|
||||
)
|
||||
|
||||
/*
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireContext(),
|
||||
title = "진행 중인 전송 정보",
|
||||
message = "현재 접속 정보로 진행중인 이송 건이 있습니다. 취소하시겠습니까?",
|
||||
onPositiveClick = {
|
||||
TransferManager.cancelTransfer()
|
||||
moveToHospSearch();
|
||||
},
|
||||
onNegativeClick = {
|
||||
moveToHospSearch();
|
||||
}
|
||||
)
|
||||
*/
|
||||
|
||||
//시작된 상황
|
||||
}
|
||||
else {
|
||||
TransferManager.serverState.set(false);
|
||||
//시작 아닌 상황
|
||||
moveToHospSearch();
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
moveToHospSearch();
|
||||
}
|
||||
} else {
|
||||
moveToHospSearch();
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
moveToHospSearch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
273
app/src/main/java/com/example/smart119/views/PaginationHelper.kt
Normal file
@ -0,0 +1,273 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.view.setPadding
|
||||
import com.example.smart119.R
|
||||
|
||||
object PaginationHelper {
|
||||
var totalPages: Int = 1 // 전체 페이지 수
|
||||
var totalRows: Int = 1 // 전체 행 개수
|
||||
var currentPage: Int = 1 // 현재 페이지 번호
|
||||
var minPage: Int = 1 // 현재 표시되는 최소 페이지 번호
|
||||
var maxPage: Int = 5 // 현재 표시되는 최대 페이지 번호
|
||||
var buttonMap = mutableMapOf<Int, Button>()
|
||||
var pageRequest = false;
|
||||
|
||||
fun setupPaginationLayout(view: View, totalPage: Int, totalRow: Int, update_page:(Int)-> Unit) {
|
||||
totalPages = totalPage
|
||||
totalRows = totalRow
|
||||
currentPage = 1
|
||||
|
||||
// 최소 & 최대 페이지 계산
|
||||
// minPage = ((currentPage - 1) / 5) * 5 + 1
|
||||
minPage = currentPage
|
||||
maxPage = minPage + 4
|
||||
if (maxPage > totalPages) maxPage = totalPages
|
||||
|
||||
val pageButtonsContainer = view.findViewById<LinearLayout>(R.id.pageButtonsContainer)
|
||||
|
||||
// dp 값을 px로 변환
|
||||
val buttonWidthPx = (60 * Resources.getSystem().displayMetrics.density).toInt()
|
||||
val marginPx = (4 * Resources.getSystem().displayMetrics.density).toInt()
|
||||
|
||||
val buttonCount = maxPage - minPage + 1
|
||||
// 페이지 버튼 컨테이너 너비 설정 (340dp → px 변환)
|
||||
var totalWidthPx = (340 * Resources.getSystem().displayMetrics.density).toInt()
|
||||
totalWidthPx = (buttonCount * buttonWidthPx) + ((buttonCount - 1) * (marginPx * 2))
|
||||
pageButtonsContainer.layoutParams = LinearLayout.LayoutParams(totalWidthPx, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||
|
||||
val cornerRadiusPx = (10 * Resources.getSystem().displayMetrics.density).toFloat()
|
||||
|
||||
// 기존 버튼 초기화
|
||||
pageButtonsContainer.removeAllViews()
|
||||
_clear_button()
|
||||
if (totalPage == 0) {
|
||||
pageButtonsContainer.setPadding(10)
|
||||
return
|
||||
};
|
||||
else {
|
||||
pageButtonsContainer.setPadding(0)
|
||||
}
|
||||
|
||||
// 페이지 개수만큼 버튼 추가
|
||||
var pageCount = 0;
|
||||
for (page in minPage..maxPage) {
|
||||
val button = Button(pageButtonsContainer.context).apply {
|
||||
id = View.generateViewId()
|
||||
text = page.toString()
|
||||
textSize = 14f
|
||||
setPadding(6, 6, 6, 6)
|
||||
layoutParams = LinearLayout.LayoutParams(buttonWidthPx, ViewGroup.LayoutParams.MATCH_PARENT).apply {
|
||||
if (pageCount == 0) {
|
||||
marginStart = (marginPx)
|
||||
}
|
||||
marginEnd = marginPx
|
||||
}
|
||||
setOnClickListener {
|
||||
updatePage(view, page) // 페이지 변경
|
||||
update_page(page)
|
||||
}
|
||||
background = GradientDrawable().apply {
|
||||
shape = GradientDrawable.RECTANGLE
|
||||
cornerRadius = cornerRadiusPx
|
||||
setColor(Color.parseColor("#0971B8"))
|
||||
}
|
||||
setTextColor(Color.WHITE)
|
||||
}
|
||||
|
||||
// 현재 페이지 버튼 색상 강조
|
||||
if (page == currentPage) {
|
||||
button.background = GradientDrawable().apply {
|
||||
shape = GradientDrawable.RECTANGLE
|
||||
cornerRadius = cornerRadiusPx
|
||||
setColor(Color.BLUE)
|
||||
}
|
||||
button.setTextColor(Color.WHITE)
|
||||
}
|
||||
|
||||
pageButtonsContainer.addView(button)
|
||||
_add_button(page, button)
|
||||
|
||||
pageCount++;
|
||||
}
|
||||
|
||||
pageRequest = true;
|
||||
|
||||
println(buttonWidthPx)
|
||||
}
|
||||
|
||||
fun _add_button(pageNum:Int, btn:Button) {
|
||||
buttonMap[pageNum] = btn
|
||||
}
|
||||
fun _clear_button() {
|
||||
buttonMap.clear();
|
||||
}
|
||||
|
||||
fun rePaginationLayout(view: View, update_page:(Int)-> Unit) {
|
||||
val pageButtonsContainer = view.findViewById<LinearLayout>(R.id.pageButtonsContainer)
|
||||
|
||||
// dp 값을 px로 변환
|
||||
val buttonWidthPx = (60 * Resources.getSystem().displayMetrics.density).toInt()
|
||||
val marginPx = (4 * Resources.getSystem().displayMetrics.density).toInt()
|
||||
|
||||
val buttonCount = maxPage - minPage + 1
|
||||
// 페이지 버튼 컨테이너 너비 설정 (340dp → px 변환)
|
||||
var totalWidthPx = (340 * Resources.getSystem().displayMetrics.density).toInt()
|
||||
totalWidthPx = (buttonCount * buttonWidthPx) + ((buttonCount - 1) * (marginPx * 2))
|
||||
pageButtonsContainer.layoutParams = LinearLayout.LayoutParams(totalWidthPx, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||
|
||||
println("totalWidthPx ${totalWidthPx}")
|
||||
|
||||
val cornerRadiusPx = (10 * Resources.getSystem().displayMetrics.density).toFloat()
|
||||
|
||||
// 기존 버튼 초기화
|
||||
pageButtonsContainer.removeAllViews()
|
||||
_clear_button()
|
||||
|
||||
// 페이지 개수만큼 버튼 추가
|
||||
var pageCount = 0;
|
||||
for (page in minPage..maxPage) {
|
||||
val button = Button(pageButtonsContainer.context).apply {
|
||||
id = View.generateViewId()
|
||||
text = page.toString()
|
||||
textSize = 14f
|
||||
setPadding(6, 6, 6, 6)
|
||||
layoutParams = LinearLayout.LayoutParams(buttonWidthPx, ViewGroup.LayoutParams.MATCH_PARENT).apply {
|
||||
if (pageCount == 0) {
|
||||
marginStart = (marginPx)
|
||||
}
|
||||
marginEnd = marginPx
|
||||
}
|
||||
setOnClickListener {
|
||||
updatePage(view, page) // 페이지 변경
|
||||
update_page(page)
|
||||
}
|
||||
background = GradientDrawable().apply {
|
||||
shape = GradientDrawable.RECTANGLE
|
||||
cornerRadius = cornerRadiusPx
|
||||
setColor(Color.parseColor("#0971B8"))
|
||||
}
|
||||
setTextColor(Color.WHITE)
|
||||
}
|
||||
|
||||
// 현재 페이지 버튼 색상 강조
|
||||
if (page == currentPage) {
|
||||
button.background = GradientDrawable().apply {
|
||||
shape = GradientDrawable.RECTANGLE
|
||||
cornerRadius = cornerRadiusPx
|
||||
setColor(Color.BLUE)
|
||||
}
|
||||
button.setTextColor(Color.WHITE)
|
||||
}
|
||||
|
||||
pageButtonsContainer.addView(button)
|
||||
_add_button(page, button)
|
||||
|
||||
pageCount++;
|
||||
}
|
||||
}
|
||||
|
||||
fun nextPage(view: View, update_page: (Int) -> Unit):Boolean {
|
||||
if (currentPage == maxPage) {
|
||||
// 5==5 이고,
|
||||
if (maxPage < totalPages) {
|
||||
minPage = maxPage + 1
|
||||
if ((maxPage + 5) <= totalPages) {
|
||||
maxPage = maxPage + 5
|
||||
}
|
||||
else {
|
||||
maxPage = totalPages
|
||||
}
|
||||
|
||||
currentPage++;
|
||||
rePaginationLayout(view, { page ->
|
||||
update_page(page)
|
||||
})
|
||||
return true;
|
||||
}
|
||||
else return false
|
||||
}
|
||||
else {
|
||||
var bef_Page = buttonMap.get(currentPage);
|
||||
var nxt_Page = buttonMap.get(currentPage + 1);
|
||||
activePageButton(bef_Page, false)
|
||||
activePageButton(nxt_Page, true)
|
||||
currentPage++
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//1,2,3,4,5,6,7,8,9,10
|
||||
//12345
|
||||
//678910
|
||||
//6에서 prev 누른 경우,(min=6, max=10)
|
||||
fun prevPage(view: View, update_page: (Int) -> Unit):Boolean {
|
||||
if (currentPage == minPage) {
|
||||
if (minPage > 1) {
|
||||
var checkMax = maxPage - 5;
|
||||
if (checkMax < 5) checkMax = 5;
|
||||
maxPage = checkMax;
|
||||
minPage = minPage - 5;
|
||||
currentPage--;
|
||||
rePaginationLayout(view, { page ->
|
||||
update_page(page)
|
||||
})
|
||||
return true
|
||||
}
|
||||
else
|
||||
return false
|
||||
}
|
||||
else {
|
||||
if (currentPage > 1) {
|
||||
var bef_Page = buttonMap.get(currentPage);
|
||||
var prv_Page = buttonMap.get(currentPage - 1);
|
||||
activePageButton(bef_Page, false)
|
||||
activePageButton(prv_Page, true)
|
||||
currentPage--
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
fun activePageButton(pageBtn: Button?, isActive: Boolean) {
|
||||
if (isActive) {
|
||||
pageBtn?.background = GradientDrawable().apply {
|
||||
shape = GradientDrawable.RECTANGLE
|
||||
cornerRadius = (10 * Resources.getSystem().displayMetrics.density).toFloat()
|
||||
setColor(Color.BLUE)
|
||||
}
|
||||
pageBtn?.setTextColor(Color.WHITE)
|
||||
} else {
|
||||
pageBtn?.background = GradientDrawable().apply {
|
||||
shape = GradientDrawable.RECTANGLE
|
||||
cornerRadius = (10 * Resources.getSystem().displayMetrics.density).toFloat()
|
||||
setColor(Color.parseColor("#0971B8"))
|
||||
}
|
||||
pageBtn?.setTextColor(Color.WHITE)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun updatePage(view: View, newPage: Int) {
|
||||
if (newPage in 1..totalPages) {
|
||||
var bef_Page = buttonMap.get(currentPage);
|
||||
var nxt_Page = buttonMap.get(newPage);
|
||||
activePageButton(bef_Page, false)
|
||||
activePageButton(nxt_Page, true)
|
||||
|
||||
currentPage = newPage
|
||||
}
|
||||
}
|
||||
|
||||
fun getPageInfo(): String {
|
||||
return "총 페이지: $totalPages, 현재 페이지: $currentPage, 표시 범위: $minPage ~ $maxPage"
|
||||
}
|
||||
}
|
184
app/src/main/java/com/example/smart119/views/TransferFragment.kt
Normal file
@ -0,0 +1,184 @@
|
||||
package com.example.smart119.views
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.example.smart119.API_Helper
|
||||
import com.example.smart119.AlertDialogUtil
|
||||
import com.example.smart119.R
|
||||
import com.example.smart119.TransferManager
|
||||
import com.example.smart119.TransferState
|
||||
import com.example.smart119.datas.HospitalSearch
|
||||
import com.example.smart119.interfaces.RetrofitClient
|
||||
import com.example.smart119.viewModel.TransferViewModel
|
||||
import com.example.smart119.views.HospitalInfoPopup.showPopupTransfer
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.google.gson.JsonObject
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass.
|
||||
* Use the [TransferFragment.newInstance] factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
class TransferFragment : Fragment() {
|
||||
// TODO: Rename and change types of parameters
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// TransferManager.registerListener("transfer_update_event", { data ->
|
||||
// println("Transfer Update Event!!!")
|
||||
// })
|
||||
// TransferManager.registerListener("transfer_update_event", ::TransferUpdateEvent)
|
||||
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.fragment_transfer, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
FragmentHandler.registerView("TransferFragment", view)
|
||||
|
||||
// var tvHospName = view.findViewById<TextView>(R.id.tvTFHospName)
|
||||
// tvHospName.text = "서울특별시서남병원"
|
||||
|
||||
// 카카오 길찾기 API
|
||||
// val src_pos = "126.705098, 37.412087";
|
||||
// val dst_pos = "126.696239, 37.395276";
|
||||
// RetrofitClient.pathInstance.findPath(
|
||||
// API_Helper.make_findpath_param(src_pos, dst_pos)
|
||||
// ).enqueue(findPathResponse())
|
||||
|
||||
try {
|
||||
if (TransferManager.getState() == TransferState.STARTED) {
|
||||
TransferManager.SetLastHospitalInfo()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
}
|
||||
|
||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
// 뒤로 가기 동작 막음
|
||||
// println("Transfer 뒤로가기클릭!!")
|
||||
}
|
||||
})
|
||||
|
||||
view.findViewById<Button>(R.id.transferCancel).setOnClickListener {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "이송 취소",
|
||||
message = "이송을 취소하시겠습니까?",
|
||||
onPositiveClick = {
|
||||
// val bottomNaviView = requireActivity().findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
// bottomNaviView.selectedItemId = R.id.hospSearch;
|
||||
TransferManager.cancelTransfer()
|
||||
},
|
||||
onNegativeClick = {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
view.findViewById<Button>(R.id.transferComplete).setOnClickListener {
|
||||
AlertDialogUtil.showAlert(
|
||||
context = requireActivity(),
|
||||
title = "이송 완료",
|
||||
message = "이송을 종료하시겠습니까?",
|
||||
onPositiveClick = {
|
||||
val bottomNaviView = requireActivity().findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||
bottomNaviView.selectedItemId = R.id.hospSearch;
|
||||
TransferManager.completeTransfer()
|
||||
},
|
||||
onNegativeClick = {}
|
||||
)
|
||||
}
|
||||
|
||||
view.findViewById<Button>(R.id.btnTFDetailInfo).setOnClickListener {
|
||||
HospitalInfoPopup.showPopupTransfer(it)
|
||||
var getHPID = HospitalSearch.getHospitalID()
|
||||
if (!getHPID.isEmpty()) {
|
||||
try {
|
||||
LoadingDialog.showDlg(requireContext())
|
||||
var reqBody = API_Helper.make_detail_hosp_param(getHPID)
|
||||
RetrofitClient.hospitalInstance.getDetail(reqBody).enqueue(hospDetailResponse())
|
||||
HospitalInfoPopup.showPopupTransfer(it)
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
} finally {
|
||||
LoadingDialog.hideDlg()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun hospDetailResponse(): Callback<JsonObject> {
|
||||
return object : Callback<JsonObject> {
|
||||
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
|
||||
LoadingDialog.hideDlg()
|
||||
if (response.isSuccessful) {
|
||||
val resObj = response.body();
|
||||
//println(resObj)
|
||||
/*
|
||||
val metaObj = resObj?.get("meta");
|
||||
if (metaObj != null) {
|
||||
val tot_count = metaObj.asJsonObject["total_count"].asInt
|
||||
if (tot_count > 0) {
|
||||
var hsfView = FragmentHandler.getView("HospitalSearchFragment")
|
||||
if (hsfView != null) {
|
||||
|
||||
val docus = resObj.getAsJsonArray("documents")
|
||||
val addObj = docus[0].asJsonObject["address"];
|
||||
val add_full = addObj.asJsonObject["address_name"]
|
||||
val add_si = addObj.asJsonObject["region_1depth_name"]
|
||||
val add_gu = addObj.asJsonObject["region_2depth_name"]
|
||||
val add_dong = addObj.asJsonObject["region_3depth_name"]
|
||||
|
||||
var geoTv = hsfView.findViewById<TextView>(R.id.tvGeoLocation)
|
||||
geoTv.text = add_full.asString;
|
||||
|
||||
HospitalSearch.set_gps_update(add_full.asString)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
//response.body()["meta"].asJsonObject["total_count"]
|
||||
} else {
|
||||
println("hospital detail not found")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
|
||||
LoadingDialog.hideDlg()
|
||||
println(t.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
|
||||
// View를 Registry에서 제거
|
||||
|
||||
FragmentHandler.unregisterView("TransferFragment")
|
||||
|
||||
}
|
||||
|
||||
}
|
BIN
app/src/main/res/drawable/basic_logo.png
Normal file
After Width: | Height: | Size: 227 KiB |
15
app/src/main/res/drawable/border_line.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<!-- 배경색 (optional, 필요 시 설정) -->
|
||||
<solid android:color="#FFFFFF" /> <!-- 흰색 배경 -->
|
||||
|
||||
<!-- 테두리 설정 -->
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="#000000" /> <!-- 빨간색 테두리 -->
|
||||
|
||||
<!-- 모서리 설정 (optional, 필요 시 설정) -->
|
||||
<corners android:radius="8dp" /> <!-- 둥근 모서리 -->
|
||||
</shape>
|
BIN
app/src/main/res/drawable/gps.png
Normal file
After Width: | Height: | Size: 16 KiB |
74
app/src/main/res/drawable/ic_launcher_background.xml
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
android:height="108dp"
|
||||
android:width="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
</vector>
|
30
app/src/main/res/drawable/ic_launcher_foreground.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
5
app/src/main/res/drawable/ic_location_on.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z"/>
|
||||
|
||||
</vector>
|
BIN
app/src/main/res/drawable/login.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
app/src/main/res/drawable/logo.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
6
app/src/main/res/drawable/page_button_background.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#0971B8"/> <!-- 기본 배경색 -->
|
||||
<corners android:radius="10dp"/> <!-- 둥근 모서리 -->
|
||||
</shape>
|
BIN
app/src/main/res/drawable/search.png
Normal file
After Width: | Height: | Size: 17 KiB |
20
app/src/main/res/drawable/spinner_border.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<!-- #f5f5f5" 색으로 채움 -->
|
||||
<solid
|
||||
android:color="#f5f5f5"/>
|
||||
|
||||
<corners
|
||||
android:bottomLeftRadius="2dp"
|
||||
android:bottomRightRadius="2dp"
|
||||
android:topLeftRadius="2dp"
|
||||
android:topRightRadius="2dp" />
|
||||
|
||||
<!-- 1dp 크기의 #000000 색 테두리 -->
|
||||
<stroke
|
||||
android:width="0dp"
|
||||
android:color="#000000"/>
|
||||
|
||||
</shape>
|
BIN
app/src/main/res/drawable/transfer.png
Normal file
After Width: | Height: | Size: 11 KiB |
44
app/src/main/res/layout/activity_main.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/MainLayout"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
android:background="#0971B8"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/nav_host_fragment"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:defaultNavHost="true"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/bottom_navigation"
|
||||
app:navGraph="@navigation/nav_graph"/>
|
||||
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
android:id="@+id/bottom_navigation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="63dp"
|
||||
android:layout_gravity="bottom"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:itemIconSize="18dp"
|
||||
app:menu="@menu/bottom_navigation_menu">
|
||||
|
||||
</com.google.android.material.bottomnavigation.BottomNavigationView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
235
app/src/main/res/layout/address_search_page.xml
Normal file
@ -0,0 +1,235 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1.5">
|
||||
|
||||
<Button
|
||||
android:id="@+id/hospSearchButtonAS"
|
||||
android:layout_width="115dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="병원검색"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/textInputLayout"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardView9"
|
||||
android:layout_width="130dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="25dp"
|
||||
app:cardBackgroundColor="@color/white"
|
||||
app:cardElevation="4dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/cardView8"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/gunGuSelectText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="10dp"
|
||||
android:gravity="start|center_vertical"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:text="군구선택"
|
||||
android:textSize="16sp">
|
||||
|
||||
</TextView>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/guGunSelectSpinner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:padding="3dp"
|
||||
android:prompt="@string/gugun_spinner_prompt"
|
||||
tools:layout_editor_absoluteX="258dp"
|
||||
tools:layout_editor_absoluteY="102dp" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardView10"
|
||||
android:layout_width="130dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="25dp"
|
||||
app:cardBackgroundColor="@color/white"
|
||||
app:cardElevation="4dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/cardView9"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hospCatText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="10dp"
|
||||
android:gravity="start|center_vertical"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:text="병원분류명선택"
|
||||
android:textSize="16sp">
|
||||
|
||||
</TextView>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardView11"
|
||||
android:layout_width="160dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="25dp"
|
||||
app:cardBackgroundColor="@color/white"
|
||||
app:cardElevation="4dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/cardView10"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/prtText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="10dp"
|
||||
android:gravity="start|center_vertical"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:text="진료과목선택"
|
||||
android:textSize="16sp">
|
||||
|
||||
</TextView>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/textInputLayout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:hint="관련검색어를 입력하세요"
|
||||
android:minWidth="200dp"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintStart_toEndOf="@+id/cardView11"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/relateInput"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="200dp"
|
||||
android:textSize="14sp" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardView8"
|
||||
android:layout_width="180dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="25dp"
|
||||
app:cardBackgroundColor="@color/white"
|
||||
app:cardElevation="4dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/siSelectSpinner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="3dp"
|
||||
android:prompt="@string/si_spinner_prompt" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="7">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/reCyclerCardViewLS"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginBottom="70dp"
|
||||
app:cardCornerRadius="5dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/reCyclerViewLS"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false" />
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/reCyclerCardViewLS">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="500dp"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<Button
|
||||
android:id="@+id/pagePrevAS"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/page_button_background"
|
||||
android:text="이전"
|
||||
app:cornerRadius="10dp"></Button>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/pageButtonsContainer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="10dp"></LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/pageNextAS"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/page_button_background"
|
||||
android:text="다음"
|
||||
app:cornerRadius="10dp"></Button>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
19
app/src/main/res/layout/content_main.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_host_fragment_content_main"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:defaultNavHost="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:navGraph="@navigation/nav_graph" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
128
app/src/main/res/layout/data_row.xml
Normal file
@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cell1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="Data 1" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cell2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="Data 2" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cell3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="Data 3" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<View
|
||||
android:id="@+id/cell4_lidar_color"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="22dp"
|
||||
android:background="#FF0000"
|
||||
android:layout_marginStart="50dp"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cell4"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:paddingStart="10dp"
|
||||
android:text="Data 4" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:padding="8dp">
|
||||
<TextView
|
||||
android:id="@+id/cell5"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="Data 5" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/cell6_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:padding="8dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/cell6_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
app:cornerRadius="10dp"
|
||||
android:text="환자 정보 전송" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
34
app/src/main/res/layout/department_address.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="진료과목을 선택하세요"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
android:paddingBottom="8dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_weight="8">
|
||||
|
||||
<!-- 그룹 컨테이너 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/departGroupContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
|
||||
</LinearLayout>
|
20
app/src/main/res/layout/dialog_loading.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="20dp"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminateTint="@color/white"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="데이터 불러오는 중..."
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp"/>
|
||||
</LinearLayout>
|
122
app/src/main/res/layout/fragment_first.xml
Normal file
@ -0,0 +1,122 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_horizontal"
|
||||
android:fillViewport="true"
|
||||
tools:context=".views.LoginFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="119구급대 응급의료 스마트플랫폼"
|
||||
android:textColor="@color/white"
|
||||
android:textStyle="bold"
|
||||
android:textSize="40sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardView"
|
||||
android:layout_width="400dp"
|
||||
android:layout_height="400dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
app:cardCornerRadius="13dp"
|
||||
app:cardElevation="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvTitle">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="30dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="3"
|
||||
android:gravity="center"
|
||||
android:text="접속 정보"
|
||||
android:textColor="#0971B8"
|
||||
android:textSize="30sp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="5dp"
|
||||
android:layout_weight="2">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/loginIdText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="아이디"
|
||||
android:inputType="text"
|
||||
android:singleLine="true" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="5dp"
|
||||
android:layout_weight="2">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/carNoText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="차량번호 ( ex: 999허9999 )"
|
||||
android:inputType="text"
|
||||
android:maxLength="10"
|
||||
android:maxLines="1" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/accessButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_weight="0.5"
|
||||
android:gravity="center"
|
||||
android:text="시작"
|
||||
android:textSize="20sp"
|
||||
app:cornerRadius="10dp"
|
||||
tools:layout_editor_absoluteX="289dp"
|
||||
tools:layout_editor_absoluteY="257dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:src="@drawable/logo"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/cardView" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
73
app/src/main/res/layout/fragment_second.xml
Normal file
@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
tools:context=".views.HospitalSearchFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView6"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="응급 병원 검색"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="40sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/cardView2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardView2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="130dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:background="@color/white"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:tabGravity="start"
|
||||
app:tabMode="scrollable"
|
||||
app:tabIndicatorColor="@android:color/holo_blue_light"
|
||||
app:tabTextColor="@android:color/black"
|
||||
app:tabSelectedTextColor="@android:color/holo_blue_dark"
|
||||
android:layout_weight="8">
|
||||
|
||||
</com.google.android.material.tabs.TabLayout>
|
||||
<!-- ViewPager2 (탭 변경 시 Fragment 변경) -->
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
494
app/src/main/res/layout/fragment_transfer.xml
Normal file
@ -0,0 +1,494 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/transferScrollView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
tools:context=".views.TransferFragment">
|
||||
|
||||
<!-- TODO: Update blank fragment layout -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView7"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="응급 병원 이송"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="40sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@+id/cardView3"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardView3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="130dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardView6"
|
||||
android:layout_width="450dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:background="@color/black"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#55000000">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="1dp"
|
||||
app:cardCornerRadius="16dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView8"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="이송 병원까지의 정보"
|
||||
android:textSize="25sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.513"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="5">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLeftDistVal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:ellipsize="none"
|
||||
android:text="0.0km"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintStart_toEndOf="@+id/tvLeftDist"
|
||||
app:layout_constraintTop_toTopOf="@+id/tvLeftDist" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTFHospName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:ellipsize="none"
|
||||
android:text="-"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintStart_toEndOf="@+id/tvLeftTime3"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/tvTFLidarValue"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginStart="44dp"-->
|
||||
<!-- android:layout_marginTop="8dp"-->
|
||||
<!-- android:text="-"-->
|
||||
<!-- android:textSize="20sp"-->
|
||||
<!-- android:ellipsize="none"-->
|
||||
<!-- app:layout_constraintStart_toEndOf="@+id/tvLeftTime4"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@+id/tvTFHospName" />-->
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="43dp"
|
||||
android:gravity="start|center_vertical"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintStart_toEndOf="@+id/tvLeftTime4"
|
||||
app:layout_constraintTop_toTopOf="@+id/tvLeftTime4">
|
||||
|
||||
<View
|
||||
android:id="@+id/tvTFLidarColor"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="22dp"
|
||||
android:background="#87CEEB" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTFLidarValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:paddingStart="8dp"
|
||||
android:text="정보 없음"
|
||||
android:textSize="20sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLeftTime3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="병원 이름"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLeftTime4"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="혼잡도"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvLeftTime3" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnTFDetailInfo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="상세정보"
|
||||
android:visibility="invisible"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLeftTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="남은 시간"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvLeftTime4" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLeftTimeVal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:ellipsize="none"
|
||||
android:text="0초"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintStart_toEndOf="@+id/tvLeftTime"
|
||||
app:layout_constraintTop_toTopOf="@+id/tvLeftTime" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/infoUpdateTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:ellipsize="none"
|
||||
android:text="00:00:00"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintStart_toEndOf="@+id/tvLeftTimeVal"
|
||||
app:layout_constraintTop_toTopOf="@+id/tvLeftTimeVal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLeftDist"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="남은 거리"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvLeftTime" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tfStateLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="이송 상태"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvLeftDist" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tfState"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:text="-"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintStart_toEndOf="@+id/tfStateLabel"
|
||||
app:layout_constraintTop_toTopOf="@+id/tfStateLabel" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/transferCancel"
|
||||
android:layout_width="137dp"
|
||||
android:layout_height="77dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:text="이송취소"
|
||||
android:textSize="20sp"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#A0A0A0"
|
||||
tools:layout_editor_absoluteX="0dp"
|
||||
tools:layout_editor_absoluteY="0dp">
|
||||
|
||||
</View>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="400dp"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cvGPS_State"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="10dp"
|
||||
android:layout_weight="1"
|
||||
app:cardCornerRadius="16dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#B04169E1">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView27"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="19dp"
|
||||
android:text="00:00:00"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.95"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView23"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="19dp"
|
||||
android:text="TextView"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.133"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView18"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="GPS 상태"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.133"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.1" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cvFindPathAPI_State"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="10dp"
|
||||
android:layout_weight="1"
|
||||
app:cardCornerRadius="16dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#B04169E1">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView26"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="19dp"
|
||||
android:text="00:00:00"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.95"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView24"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="길찾기 상태"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.133"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView20"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="19dp"
|
||||
android:text="TextView"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.133"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cvServer_State"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="10dp"
|
||||
android:layout_weight="1"
|
||||
app:cardCornerRadius="16dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#B04169E1">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView25"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="서버와의 연결 상태"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.133"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView21"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="19dp"
|
||||
android:text="00:00:00"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.95"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView22"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="19dp"
|
||||
android:text="이송여부"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.09"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/transferComplete"
|
||||
android:layout_width="244dp"
|
||||
android:layout_height="129dp"
|
||||
android:layout_marginStart="168dp"
|
||||
android:text="이송완료"
|
||||
android:textSize="20sp"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/cardView6"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.061"
|
||||
android:visibility="invisible"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
34
app/src/main/res/layout/gungu_selector.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="군구를 선택하세요"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
android:paddingBottom="8dp" />
|
||||
|
||||
<!-- 기존 Spinner 대신 AutoCompleteTextView 사용 -->
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/autoCompleteTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:drawable/editbox_background"
|
||||
android:padding="10dp"
|
||||
android:dropDownHeight="200dp"
|
||||
android:visibility="invisible"/>
|
||||
<GridView
|
||||
android:id="@+id/gridViewOptions"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:numColumns="4"
|
||||
android:stretchMode="columnWidth"
|
||||
android:gravity="center">
|
||||
</GridView>
|
||||
</LinearLayout>
|
41
app/src/main/res/layout/header_row.xml
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/column1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="Header 1"
|
||||
android:background="#0971B8"
|
||||
android:textColor="@color/white"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/column2"-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_weight="1"-->
|
||||
<!-- android:gravity="center"-->
|
||||
<!-- android:padding="8dp"-->
|
||||
<!-- android:text="Header 2"-->
|
||||
<!-- android:background="#CCCCCC"-->
|
||||
<!-- android:textStyle="bold" />-->
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/column3"-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_weight="1"-->
|
||||
<!-- android:gravity="center"-->
|
||||
<!-- android:padding="8dp"-->
|
||||
<!-- android:text="Header 3"-->
|
||||
<!-- android:background="#CCCCCC"-->
|
||||
<!-- android:textStyle="bold" />-->
|
||||
</LinearLayout>
|
25
app/src/main/res/layout/hospital_category_address.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="병원분류명을 선택하세요"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
android:paddingBottom="8dp" />
|
||||
|
||||
<GridView
|
||||
android:id="@+id/gridViewOptions"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:numColumns="auto_fit"
|
||||
android:stretchMode="columnWidth"
|
||||
android:gravity="center">
|
||||
</GridView>
|
||||
</LinearLayout>
|
25
app/src/main/res/layout/hospital_category_location.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="의료기관을 선택하세요"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
android:paddingBottom="8dp" />
|
||||
|
||||
<GridView
|
||||
android:id="@+id/gridViewOptions"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center"
|
||||
android:numColumns="auto_fit"
|
||||
android:stretchMode="columnWidth"/>
|
||||
|
||||
</LinearLayout>
|
229
app/src/main/res/layout/location_search_page.xml
Normal file
@ -0,0 +1,229 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1.5">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardView7"
|
||||
android:layout_width="180dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:cardBackgroundColor="@color/white"
|
||||
app:cardElevation="4dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/gpsRefresh"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hospCatLocText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="10dp"
|
||||
android:gravity="start|center_vertical"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:text="의료기관 선택"
|
||||
android:textSize="16sp">
|
||||
|
||||
</TextView>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spMedical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:entries="@array/medical_list"
|
||||
android:padding="3dp"
|
||||
android:prompt="@string/si_spinner_prompt" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardView5"
|
||||
android:layout_width="180dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:cardBackgroundColor="@color/white"
|
||||
app:cardElevation="4dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/cardView7"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hospPrtLocText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="10dp"
|
||||
android:gravity="start|center_vertical"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:text="진료과 선택"
|
||||
android:textSize="16sp">
|
||||
|
||||
</TextView>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spDepart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:entries="@array/medical_department_list"
|
||||
android:padding="3dp"
|
||||
android:prompt="@string/si_spinner_prompt" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardView4"
|
||||
android:layout_width="230dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:cardBackgroundColor="@color/white"
|
||||
app:cardElevation="4dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/cardView5"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spEmgYN"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:entries="@array/emergency_yn_list"
|
||||
android:padding="3dp"
|
||||
android:prompt="@string/si_spinner_prompt" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<Button
|
||||
android:id="@+id/hospSearchButton"
|
||||
android:layout_width="115dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:text="병원검색"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/cardView4"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView5"
|
||||
android:layout_width="163dp"
|
||||
android:layout_height="31dp"
|
||||
android:layout_marginStart="28dp"
|
||||
android:layout_marginTop="25dp"
|
||||
android:text="단말기 현재 위치 : "
|
||||
android:textSize="20dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvGeoLocation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="31dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="25dp"
|
||||
android:text="서울특별시"
|
||||
android:textSize="20dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/textView5"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/gpsRefresh"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@null"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/gps"
|
||||
app:layout_constraintStart_toEndOf="@+id/tvGeoLocation"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="7">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/reCyclerCardViewLS"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginBottom="70dp"
|
||||
app:cardCornerRadius="5dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/reCyclerViewLS"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false" />
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/reCyclerCardViewLS">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="500dp"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<Button
|
||||
android:id="@+id/pagePrevLS"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/page_button_background"
|
||||
android:text="이전"
|
||||
app:cornerRadius="10dp"></Button>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/pageButtonsContainer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="10dp"></LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/pageNextLS"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/page_button_background"
|
||||
android:text="다음"
|
||||
app:cornerRadius="10dp"></Button>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
47
app/src/main/res/layout/popup_detail.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:background="@drawable/border_line"
|
||||
android:elevation="8dp">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginLeft="3dp"
|
||||
android:layout_marginTop="3dp"
|
||||
android:layout_marginRight="3dp"
|
||||
android:layout_marginBottom="3dp"
|
||||
android:background="@color/white"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/popupText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="병원 상세 정보"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/closePopup"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="닫기"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
122
app/src/main/res/layout/popup_search.xml
Normal file
@ -0,0 +1,122 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:background="@drawable/border_line"
|
||||
android:elevation="8dp">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:background="@color/white"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<Button
|
||||
android:id="@+id/savePopup"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="36dp"
|
||||
android:text="적용"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="75dp"
|
||||
android:background="@color/black"
|
||||
android:layout_marginStart="36dp"
|
||||
android:layout_marginEnd="36dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/popupText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="36dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:text="주소 검색 필터 항목"
|
||||
android:textSize="18sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="130dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginStart="230dp"
|
||||
android:layout_marginTop="100dp"
|
||||
app:cardBackgroundColor="@color/white"
|
||||
app:cardElevation="4dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
<Spinner
|
||||
android:id="@+id/guGunSelectSpinner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:prompt="@string/gugun_spinner_prompt"
|
||||
tools:layout_editor_absoluteX="258dp"
|
||||
tools:layout_editor_absoluteY="102dp"
|
||||
android:padding="3dp"/>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="36dp"
|
||||
android:layout_marginTop="150dp"
|
||||
android:hint="관련검색어를 입력하세요"
|
||||
android:minWidth="240dp"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/relateInput"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="200dp"
|
||||
android:textSize="16sp" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="180dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginStart="36dp"
|
||||
android:layout_marginTop="100dp"
|
||||
app:cardBackgroundColor="@color/white"
|
||||
app:cardElevation="4dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/siSelectSpinner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="3dp"
|
||||
android:prompt="@string/si_spinner_prompt" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
15
app/src/main/res/menu/bottom_navigation_menu.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/emgLogin"
|
||||
android:icon="@drawable/login"
|
||||
android:title="로그인" />
|
||||
<item
|
||||
android:id="@+id/hospSearch"
|
||||
android:icon="@drawable/search"
|
||||
android:title="병원찾기" />
|
||||
<item
|
||||
android:id="@+id/hospTransfer"
|
||||
android:icon="@drawable/transfer"
|
||||
android:title="이송중" />
|
||||
</menu>
|
10
app/src/main/res/menu/menu_main.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="com.example.smart119.MainActivity">
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:orderInCategory="100"
|
||||
android:title="@string/action_settings"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 3.0 KiB |