From 1cca066c37e9182cbe00a2d4f97f35eea88f6012 Mon Sep 17 00:00:00 2001 From: Seunggu Kang Date: Mon, 25 Nov 2024 07:39:41 +0900 Subject: [PATCH 1/2] chore: dummy files created --- .../ktlintKotlinScriptFormat.txt | 0 .../kotlin/main/META-INF/model.kotlin_module | Bin 0 -> 24 bytes .../connectdog/core/model/Announcement.class | Bin 0 -> 5464 bytes .../core/model/AnnouncementHome.class | Bin 0 -> 4690 bytes .../connectdog/core/model/Application.class | Bin 0 -> 7496 bytes .../core/model/ConnectDogResult.class | Bin 0 -> 2122 bytes .../core/model/DataUiState$Loading.class | Bin 0 -> 850 bytes .../core/model/DataUiState$Success.class | Bin 0 -> 850 bytes .../core/model/DataUiState$Yet.class | Bin 0 -> 838 bytes .../connectdog/core/model/DataUiState.class | Bin 0 -> 875 bytes .../connectdog/core/model/Example$Grade.class | Bin 0 -> 1724 bytes .../connectdog/core/model/Example.class | Bin 0 -> 4138 bytes .../core/model/InterApplication.class | Bin 0 -> 9281 bytes .../core/model/IntermediatorManage.class | Bin 0 -> 3183 bytes .../connectdog/core/model/Recent.class | Bin 0 -> 4715 bytes .../connectdog/core/model/Review.class | Bin 0 -> 8658 bytes .../connectdog/core/model/Volunteer.class | Bin 0 -> 4211 bytes .../connectdog/core/model/login/Email.class | Bin 0 -> 2436 bytes .../core/model/login/LoginResult.class | Bin 0 -> 3436 bytes .../core/model/login/NormalLogin.class | Bin 0 -> 2953 bytes .../core/model/login/SocialLogin.class | Bin 0 -> 2971 bytes .../caches-jvm/inputs/source-to-output.tab | Bin 4096 -> 4096 bytes .../inputs/source-to-output.tab.keystream | Bin 4096 -> 4096 bytes .../inputs/source-to-output.tab.keystream.len | Bin 0 -> 8 bytes .../inputs/source-to-output.tab.len} | Bin .../inputs/source-to-output.tab.values.at | Bin 0 -> 3286 bytes .../caches-jvm/inputs/source-to-output.tab_i | Bin 32768 -> 32768 bytes .../inputs/source-to-output.tab_i.len | Bin .../jvm/kotlin/class-attributes.tab | Bin 4096 -> 4096 bytes .../jvm/kotlin/class-attributes.tab.keystream | Bin 4096 -> 4096 bytes .../kotlin/class-attributes.tab.keystream.len | Bin 0 -> 8 bytes .../jvm/kotlin/class-attributes.tab.len | Bin 0 -> 8 bytes .../jvm/kotlin/class-attributes.tab.values.at | Bin 94 -> 106 bytes .../jvm/kotlin/class-attributes.tab_i | Bin 32768 -> 32768 bytes .../jvm/kotlin/class-attributes.tab_i.len | Bin .../jvm/kotlin/class-fq-name-to-source.tab | Bin 4096 -> 4096 bytes .../class-fq-name-to-source.tab.keystream | Bin 4096 -> 4096 bytes .../class-fq-name-to-source.tab.keystream.len | Bin 0 -> 8 bytes .../kotlin/class-fq-name-to-source.tab.len | Bin 0 -> 8 bytes .../class-fq-name-to-source.tab.values.at | Bin 1403 -> 1781 bytes .../jvm/kotlin/class-fq-name-to-source.tab_i | Bin 32768 -> 32768 bytes .../kotlin/class-fq-name-to-source.tab_i.len | Bin .../jvm/kotlin/internal-name-to-source.tab | Bin 4096 -> 4096 bytes .../internal-name-to-source.tab.keystream | Bin 4096 -> 4096 bytes .../internal-name-to-source.tab.keystream.len | Bin 0 -> 8 bytes .../kotlin/internal-name-to-source.tab.len | Bin 0 -> 8 bytes .../internal-name-to-source.tab.values.at | Bin 1403 -> 1781 bytes .../jvm/kotlin/internal-name-to-source.tab_i | Bin 32768 -> 32768 bytes .../kotlin/internal-name-to-source.tab_i.len | Bin .../cacheable/caches-jvm/jvm/kotlin/proto.tab | Bin 4096 -> 4096 bytes .../caches-jvm/jvm/kotlin/proto.tab.keystream | Bin 4096 -> 4096 bytes .../jvm/kotlin/proto.tab.keystream.len | Bin 0 -> 8 bytes .../caches-jvm/jvm/kotlin/proto.tab.len | Bin 0 -> 8 bytes .../caches-jvm/jvm/kotlin/proto.tab.values.at | Bin 12127 -> 13849 bytes .../caches-jvm/jvm/kotlin/proto.tab_i | Bin 32768 -> 32768 bytes .../caches-jvm/jvm/kotlin/proto.tab_i.len | Bin .../jvm/kotlin/source-to-classes.tab | Bin 4096 -> 4096 bytes .../kotlin/source-to-classes.tab.keystream | Bin 4096 -> 4096 bytes .../source-to-classes.tab.keystream.len | Bin 0 -> 8 bytes .../jvm/kotlin/source-to-classes.tab.len} | Bin .../kotlin/source-to-classes.tab.values.at | Bin 957 -> 1227 bytes .../jvm/kotlin/source-to-classes.tab_i | Bin 32768 -> 32768 bytes .../jvm/kotlin/source-to-classes.tab_i.len | Bin .../caches-jvm/jvm/kotlin/subtypes.tab | Bin .../jvm/kotlin/subtypes.tab.keystream | Bin .../jvm/kotlin/subtypes.tab.keystream.len | Bin .../caches-jvm/jvm/kotlin/subtypes.tab.len | Bin .../jvm/kotlin/subtypes.tab.values.at | Bin .../caches-jvm/jvm/kotlin/subtypes.tab_i | Bin .../caches-jvm/jvm/kotlin/subtypes.tab_i.len | Bin .../caches-jvm/jvm/kotlin/supertypes.tab | Bin 4096 -> 4096 bytes .../jvm/kotlin/supertypes.tab.keystream | Bin .../jvm/kotlin/supertypes.tab.keystream.len | Bin .../caches-jvm/jvm/kotlin/supertypes.tab.len | Bin .../jvm/kotlin/supertypes.tab.values.at | Bin .../caches-jvm/jvm/kotlin/supertypes.tab_i | Bin .../jvm/kotlin/supertypes.tab_i.len | Bin .../cacheable/caches-jvm/lookups/counters.tab | 2 ++ .../caches-jvm/lookups/file-to-id.tab | Bin 4096 -> 4096 bytes .../lookups/file-to-id.tab.keystream | Bin 4096 -> 4096 bytes .../lookups/file-to-id.tab.keystream.len | Bin 0 -> 8 bytes .../caches-jvm/lookups/file-to-id.tab.len} | Bin .../lookups/file-to-id.tab.values.at | Bin 115 -> 139 bytes .../caches-jvm/lookups/file-to-id.tab_i | Bin 32768 -> 32768 bytes .../caches-jvm/lookups/file-to-id.tab_i.len | Bin .../caches-jvm/lookups/id-to-file.tab | Bin 4096 -> 4096 bytes .../lookups/id-to-file.tab.keystream | Bin 4096 -> 4096 bytes .../lookups/id-to-file.tab.keystream.len | Bin 0 -> 8 bytes .../caches-jvm/lookups/id-to-file.tab.len | Bin 0 -> 8 bytes .../lookups/id-to-file.tab.values.at | Bin 1047 -> 1425 bytes .../caches-jvm/lookups/id-to-file.tab_i | Bin 32768 -> 32768 bytes .../caches-jvm/lookups/id-to-file.tab_i.len | Bin .../cacheable/caches-jvm/lookups/lookups.tab | Bin 4096 -> 4096 bytes .../caches-jvm/lookups/lookups.tab.keystream | Bin 4096 -> 4096 bytes .../lookups/lookups.tab.keystream.len | Bin 0 -> 8 bytes .../caches-jvm/lookups/lookups.tab.len | Bin 0 -> 8 bytes .../caches-jvm/lookups/lookups.tab.values.at | Bin 481 -> 563 bytes .../caches-jvm/lookups/lookups.tab_i | Bin 32768 -> 32768 bytes .../caches-jvm/lookups/lookups.tab_i.len | Bin .../compileKotlin/cacheable/last-build.bin | Bin 0 -> 18 bytes .../local-state/build-history.bin | Bin 0 -> 31 bytes .../inputs/source-to-output.tab.keystream.len | Bin 8 -> 0 bytes .../inputs/source-to-output.tab.len | Bin 8 -> 0 bytes .../inputs/source-to-output.tab.values.at | Bin 2807 -> 0 bytes .../kotlin/class-attributes.tab.keystream.len | Bin 8 -> 0 bytes .../class-fq-name-to-source.tab.keystream.len | Bin 8 -> 0 bytes .../internal-name-to-source.tab.keystream.len | Bin 8 -> 0 bytes .../jvm/kotlin/proto.tab.keystream.len | Bin 8 -> 0 bytes .../caches-jvm/jvm/kotlin/proto.tab.len | Bin 8 -> 0 bytes .../source-to-classes.tab.keystream.len | Bin 8 -> 0 bytes .../jvm/kotlin/source-to-classes.tab.len | Bin 8 -> 0 bytes .../cacheable/caches-jvm/lookups/counters.tab | 2 -- .../lookups/file-to-id.tab.keystream.len | Bin 8 -> 0 bytes .../caches-jvm/lookups/file-to-id.tab.len | Bin 8 -> 0 bytes .../lookups/id-to-file.tab.keystream.len | Bin 8 -> 0 bytes .../caches-jvm/lookups/id-to-file.tab.len | Bin 8 -> 0 bytes .../lookups/lookups.tab.keystream.len | Bin 8 -> 0 bytes .../caches-jvm/lookups/lookups.tab.len | Bin 8 -> 0 bytes .../cacheable/last-build.bin | Bin 18 -> 0 bytes .../local-state/build-history.bin | Bin 31 -> 0 bytes core/model/build/kotlin/modeljar-classes.txt | 1 + core/model/build/libs/model.jar | Bin 0 -> 33239 bytes .../ktlintKotlinScriptFormat.txt | 0 .../ktlintMainSourceSetFormat.txt | 0 124 files changed, 3 insertions(+), 2 deletions(-) delete mode 100644 core/designsystem/build/reports/ktlint/ktlintKotlinScriptFormat/ktlintKotlinScriptFormat.txt create mode 100644 core/model/build/classes/kotlin/main/META-INF/model.kotlin_module create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Announcement.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Application.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/ConnectDogResult.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Loading.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Success.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Yet.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example$Grade.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/InterApplication.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/IntermediatorManage.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Recent.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Review.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Volunteer.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/Email.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/LoginResult.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/NormalLogin.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/SocialLogin.class rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/inputs/source-to-output.tab (93%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/inputs/source-to-output.tab.keystream (65%) create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len rename core/model/build/kotlin/{compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len => compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len} (100%) create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/inputs/source-to-output.tab_i (97%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/inputs/source-to-output.tab_i.len (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab (93%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream (93%) create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at (60%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i (99%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab (93%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream (93%) create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at (75%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i (99%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab (93%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream (93%) create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at (75%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i (99%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/proto.tab (92%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream (93%) create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at (80%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/proto.tab_i (98%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab (95%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream (89%) create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len rename core/model/build/kotlin/{compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len => compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len} (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at (73%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i (99%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/subtypes.tab (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/supertypes.tab (98%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len (100%) create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/counters.tab rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/file-to-id.tab (95%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/file-to-id.tab.keystream (89%) create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len rename core/model/build/kotlin/{compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len => compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len} (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/file-to-id.tab.values.at (82%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/file-to-id.tab_i (99%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/file-to-id.tab_i.len (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/id-to-file.tab (93%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/id-to-file.tab.keystream (98%) create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/id-to-file.tab.values.at (71%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/id-to-file.tab_i (99%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/id-to-file.tab_i.len (100%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/lookups.tab (92%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/lookups.tab.keystream (93%) create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.len rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/lookups.tab.values.at (65%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/lookups.tab_i (93%) rename core/model/build/kotlin/{compileReleaseKotlin => compileKotlin}/cacheable/caches-jvm/lookups/lookups.tab_i.len (100%) create mode 100644 core/model/build/kotlin/compileKotlin/cacheable/last-build.bin create mode 100644 core/model/build/kotlin/compileKotlin/local-state/build-history.bin delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/counters.tab delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.len delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/cacheable/last-build.bin delete mode 100644 core/model/build/kotlin/compileReleaseKotlin/local-state/build-history.bin create mode 100644 core/model/build/kotlin/modeljar-classes.txt create mode 100644 core/model/build/libs/model.jar delete mode 100644 core/model/build/reports/ktlint/ktlintKotlinScriptFormat/ktlintKotlinScriptFormat.txt delete mode 100644 core/model/build/reports/ktlint/ktlintMainSourceSetFormat/ktlintMainSourceSetFormat.txt diff --git a/core/designsystem/build/reports/ktlint/ktlintKotlinScriptFormat/ktlintKotlinScriptFormat.txt b/core/designsystem/build/reports/ktlint/ktlintKotlinScriptFormat/ktlintKotlinScriptFormat.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/core/model/build/classes/kotlin/main/META-INF/model.kotlin_module b/core/model/build/classes/kotlin/main/META-INF/model.kotlin_module new file mode 100644 index 0000000000000000000000000000000000000000..3aa63618ce3a770e72020d4f312e3de7744d8bea GIT binary patch literal 24 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 literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Application.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Application.class new file mode 100644 index 0000000000000000000000000000000000000000..a5e7b3fb5938f4c68ec60f4455c971e625fced6e GIT binary patch literal 7496 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 AkN^Mx literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/ConnectDogResult.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/ConnectDogResult.class new file mode 100644 index 0000000000000000000000000000000000000000..ac0caf2af68c21cfec08e9d5b349d5914d913287 GIT binary patch literal 2122 zcmbVN-%}e^6#nk+CfRHPY(i-%Y3mPSO+qC=t5ueAw_(Una#cDoIT%ne%y06fByaKcL2BW z5yM2yYnB`Bz!uG*T=QJls)@R{NuqC+n_k^=%Cn*MuD7{t1#L$pz!=PJzQfB7cQ?x) zZ)_7N0hJ*>WxKYx&7c+5imME2p}3kx3<(1obcUoIth8%2D+n0aS{epYNhnAYKy2A$ zyixuC`Al}=tT7mbZF#Qcig6;Wd97WBo0Q1eIESmAzggb4#D>ppHz;%0^#m8TNAi*< zmfDUpDQk-xRKWm4S_aJ5tF);j7T-TVJ%f zLq!gB7x^MKO()g%-}6Mn#5Wv^jw0rXEz4)fcEyia7&6s{Cmh=?Q`dN%3r+x~xua4} zOfI@yKzFM__AhOzjgeHR`|#tz-W5X`R1C#D*fZ!+%#@+%3EK5g?WIjWe54N^>`f?R zY^En0Hv_Uq;=AVD1 z63`%PieyG|n&ciSFK3SEWd=hUQN<2_i1*5jCzz}w*7*W4^q-v1(FR>HE$n|^)po6= zc5}n>@5v_0-g!0dta9I$dSuKkw_Ra3t%|#22R7O79A9XLo)y7sjYZyyyz?i$KjA)a zTEg;Qf*C7b+pk%3whVhQ!mOUcZ_aq02!zjD;lKwNr^~5zPAeZ;_zlF0BgvtA9xQr(_+YVH#hDTERpG*DJVzw@Ji172L$T>tF%i!~5*<8y i!04>;0A_$pfNX$~0HXnl9eb{`PSIF~gZc(VxbhGDJl-Vfs`wgYYeZNJ?)JZQI`x>$z0K*buv zMv&zLZzy#?7b-10k)|14R%H~oGuXqRuZ$Ck}c-&c8!pMIzkdpz1@@aDTO4N{pZ z#bC|!VOaV{wRNwKYL!Soov1?fV|noRn#6RAq-IzSR4Uu!q%ZSBL3~uquT;kfBR4yF7)q@jFox<#OoShaWaz)>k7&+8f#L34fDTFw<$aYX z^N69)*y>i`!1YkX0z=WfQJP_|H5caZLq1?|_rqw4?SWfBH)wYb58BPA6)dB&K*cJ< zMk~#R{z#gBCRCz*kt8WyR;3iTQ`63)h@e(l3x%NF&%9C|TW1F7YOl8JM{#F1zxF zxN<8l3JOx{&L1UyHx?CKWrllRbIy0q`Of_K`Q;mcC)g0Ehsnqvjx%FNnI9%`tV7#N z`ZQDRkCL8_{O8K5H)hW&tJe;+EkOt@4Ai0WBNg}kSKR??O2`S^p9-vmf1-$Jrn&6fp9heui_V#yLjTaTnqcX$bg1~As zN&Egl+it2%ocSt_6Aoz-+O5R4#!*D5#pW=v1oL;bRXtL{m>eDENT6`Sa{>Zl$oM8CZEej;$H#AU-si=|+0z?}%i$!SxEvH%+Wt<55?q`-(XNOU)!yQCp?P z`DejOz<(ocL@LWP_fpIVC`OJCw9)~O#cex86AI>-gM7~oQXWmIXR7T_{gIuIGI;A#i?43!MmGI$xT{{pI@ B!Q%h` literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState.class new file mode 100644 index 0000000000000000000000000000000000000000..72eeb88aca464962af06f2a366168c35ade3abd9 GIT binary patch literal 875 zcmb7CO>fgc5PjoKV%LZsz)obm{?0DbIo7wsO=llY|d+ZVRGg~IJ%4uJ^B(uh-%;$E>=3FJE z%~g?nl3sq-BQL!QL4@v!T*#!5W}1ANobde+g7B(QpuM4$xi-@f?Z(him1WAg5Fz2P zS=OJ5$!-v~hcoL7ZIaK*%be?bM+nM=;I2?DqFR7JGxneA`gFinen@z;S`Ol%7sNq# zwTy#ETpwx&@6|F|^j6EG;DFwWK(sE;NVGfQ<*!au&3J)`cSU zzg5QTQvJ|QPYU(H7|V00t>KG1U)8+S-m836O|olvhr5hc{dl}uc*=4Bfew3n=p$m? z=PzbGVEv5$2Y7<#tdF_RH_*oB7$U{Z6k927q01(=Q{2YR802sVcgNUpxaV-+q36(d W7&ts|c)RE*& z*=5BKVa0+4q(D1#U_4p!qZrP;HXTE|Ak~cTJxBAM_jlw!|N89@0H5LuhH^XXm5=(d zm-J$igTQSkov=${;3aDemy2UD8cE~@-KuSunha`DUb8O)l$s{e$QVe$V9*~%UKn}F zHw?@+Vd6pt9FycC`Pz#amd~9wgHdp);6mW^T!!3>IWk-rBEqQS1&+@!(RGu(=ZPrA zl1*hEJAU7#6mAqttyjoGD>OIi4{8mDmGhgMm`7f8;x&eu)>sL<2ZuEMs)j2JskR>m zRN}>A=|zNzt9Zk}>v&T`owEQ$eS7D@wuwbdi~8RqCT#82@0eH`z9&<9ZM!G%n9W~hUxlIm=L(U?IupgNgU!d?;R_&T1*_eI6&MxqW6zHp;bugEHktQ zCpm-9af4^G#^8i5-Qap!Kl_%=4Ng|{oSNg6!AXVPp3-?Po#lC6QO>?g^Q?M*`njf) zXGuxYXx};T9mG8WQ8|+Oo}u^Z4=T(ipZrTVk_7tnL{V!CCm~= zL@JBf(w(w?#?%iI@ZS*T5HJdn!DY;ijD-{N7^hhH6>kl2?MJC+h{JD>FhvR}P)3eh zPf;9z3k;LV4?P#&8-Xh_3WDcGg= z95(jow#o8i3iU|~ijAs`Rh#~P)=0!H8|&C;fyKCu%@&Lp(=qPEFy*PmxD;bH#$t@6 H7`49vIYxN* literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example.class new file mode 100644 index 0000000000000000000000000000000000000000..19ad1b7dfd58b7437899142bc38aefbae4364d62 GIT binary patch literal 4138 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 G&i?={9K{R( literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Review.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Review.class new file mode 100644 index 0000000000000000000000000000000000000000..fa56387a051311975ef75d34764317facfcd5b51 GIT binary patch literal 8658 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 literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Volunteer.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Volunteer.class new file mode 100644 index 0000000000000000000000000000000000000000..11135f888687641fd2d9442cda55654fc29a0c59 GIT binary patch literal 4211 zcmbtW-BTOa760AU$1Xy^A_L|lm|#OKB(N}cJ_xqk*okXVL0sdKCe&>fX^j?1yF|NU z?3a#Tn!livY4Vmnbo$`Tv@<2~q%$4IdCT9_>GXGZ7ij^tj1z|4d(P20=brPs=bXFW z|L2>30l1ERfqdC%6lyKk@)~ZT?AW$h_A1T}$);IoI2E&A*mUYG+cV9k3L&8H8v90} zZrD48_qKPbts*9nyk^;!cSE3*Ep-$&yryOEto$&^>fENlg_6_UDeRiwcGIwIw_w<| z;~AdikY0DZ^;W&UBG9*g7~;CoFg0ib=W32ux9r01exqP9`lfBv3q@N7}v=u4p&{Q`--s$+9&U7)wzG!4(Jyu+7WwHYOByV++6-Y@zkSrk~Q)GP1 zc$Ggfo;_OG-sLE>6lJbNnX6IeH6~Ve_8tp7iXP67EU=ftNFG`;MUYV*XXX&Lt74 za-R*3U6NMix|q{&U0|j&3oLuzshNdf3)V>4@NOGr&uKnZ@l%1b4WniT;`c4DO3L*N z+hZmFDSF_cmo?L?I+Z(yU8$SyOv!O-t-UTS8iD7C;r+*ZW*7CXh<+Q+6B*nx>h%rF zGgs1h8#hz<8Ey?E@s7ZQXrMo~GCSLbp5$(~GaTDL=TTJ+mk?Fhf^4qhk)a%@tN2A4 zMXaV!!WtX3F=>9>GU|kXIGWWVDj)J_ z|KDWhST?rnCg+M~G|hLVt5e5n+jklt;6pi9w>U!_uPR4!bV`Pb0)wS+$g>=bis2dD zPigGO2$GO5O}@YZS)=@sCAmdXmCHgrdHy7qQbv`OqCbC<;=iKzrxY#DwTJ5f*Iusj zcTKL^i%+!C=TDZDMR9W>lhl=QWiiGz9bH+J)@tc`RJ0SkB!Gi#iF?L z-KR2$aY`ph3(~KUW^kX1dxN^~gJElgWIV2=^j-@6Ejq%qFFZ^z)a=vysp*H+(H!tK zeW*G@UGIJI*W{!;2hM(;PQw4n;7n}~ol7;&)QNli=&%}Q(cZUQi^cSI=jvzi2Gu`M zvTSp`)z~(h_hrG!LUGDQebZ=Kk`IM5$9=Ug`y)>KHaw$TTQl}Tv($#uYL?C0mUKK8 z`q=CejegT{JlAU)d%<9GahWqU&U#Dm+U8}>G#liSTve_ad99z2@q#}g<5hn`#=D+A zbjo=laUYx9mx%eEm-CsPXBe2z4D!8@Im7o@JTuHC_ccay`2$Sk<_|ELTR6Z}ZY+L) z>D)--0JDFm69o?6=jdpR?k1VQd2Vr$o6J+T#6;ete2+ReCaT{sR{H{(J1 zdBhTy2tQ(p%WBR3&kp-1ln?Ur3uEz-#MgL3o@U@PXqIfdS+ebB$+nv%D?ji3X34gj zB^x$N6#3H{NAF>eE^}iUvdMsZxR!?1`0qc1Ci{nUBBUqRhE+ABr`Cs6T_e*&rRlfg z5|XvH@E|Ia0!}r zyi3yx`RNiS@sOy{}#&UNW`AzpF>%bfz0!HhTr%?84UT! z2tP%BD#A~bpN{ae9CsG-GB LG=}mnpBw)LYjJ3k literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/Email.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/Email.class new file mode 100644 index 0000000000000000000000000000000000000000..6fff8624496fa8d4cf10d0f65f8da0c0274b0e96 GIT binary patch literal 2436 zcmb7G-BTPz5dY2YeJsntEd=B%MhyrDmt+Aoevm{1f*c+s0%9o-)^In%a(laYJ4eZj z#f$k9QtG1*mJd9{Dos+c%0lwy-(*?#>~4-DP^PH5-R|k_{&n|nrl;=jf1msb;3n1> zu9p0&U8x6-tOj<;_dHROWq*^@ny{;WS-7_AZ#temTjh?M24k?c`7XCz?rqw4Hnzz> z4V@u%!|@z>i=jJLJa$--HOJeW8l_BwMZdObZwt9mrOEw zh00^VV7OHArAwK&cdNGJNm28-YZp9)7&xUM4U>|UwnV8Chu`HjUKQlXFw$H^ROQrJ zWo3{-n~7GmGw8X|wG5K5OeE03(0Mu_0|OUYprMN)A-9}>!7iSQL2A+16f$I!p({6f zIthbGkUPF7JUKymO8(9s!%TBW&uBeoZq;4Nr1D>8$SByMviOSEUCHoW?wnYs>n=2z zV#-I)37WwGE~)}wBbuZiwaL&P(v=I3#!WVAV2EMp_>ei?u3r&$>^s=Oj1^Jk9SA}x^IleBl=H**@JEDE{hm*=@xc118$^!-YG=ZvG%)a!}B)x8~Y zhWmPxe}kJ-9n5goU2&wC${>eP6C)VQrjTbCZZ5R3`N#3GNrheQq|v@c^lkBgdM%6a zU>8n|ZRDQDWCr7yF!2W7qyZLR*SSlqoEYF|#ePAI|K9-9^zsc?sN>CRVpc)Da0(mP z8N7@4)D)@eMn*FGIb+z$#?_#!;(r(#kYO z2Z#HYO|4fmHS2KSq@QNBo0^d#*-BE`4JD1Edq(f!{-id}rrSDGme#M0>qkGOG%K;t zVx`q;{^>n^;eut5PL775MNVX9WNsm|IcZp}{fS;S&gP%q*C{YV);7`^>Fp87eYV`u zfH$b5{)CaVQb)g}va04uraDQ6cQCOUj=;4Fjq1R1-IGpL6uez0aESEV$2Tcm7tx+) zi;gFj>eUTVTU8sQ2=z++Aqx)B~X}Cl0cIf1-LtWWfl6T4WQWQh7hgK9F=lO*6G@XqwQ3ra_M~*6uO*SGM z$+6$i{eYARTh#=@RhXH`A;xU3xC8wSpuy*X*b9T{zN4~L6>pPN&1R!!|A6*+{t+&z zdLo#puWX~Q>>2zu_h_}?6}(Ep3VoQc7401t6W{&-Lv>ml%Rj{B2!EMA>0qtoJ=ka` z7q??7?UGP4!wZe1xyz(gAYl?Yyorlh#UgUqp%JuKu>^$07m#u1?UaX f7ob1DK!EF^@n(SWP#FyHF+QaP>U>|J=k@;pcwQ`{ literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/LoginResult.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/LoginResult.class new file mode 100644 index 0000000000000000000000000000000000000000..292f57aad9ae869a40474a6a3924e9a4e92443a1 GIT binary patch literal 3436 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 D%T$t( literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/SocialLogin.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/SocialLogin.class new file mode 100644 index 0000000000000000000000000000000000000000..7c1696357842e36f9a0a9374e17ff983888f8f30 GIT binary patch literal 2971 zcmbVOTW=dh6#iy?+c-|LahrS7q-|*93w4^(3nVSHr6n#-TAGm31`w0=l5D)*H9PBw zzMww!Cse>ANQj3%fJ84U5(@1be}X@P5NEs_XB!)WB6;_mIeX?i*E!=q{(k-&fD8DP z;k52l3zfPsy{ahaj%^#dS9aEjb&W#RDH~S7a@I_{u;}O}w@Q*vfH7zre3KU}Zm$(? ztZvY*1R@OaS<^PXiwq|wOFIgSo@?4`Gp&-$GQ+Ww$)Mtl2b8k6)MBwisM=2*T!bGVA`JH+T1D>ZD~oEx=0|&(5J5(dL;n4 z$z5JGNO6~QzV~gNOCg1>Bs$T}pw?Vx(<~dV3XLH$nORODhIA599AHSd#+HJLz78np zPeJp!L58TeZVHAorG4a`($KwTc$aoE!EkUg(`uU1MS3>_hZ&M&tmfE;?VSoQrpX=M zsoi5(`G3{gm(wy$@g(Kp7(+^$nMJ4r zX69NVxWX-K(e#X&6i%X$#Os*qiG$kfeAv-{KlmXdfszC|ou;|;1|@o(3yQvMG)`La zm1*OvCvZN6vpAQ;n|O=nj%$cUOEFT88(-A9MM>)m`?4L&T`I_bjU1XceAP1Ou&LZN zu1csqCq@%Hg-f_BC&m?qnB%R>X%n6efg(e1DVSeWL|*0|CwoeDGeYq*`BLQz46H)( zFHO0cBCbps{&Va8(WEk{Bo%Gzev*EQ)}2(;4x*hzrCgO%eepmY+`2!lOtH&->A0p0 zD^n4oQAuBX7gw~{^$x8=uI64oh!CG_@}pWO@w8c06@O!cYiuQDcKv{sB89GLRqGy( z4zejW_wu2H=pm^_JR`o>hkM9w_4*iOR3(RpqiS4BkZ{|RK&Wbo7eB_+GE5px6nw04 z0nyY89k!Dd8XP0H>b7TAjiSA23X`gJY3I_Qq2_l^Psy~6g?e?>aF=97WhES)Tg%)v z79LwgW23;3}o|< zG4wNiR&cuk7o}S)LZDHCjbWJhk4Qf5L(qDJRs)VC&K{Qk~UJlLSQ2tWG@c41sd876x$PMtO;~%w?}Nx&Esu1H@w(; zGhGanL|KtJ3RqU8KU|Stq1?&kpJGDBq4jrO{Zx4$WtC`6rn4ZQmueD3ngwN10~Gc`BJKR=3T*FMIjW4Fz^I3vm@Hrxw`CN2M_ZGTKf=6Y5_$ zn1IsL=mKe-aGR+=hpV_oe#j&zWGBBvOav?RRvM=6CbSLfWU~rEdjOh)&$}LhXh6i4hxJ4j0+qQxY+o5Rp4xc$p|ds6SAa| JrD=L{{{SU=nP~t3 literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab similarity index 93% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab index 2b9d162189ffcf79d690b83575a11cd0daa5342b..b3ee9da30bce849bc8cd2f1fcf590264891270b5 100644 GIT binary patch literal 4096 zcmeH@DGmZb5Jihc5|*HGSdg4zf<~f{a0C!IZUBxGpfDs{Uet;>sdT?Zuqhj(;uas(WD^q;CK&D}-IL?lr4LtY{0`}RU(e#6^LuOvKfszS zk#!E~zJUQbe*s(a_ylTsvlclbhYw&!u415BFpDB!N_NNtIlcq!qFMh2%*f>xIFqMK g@}I0XsU`z5AOkWW12P~3G9UvoAOkWW1OH^;3xTpj761SM delta 152 zcmZorXi(6d?X#PY0SLH31Plm37&m}a0}%fQ0+0yzL|tiCkV4UkzSaT3Kn62VW;Kw$ z`se?DMn(n(b|4)Jq)-3)|9=yZ{`T|#e{LoQ22~)P0i*+d{QrLdNH=`{|6hTbfnmkB X|Nm=&^yRPr|8Hhw{LeR8fKd|wL`5_# diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream similarity index 65% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream index 39a98da471a0fb9e0524d87417d3103b5d678e57..cad3c73a06bc24fb11aad87b27fafb5e1e1ee087 100644 GIT binary patch delta 142 zcmZorXi#7bpUCJraV{TYERYt>$xqMB)As?9L8-;1IVF18B{4vW$@3Y7C(NCk&zuNW zCkRm&oS&STm;+WlS(Z6rVz3uCM8Y*UF*9fKUZ!NmP>|_gS4|FO5=PePmtT|%)4858 KX7feneOv&Ku`)6M delta 76 zcmZorXi#7bn#kxmIhHYaq8H!f7UnOL7=;-lfI^cPd06zaOJYE>6)eINye4m8YEix>fRf)`!@ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len new file mode 100644 index 0000000000000000000000000000000000000000..1e061838fa6f03a369ee91f44cd453a5241ede2b GIT binary patch literal 8 McmZQz00CAf002|~NB{r; literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at new file mode 100644 index 0000000000000000000000000000000000000000..012c7cfd33fd93b8a41158d4f3aa6650b6cc6c30 GIT binary patch literal 3286 zcmcguyG{c!5OhJoXQa56_#2`;NKjt73z4Xzjc>V__;KdhYmZy^9zfPX2eNgea*}pI#VV~wd@um^X8RL$w zL0UsYoUYi95}#-|(@tk$g#@*qQ5yPG(>XE$9l2nrl-^ilKYgW&rtDvg<`3MLU1KRB z#fJ%)lptsx@XAUOUtC%hlXTG0(Ehn#YZBi5XVA4e6njGnkzKo#AZf}&YHk?7_)DACB~7Z+HkyZ`_I literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i similarity index 97% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i index cbc49165b6381e5b593f335b60c4e7b56924a42b..ff098fe18ad98c7bc2348c953509859fe0b98609 100644 GIT binary patch delta 178 zcmV;j08RgZfC7Mk0t5gL00WVcgb3IG0048oQ?{{@cm$KMJ_H1PVV2XekvIdB&@%)C zsf-Y$v60XO0jRSf4POfgzyJUM=R@-=v61)zlOPQQvxFK<83DMn(KFu)0f4iyKF@>tv5~k12$%o> g02Z?x;j@t%fDi%TvypEf5R;H^1O#Vl3G9&(NPfdWqyPW_ delta 142 zcmV;90CE3-fC7Mk0t5gH00WVcgb0`b0048oQ?|1)4Y&uBfEWY>sf-Y$voQ_O1e1Uo z1hXU!TnnL~0+WD81ha%1Oc?>lv(Yo(3IT|-u|CfT0id&iM=u1kKn+L=lOPQQ1S;X& wgt3uG1C!7*1O&|m7NfH<4Y&o9us#F?7PB1TvymEr5R;QZuFsOaX4Oldp-^xYuE delta 16 YcmZorXi(U2fobzX=6IgT8<;Nw05;_YoB#j- diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len new file mode 100644 index 0000000000000000000000000000000000000000..421525b5d9b1302d83121b159494b8f321d5d88e GIT binary patch literal 8 McmZQz00HJ%005`}o&W#< literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len new file mode 100644 index 0000000000000000000000000000000000000000..14f7c061cc4bef2fdb72d8ebd5cc8c9a23a22d1b GIT binary patch literal 8 McmZQz00Bk`001HY8UO$Q literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at similarity index 60% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at index ac65f4acd1592d901683ff183db9037362bd187c..89c186bebfb03550c6eaeea910c81f10a4cff4cc 100644 GIT binary patch delta 7 Ocma#cnh-b9p9cU7x&osB delta 4 Lcmd0bn-B*81VjP1 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i similarity index 99% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i index 7838bdec63e3ec4c0ed0473fe9f1c61fa873644c..1890187df33fca8e50484092edddc4a226872e22 100644 GIT binary patch delta 81 zcmZo@U}|V!Vqp+wVBWlu--c_m1J?>3jvovR4F8rq_1`Gy$imLZz;NP6S=B~C1!fKo kAZJMvgWN;QZuFsOaX4Oldp-^xYuE delta 16 YcmZorXi(U2fobzX=6IgT8<;Nw05;_YoB#j- diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len new file mode 100644 index 0000000000000000000000000000000000000000..421525b5d9b1302d83121b159494b8f321d5d88e GIT binary patch literal 8 McmZQz00HJ%005`}o&W#< literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len new file mode 100644 index 0000000000000000000000000000000000000000..14f7c061cc4bef2fdb72d8ebd5cc8c9a23a22d1b GIT binary patch literal 8 McmZQz00Bk`001HY8UO$Q literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at similarity index 75% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at index 5cf06f95712c3cd657152de296d3361cb50dfbe3..c9bd96945281e0959847b515895d9e760e458a44 100644 GIT binary patch delta 110 zcmey(^_6!+HS6Rhj6Q-n`RSQ?`mVW&nK^pdC23jvovR4F8rq_1`Gy$imLZz;NP6S=B~C1!fKo kAZJMvgWN;QZuFsOaX4Oldp-^`9Wg delta 16 YcmZorXi(U2fobzX=6IgT8<;Nw05;_YoB#j- diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len new file mode 100644 index 0000000000000000000000000000000000000000..421525b5d9b1302d83121b159494b8f321d5d88e GIT binary patch literal 8 McmZQz00HJ%005`}o&W#< literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len new file mode 100644 index 0000000000000000000000000000000000000000..14f7c061cc4bef2fdb72d8ebd5cc8c9a23a22d1b GIT binary patch literal 8 McmZQz00Bk`001HY8UO$Q literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at similarity index 75% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at index 5cf06f95712c3cd657152de296d3361cb50dfbe3..c9bd96945281e0959847b515895d9e760e458a44 100644 GIT binary patch delta 110 zcmey(^_6!+HS6Rhj6Q-n`RSQ?`mVW&nK^pdC22)eY7vLVhQOswXp8V4I7LgVgS&G}|G-)ru9MIoa7-7$txKukuHZ0a070@4Y&a};0D}) P8*l?|zzw*8e{En7>ql0^ literal 4096 zcmeH@tqKA`6h=pzMSOs5X7NQ#+iYSq2xf~ufp)9S7f_5FY_ez+#3HhSKidSu@tf5R z79T+F2eaqyy~7N1CXHp;DHZ?8lm8T)8>olkM|s=V8fDAZK7Llqs_*`%^%HBIU)PS! z6WZeN0b}u$LL|=akc!|k_00000 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream similarity index 93% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream index 5723d61ce51587cb8df8fd3b85f210e65a6f1f71..9eb21618efce78375b4e02ebb9d60502efd8a993 100644 GIT binary patch delta 95 zcmZorXi(U2fr(LfBBK&dPJVi3p1x~tVrGspkS_$``+!7)Qj1G-N{~eT@{4j4bHH*S TQ9+2>;QZuFsOaVkOldp-^_w8b delta 16 YcmZorXi(U2fobzB<}{wk2bfO*05<>zr2qf` diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len new file mode 100644 index 0000000000000000000000000000000000000000..087214bedab255e8874b48dbfad13af4192beaab GIT binary patch literal 8 McmZQz00HKe006fDtpET3 literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len new file mode 100644 index 0000000000000000000000000000000000000000..8fe89d82d540f0f9c8b866f249f77e7623cde7a1 GIT binary patch literal 8 McmZQz00Bk?001fgA^-pY literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at similarity index 80% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at index a5a4ee1d7636cb19d00448c4896fc3466db56ebb..94c3219d394d50ec46d6389e0ccfbb1aac662f52 100644 GIT binary patch delta 1282 zcmdUv&rcIU6vt<`?d)`0cBhMlwuo53@I#@6L?gjyFfmp_2m$q`$qH+&Y`bI&c=QkO zpk@xn1QX!I$;9lA5mgeXTh=?Y(1a#u15z#Vb^=CJi)=}ftS^Wq#*g>-O`7{;T&QN#P$ zdsPWWzIml{U*)`5;$sZ)XRTY6GqNgEq#}50s!T9@o6oTuTI!yXlZ%m3BQn`a34~~r z5ShwClt7F_sE!hv$VD?!Q7Y|4CgU^-VoPaHf>86P?n$#LQMHMQigHmBqj(GJusdbX z^)nZ3r(CHOu2s#7Jq}{b;t>St{;7xNs#&njTDdT{>{e>!@qycjl&xidGTXozrs-Lx z7rFvhhXm>nIy~+w$z4gEY}d#PZep2YIA20o2~X`?jnkG;?V}o->Fz#TYH+hU$P~<` zn#~#@whFT+cp2O88th2X7>`4@DkWPu4X0{D=h-&xxh(unao4j}eZ^kpt`p|`yj8E? zbQY}|q)FGh?^^W-A}6k6ThnIMLSy}GWcY#s7&O2z@uvo0v}bkDW}6EWT!31(Jv_jq z!cc(ey#iYxv~wI&oMS4c4J>X9zER;trZFJKZ#=-HhG8d70H(|xfyuvqz@#-}^4SSY zDZlJ^PhhG*n*^JQHX&5m!UmkPRe&25;HDk7YT7=&zuJW?nf3Z3$6Y{u{Y*O5n>^Ah z?MY5!CYZ#&pUyTB+5Inx6a|qvXTH)z{FKz3_@dOD)WqV{bCVquB{$o%XrfD8 z-<;3h&4#A>=VnGeT}Cv)Uz<(&_0R>EPF^FZJ9)Z5Hk#sSU=L?!)k(+}i zc4xD{kN~>do=#2^y(xg|kwZ$G-Ni~d&_%g6ACW6%LNoNrW(P$NbVJW=?pJYQM^pJ} R^9}81Onj(TP5x%83;;@)f_MM` diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i similarity index 98% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i index b55ca3082aa7dcb6a8a95035a0f07a46678cdd5b..6f03108c314f09c3a53aaee6fc95506ef1666d23 100644 GIT binary patch delta 112 zcmZo@U}|V!Vqp+rVBRR$!pI@O$iPq)nP<6CP=jUj4%QAOjvovR46~+BS+h}a1@q<) z+KQ6=KqV<{U;Z2bO7uOAw4W&GusOl?1``JdP{Ki=Zox)D57x~cz6Yc^B!D7+E}s9s Oc_BXs&*q5I6C$H{`~*1 b!NS1645ZtD^uFK!|33lJl|XvqLk@lb4bB|T delta 71 zcmZorXi(6d?X#PY0SLH31Plm37&m}a0}%fQ0+0yzL|tiCkV4UkzTKM{8UOQ57GTr_ E0IUfOjsO4v diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream similarity index 89% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream index e3a14c307486e7fa5f9e60d92c5274dfaa2b0797..78cd47cda8def3eb5da11760d836028e1f509b77 100644 GIT binary patch delta 107 zcmZorXi(U2ftfLUBBLjNPJVi3p1x~tVrGtBc1bKyNE9OE1Cj_zEiTO|L6z{!FUn2K X0ZT(AL?AkX^OG|X5}PkF@8bdh?ffRC delta 17 YcmZorXi(U2fqAnN>prf{39Lno06TjI5dZ)H diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len new file mode 100644 index 0000000000000000000000000000000000000000..1e061838fa6f03a369ee91f44cd453a5241ede2b GIT binary patch literal 8 McmZQz00CAf002|~NB{r; literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at similarity index 73% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at index 25a7dcc9dbdb77fcd10def6fd9af6ade1da7c4b4..b623d48dcde03d113fbe91e99c3dcda24e47d7cb 100644 GIT binary patch delta 157 zcmdnXewuT`Ugn8gRb_MX(=+q*U2_vNbNKYK^Gk9v^Wt;!Q%ZAEof(WL^D`?cLsa;H h)CHv$m*$kr%F{NzmR>HtXAH>>~v delta 7 OcmX@jxtD#zUS delta 12 TcmZorXi%8o!zi}VcQZc#8MFiR diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/counters.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/counters.tab new file mode 100644 index 000000000..4fef5ef89 --- /dev/null +++ b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/counters.tab @@ -0,0 +1,2 @@ +15 +0 \ No newline at end of file diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab similarity index 95% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab index f5ab490264ceb75c030d12396d5fac5182eae634..fe54fd70754eacd70d278653abce57bf141b6f1f 100644 GIT binary patch delta 99 zcmZorXi(6d?X#PY0SNd(1Plm37(aki0}%fQ0+0y*L|tiCkV5T=zTFBJm>C#)fHE2^ Y3=C~Rx(!G-0O=<{x(Y~de8|BM03x;>djJ3c delta 71 zcmZorXi(6d?X#PY0SLH31Plm37&m}a0}%fQ0+0yzL|tiCkV5&1zTKM{8UOQ57GTr_ E0IZ7*m;e9( diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream similarity index 89% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream index e3a14c307486e7fa5f9e60d92c5274dfaa2b0797..78cd47cda8def3eb5da11760d836028e1f509b77 100644 GIT binary patch delta 107 zcmZorXi(U2ftfLUBBLjNPJVi3p1x~tVrGtBc1bKyNE9OE1Cj_zEiTO|L6z{!FUn2K X0ZT(AL?AkX^OG|X5}PkF@8bdh?ffRC delta 17 YcmZorXi(U2fqAnN>prf{39Lno06TjI5dZ)H diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len new file mode 100644 index 0000000000000000000000000000000000000000..1e061838fa6f03a369ee91f44cd453a5241ede2b GIT binary patch literal 8 McmZQz00CAf002|~NB{r; literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at similarity index 82% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at index afce831e8f06b6776dd87e9f59f94f1de8d53662..3763557f4e133063db1be5f879f8d4ba4a2d37c0 100644 GIT binary patch delta 30 ZcmXT!W}Hwg!NLFp++dOiO!9(BJ^(#$0$l(A delta 5 McmeBXES^vd00pc90{{R3 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i similarity index 99% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i index d18cf546bbfb77e6ad11634a4230ec9084868bc2..ed8fa62ab3b4da6e4f97b3d6e29395f78476e909 100644 GIT binary patch delta 96 zcmZo@U}|V!VqxHCVBUO@aS!9>1B?L@93L1M7@mLn7y=YB5Z>&eYrw{F11RKfz>^0Q uY7pGynjpdP04TC|sn`afNCNZb6A1>a94~-EiFGqJ0fjb*ZQf85zzhHcI3Z~O delta 60 zcmZo@U}|V!VqxHBVBUO@aS!9>1B?L@n;$S*2ygb#HDCj>Is`YlCV+%8m^YtDFkl6; Mc8G1>P!qrm0A*Meu>b%7 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab similarity index 93% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab index bfc127c57bf5ef1aadbd81762bf7cc1a0ddca96e..da2694aa1f9f7af09447a1078c4d655f002fdc53 100644 GIT binary patch delta 99 zcmZorXi(6d?X#PY0SNd(1Plm37(aki0}%fQ0+0y*L|tiCkZS3PzTFDkK*o#T|Nrv< Y={_LM3#9dcG)Td@U;qDae8|BM0QBY?fB*mh delta 71 zcmZorXi(6d?X#PY0SLH31Plm37&m}a0}%fQ0+0yzL|tiCE+9jAqHp(RM#leqlLZ(x E0ju5(ivR!s diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream similarity index 98% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream index b73411eda599178cd04ec5f0e2c9f90e9d194ae5..fbebe849c1a1a4cf2d621f53ec975a5c522de6d3 100644 GIT binary patch delta 27 icmZorXi(s1U}R!uVP#|I;N;@w;pN*X_@1AMfdK$8?E`xN delta 23 ecmZorXi(s0U}R!uVP#|I;N;pU_?~~F0viA-q67K> diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len new file mode 100644 index 0000000000000000000000000000000000000000..933d5532f46fad8a388cd1eda7b7501d90c98111 GIT binary patch literal 8 LcmZQz00Vvi02crd literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len new file mode 100644 index 0000000000000000000000000000000000000000..cf8a30a1c969e61b953bddf5da4778377335bdd6 GIT binary patch literal 8 LcmZQz0D~U@0RRB` literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at similarity index 71% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at index f4949425917fad884b1b8c264ade31df0db0a4cb..ae70a8d7175adb19e3b6a8d26557fde6c8c1ac62 100644 GIT binary patch delta 110 zcmbQvF_C+NILqWEj6Q-n`RSQ?`mVW&nK^pdC2!F< diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i similarity index 99% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i index fd274018e830e7a5904ca90fabd233646303783d..0c9845623d3d099e18f544a802938cdc81bad682 100644 GIT binary patch delta 46 scmZo@U}|V!Vq)N%$P_1ggMop88;BnOF%J;G0AgMs{s6>$8xx!B0n<|m`2YX_ delta 19 acmZo@U}|V!Vq)N$$P~A+rKW!31Qh@}(*}0{ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab similarity index 92% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab index 5d1798fe6c30b47b2dd0895c367b86d1929331c1..2ea84b0b615b2eeda58ce97e7265cdb2d3009867 100644 GIT binary patch delta 177 zcmZorXi(6d?X#PY0SGKX1Plm37#>Uv3=Kf$e;@#fSWeWHW(6rM-00iSnA7p^|NkCF z28JdeJrzjT0O@%^x(rA!2hu4(dIOM-1JXNzbOew-1f+w2^l2dN1EjA2X)7Ro7f7oB c>1RM%2uQyN(kwvw2avw>_y7ORj7&Rt0ka!M3jhEB delta 109 zcmZorXi(6d?X#PY0SF901Plm38B7ce4M669AOMLNOw^TT1u2Z*=-bbzQuFWs{~ksL hhBP2O6-b8w>3Klf4M;Bs(keiDb0E`t-pL6}fdE)aAt?X= diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream similarity index 93% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream index eeb177d5157335078b15e5291dd54457256889b5..c5555f823707dd85610c1d8e5eb7e895ee456681 100644 GIT binary patch delta 93 zcmZorXi(Tt%^1M^Kf0!I^@R_N>m4JGff+%k9xVbhUhmev17=LI@-c)n{GTrQ#|RRs ZD*JH)%#dSfS^{Ql`*8Z+<|;;0J^+N{ES3NO delta 16 XcmZorXi(Tt&A9mtqY2++0j59zF(d^g diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len new file mode 100644 index 0000000000000000000000000000000000000000..93e68eb1eccc2c56ce43754fe543f89edcf16933 GIT binary patch literal 8 McmZQz00AaO000dD1ONa4 literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.len new file mode 100644 index 0000000000000000000000000000000000000000..5ffc1b29da6b9f4d549b5cd7ca2ba240098d0c7b GIT binary patch literal 8 McmZQz00AZs002|~O8@`> literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at similarity index 65% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at index 8bd51fcfa1914a786c8ce5d695d6c764b19f30d1..c9c04602a391f012ff514fd306f305c704ef101b 100644 GIT binary patch delta 106 zcmaFJyqRS~A)^xu0}yb7NggoC3nuvlz~VrH2Z(urm=BlA$%Tv_j0O|eDT)DAabxJ< F1OU8k2KfL0 delta 16 YcmdnY@{oB$A>-uDj2;u$sxxu|05_QhyZ`_I diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab_i similarity index 93% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab_i index 42142a0bacc3001696c26ce8ee87abee91b9bf1e..d314f4ab39dad6177349578a192922d0f2c93ac2 100644 GIT binary patch delta 261 zcmZo@U}|V!VqvgkVBRRm!pOnF#K16l55M3=ZOEBl;mJHW2w wxB=w7nlN=2P(cDC#}6Ry?Y%EfKsgTP%@b-Y8QFmbY&UAl1$tm}M%@fX0Fzx)Jpcdz delta 172 zcmZo@U}|V!Vqq{~VBWlt(S>od2V(%o<^Y2R*3A<90gMwB7EEraWMR>IA7wUC@WSQ? zf$=xOpMx50=R{Bvx>I0E&DF`muhZV8-STk`F{CZ(#he`G9@{*WwL~ zjFTO#GdOMlRS13N-V4+dz%u!Q9t+FQsi77?D>pDM-r>m4@d7CSrO#9zDAECRL{Naj W=7N|XoSP@qSOOg}e{)9N3`PJPRY4*E diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len diff --git a/core/model/build/kotlin/compileKotlin/cacheable/last-build.bin b/core/model/build/kotlin/compileKotlin/cacheable/last-build.bin new file mode 100644 index 0000000000000000000000000000000000000000..5e2dabde74f0c27b03ddbe495d9329cf7cae549e GIT binary patch literal 18 YcmZ4UmVvdLhk=1{a)R%NKMX(s05~iKPXGV_ literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileKotlin/local-state/build-history.bin b/core/model/build/kotlin/compileKotlin/local-state/build-history.bin new file mode 100644 index 0000000000000000000000000000000000000000..0a322d558880b4cd18c40938a1b4cabe619e09de GIT binary patch literal 31 dcmZ4UmVvcgk^ur385kHRC-{E&1LZR?003nx1zi9D literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len deleted file mode 100644 index d668d29e3549857164aea4d670feb76be744c537..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 McmZQz00HI;007J5QZ%+1;FauWS*P)_ZQJe z6dvp!-X1Tsn5>8W`Q@}Twms+%I$PW5Hc0$DCF*#Ezfs2E;aaRbcv3rrTS)GcDql{;DKSHA~=k6H5b4cmqSDF6Tf diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len deleted file mode 100644 index 3e5b6a53b2112490602c273be4e1ef350c97c8aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 McmZQz00E{8007(o(*OVf diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len deleted file mode 100644 index 3e5b6a53b2112490602c273be4e1ef350c97c8aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 McmZQz00E{8007(o(*OVf diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len deleted file mode 100644 index 3e5b6a53b2112490602c273be4e1ef350c97c8aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 McmZQz00E{8007(o(*OVf diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len deleted file mode 100644 index c1727f81f1c581b1be67e7a57fc5848110e04f40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 McmZQz00E}^008R%;s5{u diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len deleted file mode 100644 index 9911af5051faa67d9b81264a155131096082b4f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 McmZQz00Bk@000UA0ssI2 diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len deleted file mode 100644 index d668d29e3549857164aea4d670feb76be744c537..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 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

x=Oa5nT=XxsHro+Q?hYxK^#rUjGn5BS#yr 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 I?dP-q2S1UVqyPW_ literal 0 HcmV?d00001 diff --git a/core/model/build/reports/ktlint/ktlintKotlinScriptFormat/ktlintKotlinScriptFormat.txt b/core/model/build/reports/ktlint/ktlintKotlinScriptFormat/ktlintKotlinScriptFormat.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/core/model/build/reports/ktlint/ktlintMainSourceSetFormat/ktlintMainSourceSetFormat.txt b/core/model/build/reports/ktlint/ktlintMainSourceSetFormat/ktlintMainSourceSetFormat.txt deleted file mode 100644 index e69de29bb..000000000 From 85f344fe007c0053291ed0a62fac746a9d2100f8 Mon Sep 17 00:00:00 2001 From: Seunggu Kang Date: Mon, 3 Feb 2025 21:14:42 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- app/build.gradle.kts | 12 +- app/src/main/AndroidManifest.xml | 4 +- core/data/build.gradle.kts | 15 + .../connectdog/core/data/api/ApiService.kt | 72 ++- .../core/data/api/InterApiService.kt | 47 +- .../connectdog/core/data/api/model/AuthDto.kt | 5 - .../core/data/api/model/EmailDto.kt | 5 - .../api/model/IsDuplicateNicknameResponse.kt | 5 - .../api/model/IsDuplicatePhoneNumberBody.kt | 5 - .../model/IsDuplicatePhoneNumberResponse.kt | 7 - .../core/data/api/model/NormalLoginBody.kt | 6 - .../core/data/api/model/PhoneDto.kt | 5 - .../core/data/api/model/SocialLoginBody.kt | 6 - .../data/api/model/volunteer/EmailAuthDto.kt | 6 - .../model/volunteer/EmailCertificationBody.kt | 5 - .../connectdog/core/data/di/ApiModule.kt | 24 +- .../core/data/di/DataStoreModule.kt | 21 + .../core/data/di/VolunteerDataModule.kt | 32 +- .../data/repository/AuthRepositoryImpl.kt | 65 +++ .../data/repository/DataStoreRepository.kt | 106 ----- .../repository/DataStoreRepositoryImpl.kt | 102 +++++ .../core/data/repository/LoginRepository.kt | 31 -- .../data/repository/LoginRepositoryImpl.kt | 70 ++- .../core/data/repository/MyPageRepository.kt | 6 +- .../data/repository/MyPageRepositoryImpl.kt | 6 +- .../core/data/repository/SignUpRepository.kt | 20 - .../data/repository/SignUpRepositoryImpl.kt | 150 +++--- .../core/designsystem/BuildConfig.java | 10 + .../core/designsystem/BuildConfig.java | 10 + .../core/designsystem/component/ActionRow.kt | 40 ++ .../core/designsystem/component/Banner.kt | 6 + .../core/designsystem/component/CheckBox.kt | 78 ++++ .../core/designsystem/component/Line.kt | 31 ++ .../core/designsystem/component/SearchBar.kt | 82 ++++ .../core/designsystem/component/TopAppBar.kt | 8 +- .../core/designsystem/theme/Color.kt | 3 + .../src/main/res/values/strings.xml | 6 +- core/model/build.gradle.kts | 26 +- .../model/AnnouncementHome$Companion.class | Bin 0 -> 1340 bytes .../core/model/AnnouncementHome.class | Bin 4690 -> 5013 bytes .../model/auth/AuthCodeWithAccessToken.class | Bin 0 -> 3050 bytes .../core/model/{login => auth}/Email.class | Bin 2436 -> 2431 bytes .../core/model/auth/EmailAuthCode.class | Bin 0 -> 2496 bytes .../connectdog/core/model/auth/Phone.class | Bin 0 -> 2431 bytes .../model/auth/PhoneNumberDuplication.class | Bin 0 -> 3342 bytes .../core/model/signup/IsDuplicated.class | Bin 0 -> 2135 bytes .../connectdog/core/model/signup/Name.class | Bin 0 -> 2431 bytes .../core/model/signup/Nickname.class | Bin 0 -> 2471 bytes .../model/signup/NormalVolunteerDetail.class | Bin 0 -> 5350 bytes .../model/signup/SocialVolunteerDetail.class | Bin 0 -> 4404 bytes .../caches-jvm/inputs/source-to-output.tab | Bin 4096 -> 4096 bytes .../inputs/source-to-output.tab.keystream | Bin 4096 -> 4096 bytes .../inputs/source-to-output.tab.keystream.len | Bin 8 -> 8 bytes .../inputs/source-to-output.tab.len | Bin 8 -> 8 bytes .../inputs/source-to-output.tab.values.at | Bin 3286 -> 5348 bytes .../caches-jvm/inputs/source-to-output.tab_i | Bin 32768 -> 32768 bytes .../jvm/kotlin/class-attributes.tab | Bin 4096 -> 4096 bytes .../jvm/kotlin/class-attributes.tab.keystream | Bin 4096 -> 4096 bytes .../kotlin/class-attributes.tab.keystream.len | Bin 8 -> 8 bytes .../jvm/kotlin/class-attributes.tab.len | Bin 8 -> 8 bytes .../jvm/kotlin/class-attributes.tab.values.at | Bin 106 -> 139 bytes .../jvm/kotlin/class-attributes.tab_i | Bin 32768 -> 32768 bytes .../jvm/kotlin/class-fq-name-to-source.tab | Bin 4096 -> 4096 bytes .../class-fq-name-to-source.tab.keystream | Bin 4096 -> 4096 bytes .../class-fq-name-to-source.tab.keystream.len | Bin 8 -> 8 bytes .../kotlin/class-fq-name-to-source.tab.len | Bin 8 -> 8 bytes .../class-fq-name-to-source.tab.values.at | Bin 1781 -> 2865 bytes .../jvm/kotlin/class-fq-name-to-source.tab_i | Bin 32768 -> 32768 bytes .../jvm/kotlin/internal-name-to-source.tab | Bin 4096 -> 4096 bytes .../internal-name-to-source.tab.keystream | Bin 4096 -> 4096 bytes .../internal-name-to-source.tab.keystream.len | Bin 8 -> 8 bytes .../kotlin/internal-name-to-source.tab.len | Bin 8 -> 8 bytes .../internal-name-to-source.tab.values.at | Bin 1781 -> 2865 bytes .../jvm/kotlin/internal-name-to-source.tab_i | Bin 32768 -> 32768 bytes .../cacheable/caches-jvm/jvm/kotlin/proto.tab | Bin 4096 -> 4096 bytes .../caches-jvm/jvm/kotlin/proto.tab.keystream | Bin 4096 -> 4096 bytes .../jvm/kotlin/proto.tab.keystream.len | Bin 8 -> 8 bytes .../caches-jvm/jvm/kotlin/proto.tab.len | Bin 8 -> 8 bytes .../caches-jvm/jvm/kotlin/proto.tab.values.at | Bin 13849 -> 19376 bytes .../caches-jvm/jvm/kotlin/proto.tab_i | Bin 32768 -> 32768 bytes .../jvm/kotlin/source-to-classes.tab | Bin 4096 -> 4096 bytes .../kotlin/source-to-classes.tab.keystream | Bin 4096 -> 4096 bytes .../source-to-classes.tab.keystream.len | Bin 8 -> 8 bytes .../jvm/kotlin/source-to-classes.tab.len | Bin 8 -> 8 bytes .../kotlin/source-to-classes.tab.values.at | Bin 1227 -> 2007 bytes .../jvm/kotlin/source-to-classes.tab_i | Bin 32768 -> 32768 bytes .../caches-jvm/jvm/kotlin/supertypes.tab | Bin 4096 -> 4096 bytes .../cacheable/caches-jvm/lookups/counters.tab | 2 +- .../caches-jvm/lookups/file-to-id.tab | Bin 4096 -> 4096 bytes .../lookups/file-to-id.tab.keystream | Bin 4096 -> 4096 bytes .../lookups/file-to-id.tab.keystream.len | Bin 8 -> 8 bytes .../caches-jvm/lookups/file-to-id.tab.len | Bin 8 -> 8 bytes .../lookups/file-to-id.tab.values.at | Bin 139 -> 199 bytes .../caches-jvm/lookups/file-to-id.tab_i | Bin 32768 -> 32768 bytes .../caches-jvm/lookups/id-to-file.tab | Bin 4096 -> 4096 bytes .../lookups/id-to-file.tab.keystream | Bin 4096 -> 4096 bytes .../lookups/id-to-file.tab.keystream.len | Bin 8 -> 8 bytes .../caches-jvm/lookups/id-to-file.tab.len | Bin 8 -> 8 bytes .../lookups/id-to-file.tab.values.at | Bin 1425 -> 2414 bytes .../caches-jvm/lookups/id-to-file.tab_i | Bin 32768 -> 32768 bytes .../cacheable/caches-jvm/lookups/lookups.tab | Bin 4096 -> 4096 bytes .../caches-jvm/lookups/lookups.tab.keystream | Bin 4096 -> 4096 bytes .../lookups/lookups.tab.keystream.len | Bin 8 -> 8 bytes .../caches-jvm/lookups/lookups.tab.len | Bin 8 -> 8 bytes .../caches-jvm/lookups/lookups.tab.values.at | Bin 563 -> 984 bytes .../caches-jvm/lookups/lookups.tab_i | Bin 32768 -> 32768 bytes .../compileKotlin/cacheable/last-build.bin | Bin 18 -> 18 bytes .../local-state/build-history.bin | Bin 31 -> 504 bytes core/model/build/kotlin/modeljar-classes.txt | 2 +- core/model/build/libs/model.jar | Bin 33239 -> 48976 bytes .../connectdog/core/model/AnnouncementHome.kt | 13 +- .../model/auth/AuthCodeWithAccessToken.kt | 6 + .../connectdog/core/model/auth/Email.kt | 5 + .../core/model/auth/EmailAuthCode.kt | 5 + .../connectdog/core/model/auth/Phone.kt | 5 + .../core/model/auth/PhoneNumberDuplication.kt | 7 + .../core/model/login/LoginResult.kt} | 4 +- .../core/model/login/NormalLogin.kt | 6 + .../core/model/login/SocialLogin.kt | 6 + .../core/model/signup/IsDuplicated.kt | 5 + .../connectdog/core/model/signup/Name.kt | 5 + .../connectdog/core/model/signup/Nickname.kt | 5 + .../model/signup/NormalVolunteerDetail.kt} | 4 +- .../model/signup/SocialVolunteerDetail.kt} | 4 +- .../kusitms/connectdog/core/util/Constants.kt | 20 +- core/util/src/main/res/values/string.xml | 5 + .../model/remote/request/NormalLoginDto.kt | 6 - domain/build.gradle.kts | 11 +- .../domain/repository/AuthRepository.kt | 19 + .../domain/repository/DataStoreRepository.kt | 23 + .../domain/repository/LoginRepository.kt | 22 + .../domain/repository/SignUpRepository.kt | 26 ++ .../domain/usecase/GetAppModeUseCase.kt | 12 + .../domain/usecase/GetFcmTokenUseCase.kt | 12 + .../domain/usecase/UpdateFcmTokenUseCase.kt | 12 + ...uthForIntermediatorPasswordResetUseCase.kt | 12 + ...ilAuthForVolunteerPassowordResetUseCase.kt | 12 + .../usecase/auth/GetEmailAuthCodeUseCase.kt | 12 + ...ermediatorPhoneNumberDuplicationUseCase.kt | 12 + ...tVolunteerPhoneNumberDuplicationUseCase.kt | 12 + .../auth/SearchIntermediatorEmailUseCase.kt | 12 + .../auth/SearchVolunteerEmailUseCase.kt | 12 + .../usecase/login/DeleteAccessTokenUseCase.kt | 12 + .../login/IntermediatorLoginUseCase.kt | 15 + .../domain/usecase/login/LogoutUseCase.kt | 12 + .../usecase/login/SocialLoginUseCase.kt | 15 + .../usecase/login/UpdateAccessTokenUseCase.kt | 12 + .../usecase/login/UpdateAppModeUseCase.kt | 18 + .../login/UpdateRefreshTokenUseCase.kt | 12 + .../login/UpdateSocialProviderUseCase.kt | 16 + .../usecase/login/UpdateSocialTokenUseCase.kt | 12 + .../usecase/login/VolunteerLoginUseCase.kt | 15 + .../signup/GetIntermediatorNameDuplication.kt | 12 + .../signup/GetSocialProviderUseCase.kt | 12 + .../usecase/signup/GetSocialTokenUseCase.kt | 12 + .../signup/GetVolunteerNicknameDuplication.kt | 12 + .../InitNormalVolunteerSignUpUseCase.kt | 28 ++ .../InitSocialVolunteerSignUpUseCase.kt | 28 ++ feature/home/build.gradle.kts | 2 +- .../connectdog/feature/home/HomeViewModel.kt | 18 +- .../feature/home/screen/HomeScreen.kt | 280 ++---------- feature/home/src/main/res/values/string.xml | 2 - feature/intermediator/build.gradle.kts | 2 +- .../viewmodel/InterHomeViewModel.kt | 21 +- feature/login/build.gradle.kts | 30 +- .../login/{ => navigation}/LoginNavigation.kt | 63 ++- ....kt => EmailAuthForPasswordResetScreen.kt} | 85 ++-- .../login/screen/EmailSearchResultScreen.kt | 2 +- .../feature/login/screen/EmailSearchScreen.kt | 134 +++--- .../feature/login/screen/LoginScreen.kt | 147 +++--- .../feature/login/screen/NoAccountScreen.kt | 57 +++ .../feature/login/screen/NormalLoginScreen.kt | 134 ++---- ...SearchScreen.kt => PasswordResetScreen.kt} | 6 +- .../state/EmailAuthForPasswordResetUiState.kt | 36 ++ .../feature/login/state/EmailSearchUiState.kt | 29 ++ .../feature/login/state/LoginUiState.kt | 28 ++ .../login/state/PasswordResetUiState.kt | 19 + .../EmailAuthForPasswordResetViewModel.kt | 93 ++++ .../login/viewmodel/EmailSearchViewModel.kt | 91 ++++ .../feature/login/viewmodel/LoginViewModel.kt | 249 ++++------ ...ViewModel.kt => PasswordResetViewModel.kt} | 13 +- .../viewmodel/PasswordSearchAuthViewModel.kt | 105 ----- .../login/viewmodel/SearchViewModel.kt | 77 ---- feature/login/src/main/res/values/strings.xml | 18 + feature/main/build.gradle.kts | 9 +- .../connectdog/feature/main/MainActivity.kt | 20 +- .../connectdog/feature/main/MainNavigator.kt | 36 +- .../connectdog/feature/main/MainScreen.kt | 56 ++- .../connectdog/feature/main/MainUiState.kt | 15 + .../connectdog/feature/main/MainViewModel.kt | 31 +- feature/mypage/build.gradle.kts | 2 +- .../mypage/viewmodel/EditProfileViewModel.kt | 3 +- .../viewmodel/PasswordChangeViewModel.kt | 6 +- .../mypage/viewmodel/SettingViewModel.kt | 28 +- feature/signup/build.gradle.kts | 12 +- .../signup/navigation/SignUpNavigation.kt | 191 ++++---- .../screen/common/CeritificationScreen.kt | 127 +++-- .../screen/common/CompleteSignUpScreen.kt | 33 +- .../screen/common/RegisterEmailScreen.kt | 191 ++++---- .../screen/common/RegisterPasswordScreen.kt | 180 ++++---- .../signup/screen/common/TermScreen.kt | 285 ++++-------- .../IntermediatorInformationScreen.kt | 11 +- .../IntermediatorProfileScreen.kt | 228 ++++----- .../volunteer/SelectProfileImageScreen.kt | 126 ++--- .../volunteer/VolunteerProfileScreen.kt | 193 ++++---- .../signup/state/SelectProfileImageUiState.kt | 13 + .../connectdog/signup/state/SignUpUiState.kt | 95 ++++ .../connectdog/signup/state/TermsUiState.kt | 48 ++ .../viewmodel/CertificationViewModel.kt | 4 +- .../IntermediatorProfileViewModel.kt | 4 +- .../viewmodel/RegisterEmailViewModel.kt | 89 ---- .../viewmodel/SelectProfileImageViewModel.kt | 23 + .../signup/viewmodel/SignUpViewModel.kt | 432 ++++++++++++------ .../signup/viewmodel/TermsViewModel.kt | 89 ++-- .../viewmodel/VolunteerProfileViewModel.kt | 73 --- feature/signup/src/main/res/values/string.xml | 28 ++ gradle.properties | 3 +- gradle/libs.versions.toml | 3 + settings.gradle.kts | 13 +- 220 files changed, 3446 insertions(+), 2715 deletions(-) delete mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/AuthDto.kt delete mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/EmailDto.kt delete mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicateNicknameResponse.kt delete mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberBody.kt delete mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberResponse.kt delete mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/NormalLoginBody.kt delete mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/PhoneDto.kt delete mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/SocialLoginBody.kt delete mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailAuthDto.kt delete mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailCertificationBody.kt create mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/di/DataStoreModule.kt create mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/repository/AuthRepositoryImpl.kt delete mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepository.kt create mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepositoryImpl.kt delete mode 100644 core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepository.kt create mode 100644 core/designsystem/build/generated/source/buildConfig/debug/com/kusitms/connectdog/core/designsystem/BuildConfig.java create mode 100644 core/designsystem/build/generated/source/buildConfig/release/com/kusitms/connectdog/core/designsystem/BuildConfig.java create mode 100644 core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/ActionRow.kt create mode 100644 core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/CheckBox.kt create mode 100644 core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Line.kt create mode 100644 core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/SearchBar.kt create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome$Companion.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.class rename core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/{login => auth}/Email.class (76%) create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/EmailAuthCode.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Phone.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/PhoneNumberDuplication.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/IsDuplicated.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Name.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Nickname.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.class create mode 100644 core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/SocialVolunteerDetail.class create mode 100644 core/model/src/main/java/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.kt create mode 100644 core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Email.kt create mode 100644 core/model/src/main/java/com/kusitms/connectdog/core/model/auth/EmailAuthCode.kt create mode 100644 core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Phone.kt create mode 100644 core/model/src/main/java/com/kusitms/connectdog/core/model/auth/PhoneNumberDuplication.kt rename core/{data/src/main/java/com/kusitms/connectdog/core/data/api/model/LoginResponseItem.kt => model/src/main/java/com/kusitms/connectdog/core/model/login/LoginResult.kt} (51%) create mode 100644 core/model/src/main/java/com/kusitms/connectdog/core/model/login/NormalLogin.kt create mode 100644 core/model/src/main/java/com/kusitms/connectdog/core/model/login/SocialLogin.kt create mode 100644 core/model/src/main/java/com/kusitms/connectdog/core/model/signup/IsDuplicated.kt create mode 100644 core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Name.kt create mode 100644 core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Nickname.kt rename core/{data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/NormalVolunteerSignUpBody.kt => model/src/main/java/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.kt} (65%) rename core/{data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/SocialVolunteerSignUpBody.kt => model/src/main/java/com/kusitms/connectdog/core/model/signup/SocialVolunteerDetail.kt} (58%) create mode 100644 core/util/src/main/res/values/string.xml delete mode 100644 data/src/main/java/com/kusitms/connectdog/data/model/remote/request/NormalLoginDto.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/repository/AuthRepository.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/repository/DataStoreRepository.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/repository/LoginRepository.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/repository/SignUpRepository.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetAppModeUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetFcmTokenUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/UpdateFcmTokenUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForIntermediatorPasswordResetUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForVolunteerPassowordResetUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetEmailAuthCodeUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetIntermediatorPhoneNumberDuplicationUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetVolunteerPhoneNumberDuplicationUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchIntermediatorEmailUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchVolunteerEmailUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/DeleteAccessTokenUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/IntermediatorLoginUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/LogoutUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/SocialLoginUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAccessTokenUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAppModeUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateRefreshTokenUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialProviderUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialTokenUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/VolunteerLoginUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetIntermediatorNameDuplication.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialProviderUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialTokenUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetVolunteerNicknameDuplication.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitNormalVolunteerSignUpUseCase.kt create mode 100644 domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitSocialVolunteerSignUpUseCase.kt rename feature/login/src/main/java/com/kusitms/connectdog/feature/login/{ => navigation}/LoginNavigation.kt (72%) rename feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/{PasswordSearchAuthScreen.kt => EmailAuthForPasswordResetScreen.kt} (57%) create mode 100644 feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NoAccountScreen.kt rename feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/{PasswordSearchScreen.kt => PasswordResetScreen.kt} (96%) create mode 100644 feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailAuthForPasswordResetUiState.kt create mode 100644 feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailSearchUiState.kt create mode 100644 feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/LoginUiState.kt create mode 100644 feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/PasswordResetUiState.kt create mode 100644 feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailAuthForPasswordResetViewModel.kt create mode 100644 feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailSearchViewModel.kt rename feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/{PasswordSearchViewModel.kt => PasswordResetViewModel.kt} (77%) delete mode 100644 feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordSearchAuthViewModel.kt delete mode 100644 feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/SearchViewModel.kt create mode 100644 feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainUiState.kt create mode 100644 feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SelectProfileImageUiState.kt create mode 100644 feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SignUpUiState.kt create mode 100644 feature/signup/src/main/java/com/kusitms/connectdog/signup/state/TermsUiState.kt delete mode 100644 feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/RegisterEmailViewModel.kt create mode 100644 feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SelectProfileImageViewModel.kt delete mode 100644 feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/VolunteerProfileViewModel.kt diff --git a/.gitignore b/.gitignore index ec9cfba01..3c5e3b0b9 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,5 @@ core/designsystem/build/outputs/aar/ core/model/build/outputs/aar/ core/designsystem/build/tmp/kotlin-classes/debug/META-INF core/designsystem/build/tmp -core/designsystem/build/kotlin/compileReleaseKotlin/ \ No newline at end of file +core/designsystem/build/kotlin/compileReleaseKotlin/ +core/model/build/kotlin compileReleaseKotlin/ \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0efbc6b82..46cc891df 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,4 +1,5 @@ import com.kusitms.connectdog.Configuration +import org.jetbrains.kotlin.konan.properties.Properties @Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed plugins { @@ -24,6 +25,13 @@ android { vectorDrawables { useSupportLibrary = true } + + val localProperties = Properties() + val localPropertiesFile = rootProject.file("local.properties") + if (localPropertiesFile.exists()) { localPropertiesFile.inputStream().use { localProperties.load(it) } } + + val kakaoAppKey: String = localProperties.getProperty("kakao_app_key") ?: "" + manifestPlaceholders["KAKAO_APP_KEY"] = kakaoAppKey } buildTypes { @@ -43,7 +51,9 @@ android { kotlinOptions { jvmTarget = "17" } - + buildFeatures { + buildConfig = true + } packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3141c2a6c..8f88bf606 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,7 +18,7 @@ tools:targetApi="33"> + android:value="${KAKAO_APP_KEY}" /> + android:scheme="kakao${KAKAO_APP_KEY}" /> diff --git a/core/data/build.gradle.kts b/core/data/build.gradle.kts index 29b949ee8..80c307d03 100644 --- a/core/data/build.gradle.kts +++ b/core/data/build.gradle.kts @@ -1,4 +1,5 @@ import com.kusitms.connectdog.Configuration +import org.jetbrains.kotlin.konan.properties.Properties @Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed plugins { @@ -16,6 +17,14 @@ android { defaultConfig { minSdk = Configuration.minSdk + val localProperties = Properties() + val localPropertiesFile = rootProject.file("local.properties") + if (localPropertiesFile.exists()) { localPropertiesFile.inputStream().use { localProperties.load(it) } } + + val baseUrl: String = localProperties.getProperty("BASE_URL") ?: "" + + buildConfigField("String", "BASE_URL", "\"$baseUrl\"") + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") } @@ -36,15 +45,21 @@ android { kotlinOptions { jvmTarget = "17" } + buildFeatures { + buildConfig = true + } } dependencies { + implementation(projects.domain) implementation(project(":core:model")) implementation(project(":core:util")) kapt(libs.hilt.compiler) implementation(libs.hilt.android) + implementation(libs.kotlinx.coroutines.core) + implementation(libs.retrofit.core) implementation(libs.retrofit.kotlin.serialization) implementation(libs.retrofit.converter.moshi) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/ApiService.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/ApiService.kt index fed0d091b..d8078a559 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/ApiService.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/ApiService.kt @@ -1,18 +1,9 @@ package com.kusitms.connectdog.core.data.api import com.kusitms.connectdog.core.data.api.model.AdditionalAuthBody -import com.kusitms.connectdog.core.data.api.model.AuthDto -import com.kusitms.connectdog.core.data.api.model.EmailDto import com.kusitms.connectdog.core.data.api.model.FcmTokenRequestBody -import com.kusitms.connectdog.core.data.api.model.IsDuplicateNicknameResponse -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberBody -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberResponse -import com.kusitms.connectdog.core.data.api.model.LoginResponseItem import com.kusitms.connectdog.core.data.api.model.MyInfoResponseItem -import com.kusitms.connectdog.core.data.api.model.NormalLoginBody -import com.kusitms.connectdog.core.data.api.model.PhoneDto import com.kusitms.connectdog.core.data.api.model.Response -import com.kusitms.connectdog.core.data.api.model.SocialLoginBody import com.kusitms.connectdog.core.data.api.model.VolunteerResponse import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorInfoResponseItem import com.kusitms.connectdog.core.data.api.model.volunteer.AnnouncementHomeResponseItem @@ -24,18 +15,25 @@ import com.kusitms.connectdog.core.data.api.model.volunteer.ApplyBody import com.kusitms.connectdog.core.data.api.model.volunteer.BadgeResponse import com.kusitms.connectdog.core.data.api.model.volunteer.BasicInformationResponse import com.kusitms.connectdog.core.data.api.model.volunteer.BookmarkResponseItem -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailAuthDto -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailCertificationBody -import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody -import com.kusitms.connectdog.core.data.api.model.volunteer.NormalVolunteerSignUpBody import com.kusitms.connectdog.core.data.api.model.volunteer.NoticeDetailResponseItem import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordCheckResponse import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordDto import com.kusitms.connectdog.core.data.api.model.volunteer.ReviewDetailResponse import com.kusitms.connectdog.core.data.api.model.volunteer.ReviewDetailWithId -import com.kusitms.connectdog.core.data.api.model.volunteer.SocialVolunteerSignUpBody import com.kusitms.connectdog.core.data.api.model.volunteer.UserInfoResponse import com.kusitms.connectdog.core.data.api.model.volunteer.VolunteerAccountInfo +import com.kusitms.connectdog.core.model.auth.AuthCodeWithAccessToken +import com.kusitms.connectdog.core.model.auth.Email +import com.kusitms.connectdog.core.model.auth.EmailAuthCode +import com.kusitms.connectdog.core.model.auth.Phone +import com.kusitms.connectdog.core.model.auth.PhoneNumberDuplication +import com.kusitms.connectdog.core.model.login.LoginResult +import com.kusitms.connectdog.core.model.login.NormalLogin +import com.kusitms.connectdog.core.model.login.SocialLogin +import com.kusitms.connectdog.core.model.signup.IsDuplicated +import com.kusitms.connectdog.core.model.signup.Nickname +import com.kusitms.connectdog.core.model.signup.NormalVolunteerDetail +import com.kusitms.connectdog.core.model.signup.SocialVolunteerDetail import okhttp3.MultipartBody import okhttp3.RequestBody import retrofit2.http.Body @@ -83,28 +81,28 @@ internal interface ApiService { */ @POST("/volunteers/nickname/isDuplicated") suspend fun postNickname( - @Body nickname: IsDuplicateNicknameBody - ): IsDuplicateNicknameResponse + @Body body: Nickname + ): IsDuplicated @POST("/volunteers/sign-up/email") - suspend fun postEmail( - @Body emailCertificationBody: EmailCertificationBody - ): AuthDto + suspend fun getEmailAuthCode( + @Body body: Email + ): EmailAuthCode @POST("/volunteers/sign-up") suspend fun postNormalVolunteerSignUp( - @Body normalVolunteerSignUpBody: NormalVolunteerSignUpBody + @Body body: NormalVolunteerDetail ) @PATCH("/volunteers/sign-up/social") suspend fun postSocialVolunteerSignUp( - @Body socialVolunteerSignUpBody: SocialVolunteerSignUpBody + @Body socialVolunteerSignUpBody: SocialVolunteerDetail ) @POST("/volunteers/phone/isDuplicated") - suspend fun getIsDuplicatePhoneNumber( - @Body isDuplicatePhoneNumberBody: IsDuplicatePhoneNumberBody - ): IsDuplicatePhoneNumberResponse + suspend fun getPhoneNumberDuplication( + @Body body: Phone + ): PhoneNumberDuplication /** * 봉사관리 @@ -147,25 +145,19 @@ internal interface ApiService { */ @Headers("Content-Type: application/json") @POST("/volunteers/login") - suspend fun postLoginData( - @Body loginBody: NormalLoginBody - ): LoginResponseItem - - @Headers("Content-Type: application/json") - @POST("/intermediaries/login") - suspend fun postIntermediatorLoginData( - @Body loginBody: NormalLoginBody - ): LoginResponseItem + suspend fun normalLogin( + @Body loginBody: NormalLogin + ): LoginResult @POST("/volunteers/login/social") suspend fun postSocialLoginData( - @Body socialLoginBody: SocialLoginBody - ): LoginResponseItem + @Body socialLoginBody: SocialLogin + ): LoginResult @POST("/volunteers/search/send-email") suspend fun volunteerPasswordSearchAuth( - @Body body: EmailDto - ): EmailAuthDto + @Body body: Email + ): AuthCodeWithAccessToken /**s * 이동봉사자 > 마이페이지 @@ -284,7 +276,7 @@ internal interface ApiService { suspend fun getVolunteerAccountInfo(): VolunteerAccountInfo @POST("/volunteers/search/email") - suspend fun volunteerEmailSearch( - @Body body: PhoneDto - ): EmailDto + suspend fun searchVolunteerEmail( + @Body body: Phone + ): Email } diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/InterApiService.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/InterApiService.kt index 335501855..071669646 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/InterApiService.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/InterApiService.kt @@ -1,13 +1,8 @@ package com.kusitms.connectdog.core.data.api -import com.kusitms.connectdog.core.data.api.model.EmailDto import com.kusitms.connectdog.core.data.api.model.FcmTokenRequestBody -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberBody -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberResponse -import com.kusitms.connectdog.core.data.api.model.PhoneDto import com.kusitms.connectdog.core.data.api.model.Response import com.kusitms.connectdog.core.data.api.model.VolunteerResponse -import com.kusitms.connectdog.core.data.api.model.intermediator.DuplicateDto import com.kusitms.connectdog.core.data.api.model.intermediator.InterAnnouncementDetailResponse import com.kusitms.connectdog.core.data.api.model.intermediator.InterApplicationCompletedResponseItem import com.kusitms.connectdog.core.data.api.model.intermediator.InterApplicationInProgressResponseItem @@ -17,16 +12,23 @@ import com.kusitms.connectdog.core.data.api.model.intermediator.InterProfileFind import com.kusitms.connectdog.core.data.api.model.intermediator.InterProfileInfoResponse import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorAccountInfo import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorProfileInfoResponseItem -import com.kusitms.connectdog.core.data.api.model.intermediator.NameDto -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailAuthDto import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordCheckResponse import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordDto import com.kusitms.connectdog.core.data.api.model.volunteer.ReviewDetailResponse +import com.kusitms.connectdog.core.model.auth.AuthCodeWithAccessToken +import com.kusitms.connectdog.core.model.auth.Email +import com.kusitms.connectdog.core.model.auth.Phone +import com.kusitms.connectdog.core.model.auth.PhoneNumberDuplication +import com.kusitms.connectdog.core.model.login.LoginResult +import com.kusitms.connectdog.core.model.login.NormalLogin +import com.kusitms.connectdog.core.model.signup.IsDuplicated +import com.kusitms.connectdog.core.model.signup.Name import okhttp3.MultipartBody import okhttp3.RequestBody import retrofit2.http.Body import retrofit2.http.DELETE import retrofit2.http.GET +import retrofit2.http.Headers import retrofit2.http.Multipart import retrofit2.http.PATCH import retrofit2.http.POST @@ -36,6 +38,15 @@ import retrofit2.http.Query internal interface InterApiService { + /** + * 로그인 + */ + @Headers("Content-Type: application/json") + @POST("/intermediaries/login") + suspend fun normalLogin( + @Body body: NormalLogin + ): LoginResult + /** * 회원가입 */ @@ -47,14 +58,14 @@ internal interface InterApiService { ) @POST("/intermediaries/phone/isDuplicated") - suspend fun getIsDuplicatePhoneNumber( - @Body body: IsDuplicatePhoneNumberBody - ): IsDuplicatePhoneNumberResponse + suspend fun getPhoneNumberDuplication( + @Body body: Phone + ): PhoneNumberDuplication @POST("/intermediaries/name/isDuplicated") suspend fun checkIsDuplicateName( - @Body body: NameDto - ): DuplicateDto + @Body body: Name + ): IsDuplicated @POST("/intermediaries/password/check") suspend fun checkInterPassword( @@ -158,9 +169,9 @@ internal interface InterApiService { suspend fun patchNotification() @POST("/intermediaries/search/send-email") - suspend fun interPasswordSearchAuth( - @Body body: EmailDto - ): EmailAuthDto + suspend fun emailAuthForPasswordReset( + @Body body: Email + ): AuthCodeWithAccessToken @Multipart @POST("/intermediaries/posts") @@ -176,7 +187,7 @@ internal interface InterApiService { suspend fun interWithdraw() @POST("/intermediaries/search/email") - suspend fun interEmailSearch( - @Body body: PhoneDto - ): EmailDto + suspend fun searchIntermediatorEmail( + @Body body: Phone + ): Email } diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/AuthDto.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/AuthDto.kt deleted file mode 100644 index 33dd3cf4d..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/AuthDto.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class AuthDto( - val authCode: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/EmailDto.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/EmailDto.kt deleted file mode 100644 index dabd831b0..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/EmailDto.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class EmailDto( - val email: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicateNicknameResponse.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicateNicknameResponse.kt deleted file mode 100644 index 287e07d7a..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicateNicknameResponse.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class IsDuplicateNicknameResponse( - val isDuplicated: Boolean -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberBody.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberBody.kt deleted file mode 100644 index 2c9411856..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberBody.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class IsDuplicatePhoneNumberBody( - val phone: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberResponse.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberResponse.kt deleted file mode 100644 index c942be00a..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberResponse.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class IsDuplicatePhoneNumberResponse( - val isDuplicated: Boolean, - val socialType: String?, - val email: String? -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/NormalLoginBody.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/NormalLoginBody.kt deleted file mode 100644 index 8678e3a27..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/NormalLoginBody.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class NormalLoginBody( - val email: String, - val password: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/PhoneDto.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/PhoneDto.kt deleted file mode 100644 index c2b160711..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/PhoneDto.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class PhoneDto( - val phone: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/SocialLoginBody.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/SocialLoginBody.kt deleted file mode 100644 index 3f7554a54..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/SocialLoginBody.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class SocialLoginBody( - val accessToken: String, - val provider: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailAuthDto.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailAuthDto.kt deleted file mode 100644 index 98a19d223..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailAuthDto.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model.volunteer - -data class EmailAuthDto( - val authCode: String, - val accessToken: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailCertificationBody.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailCertificationBody.kt deleted file mode 100644 index 3473527f6..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailCertificationBody.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model.volunteer - -data class EmailCertificationBody( - val email: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/ApiModule.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/ApiModule.kt index eab102c32..177d162c2 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/ApiModule.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/ApiModule.kt @@ -1,16 +1,15 @@ package com.kusitms.connectdog.core.data.di -import android.content.Context import android.util.Log +import com.kusitms.connectdog.core.data.BuildConfig import com.kusitms.connectdog.core.data.api.ApiService import com.kusitms.connectdog.core.data.api.InterApiService -import com.kusitms.connectdog.core.data.repository.DataStoreRepository +import com.kusitms.connectdog.domain.repository.DataStoreRepository import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import dagger.Module import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking @@ -31,12 +30,10 @@ private const val TAG = "API Module" @Module @InstallIn(SingletonComponent::class) internal object ApiModule { - private const val BASE_URL = "https://dev-api.pawwithu.site/" - @Provides fun provideNetworkInterceptor(dataStoreRepository: DataStoreRepository): Interceptor = Interceptor { chain -> val request = chain.request() - val jwt = runBlocking { dataStoreRepository.accessTokenFlow.first().toString() } + val jwt = runBlocking { dataStoreRepository.getAccessToken().first().toString() } Log.d(TAG, "AccessToken: $jwt") @@ -57,12 +54,6 @@ internal object ApiModule { } } - @Provides - @Singleton - fun provideDataStoreRepository(@ApplicationContext context: Context): DataStoreRepository { - return DataStoreRepository(context) - } - @Provides @Singleton fun provideOkhttpClient(interceptor: Interceptor): OkHttpClient { @@ -93,7 +84,7 @@ internal object ApiModule { moshi: Moshi ): ApiService { return Retrofit.Builder() - .baseUrl(BASE_URL) + .baseUrl(BuildConfig.BASE_URL) .addConverterFactory(MoshiConverterFactory.create(moshi)) .client(okHttpClient).build() .create(ApiService::class.java) @@ -106,7 +97,7 @@ internal object ApiModule { moshi: Moshi ): InterApiService { return Retrofit.Builder() - .baseUrl(BASE_URL) + .baseUrl(BuildConfig.BASE_URL) .addConverterFactory(MoshiConverterFactory.create(moshi)) .client(okHttpClient).build() .create(InterApiService::class.java) @@ -114,8 +105,5 @@ internal object ApiModule { @Provides @Singleton - fun provideJson(): Json = - Json { - ignoreUnknownKeys = true - } + fun provideJson(): Json = Json { ignoreUnknownKeys = true } } diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/DataStoreModule.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/DataStoreModule.kt new file mode 100644 index 000000000..74b651068 --- /dev/null +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/DataStoreModule.kt @@ -0,0 +1,21 @@ +package com.kusitms.connectdog.core.data.di + +import android.content.Context +import com.kusitms.connectdog.core.data.repository.DataStoreRepositoryImpl +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@InstallIn(SingletonComponent::class) +@Module +internal object DataStoreModule { + @Provides + @Singleton + fun provideDataStoreRepository(@ApplicationContext context: Context): DataStoreRepository { + return DataStoreRepositoryImpl(context) + } +} \ No newline at end of file diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/VolunteerDataModule.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/VolunteerDataModule.kt index 0d13f0ac5..a53183919 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/VolunteerDataModule.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/VolunteerDataModule.kt @@ -4,18 +4,20 @@ import com.kusitms.connectdog.core.data.api.ApiService import com.kusitms.connectdog.core.data.api.InterApiService import com.kusitms.connectdog.core.data.repository.ApplyRepository import com.kusitms.connectdog.core.data.repository.ApplyRepositoryImpl +import com.kusitms.connectdog.core.data.repository.AuthRepositoryImpl import com.kusitms.connectdog.core.data.repository.DetailRepository import com.kusitms.connectdog.core.data.repository.DetailRepositoryImpl import com.kusitms.connectdog.core.data.repository.HomeRepository import com.kusitms.connectdog.core.data.repository.HomeRepositoryImpl -import com.kusitms.connectdog.core.data.repository.LoginRepository import com.kusitms.connectdog.core.data.repository.LoginRepositoryImpl import com.kusitms.connectdog.core.data.repository.ManagementRepository import com.kusitms.connectdog.core.data.repository.ManagementRepositoryImpl import com.kusitms.connectdog.core.data.repository.MyPageRepository import com.kusitms.connectdog.core.data.repository.MyPageRepositoryImpl -import com.kusitms.connectdog.core.data.repository.SignUpRepository import com.kusitms.connectdog.core.data.repository.SignUpRepositoryImpl +import com.kusitms.connectdog.domain.repository.AuthRepository +import com.kusitms.connectdog.domain.repository.LoginRepository +import com.kusitms.connectdog.domain.repository.SignUpRepository import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -26,6 +28,24 @@ import javax.inject.Singleton @Module internal class VolunteerDataModule { + @Provides + @Singleton + fun provideLoginRepository( + apiService: ApiService, + intermediatorApi: InterApiService + ): LoginRepository { + return LoginRepositoryImpl(apiService, intermediatorApi) + } + + @Provides + @Singleton + fun provideAuthRepository( + apiService: ApiService, + intermediatorApi: InterApiService + ): AuthRepository { + return AuthRepositoryImpl(apiService, intermediatorApi) + } + @Provides @Singleton fun provideSignUpRepository( @@ -37,11 +57,11 @@ internal class VolunteerDataModule { @Provides @Singleton - fun provideLoginRepository( - apiService: ApiService, + fun provideTestRepository( + volunteerApi: ApiService, intermediatorApi: InterApiService - ): LoginRepository { - return LoginRepositoryImpl(apiService, intermediatorApi) + ): com.kusitms.connectdog.core.data.repository.SignUpRepository { + return SignUpRepositoryImpl(volunteerApi, intermediatorApi) } @Provides diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/AuthRepositoryImpl.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/AuthRepositoryImpl.kt new file mode 100644 index 000000000..07fa07699 --- /dev/null +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/AuthRepositoryImpl.kt @@ -0,0 +1,65 @@ +package com.kusitms.connectdog.core.data.repository + +import com.kusitms.connectdog.core.data.api.ApiService +import com.kusitms.connectdog.core.data.api.InterApiService +import com.kusitms.connectdog.core.model.auth.Email +import com.kusitms.connectdog.core.model.auth.Phone +import com.kusitms.connectdog.core.model.auth.AuthCodeWithAccessToken +import com.kusitms.connectdog.core.model.auth.EmailAuthCode +import com.kusitms.connectdog.core.model.auth.PhoneNumberDuplication +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject + +internal class AuthRepositoryImpl @Inject constructor( + private val volunteerApi: ApiService, + private val intermediatorApi: InterApiService +) : AuthRepository { + override suspend fun getEmailAuthCode( + email: String + ): Result = runCatching { + val body = Email(email) + return@runCatching volunteerApi.getEmailAuthCode(body) + } + + override suspend fun searchVolunteerEmail( + phone: String + ): Result = runCatching { + val body = Phone(phone = phone) + return@runCatching volunteerApi.searchVolunteerEmail(body) + } + + override suspend fun searchIntermediatorEmail( + phone: String + ): Result = runCatching { + val body = Phone(phone = phone) + return@runCatching intermediatorApi.searchIntermediatorEmail(body) + } + + override suspend fun emailAuthForVolunteerPasswordReset( + email: String + ): Result = runCatching { + val body = Email(email = email) + return@runCatching volunteerApi.volunteerPasswordSearchAuth(body) + } + + override suspend fun emailAuthForIntermediatorPasswordReset( + email: String + ): Result = runCatching { + val body = Email(email = email) + return@runCatching intermediatorApi.emailAuthForPasswordReset(body) + } + + override suspend fun getVolunteerPhoneNumberDuplication( + phone: String + ): Result = runCatching { + val body = Phone(phone = phone) + return@runCatching volunteerApi.getPhoneNumberDuplication(body) + } + + override suspend fun getIntermediatorPhoneNumberDuplication( + phone: String + ): Result = runCatching { + val body = Phone(phone = phone) + return@runCatching intermediatorApi.getPhoneNumberDuplication(body) + } +} \ No newline at end of file diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepository.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepository.kt deleted file mode 100644 index 5c29f7b87..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepository.kt +++ /dev/null @@ -1,106 +0,0 @@ -package com.kusitms.connectdog.core.data.repository - -import android.content.Context -import androidx.datastore.core.DataStore -import androidx.datastore.preferences.core.Preferences -import androidx.datastore.preferences.core.edit -import androidx.datastore.preferences.core.stringPreferencesKey -import androidx.datastore.preferences.preferencesDataStore -import com.kusitms.connectdog.core.util.AppMode -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.android.scopes.ActivityRetainedScoped -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.map -import javax.inject.Inject - -private val Context.dataStore: DataStore by preferencesDataStore(name = "TokenDataStore") - -@ActivityRetainedScoped -class DataStoreRepository @Inject constructor( - @ApplicationContext private val context: Context -) { - private object PreferenceKeys { - val accessToken = stringPreferencesKey("access_token") - val refreshToken = stringPreferencesKey("refresh_token") - val socialToken = stringPreferencesKey("social_token") - val fcmToken = stringPreferencesKey("fcm_token") - val appMode = stringPreferencesKey("app_mode") - val socialProvider = stringPreferencesKey("social_provider") - } - - suspend fun saveSocialToken(accessToken: String) { - context.dataStore.edit { preferences -> - preferences[PreferenceKeys.socialToken] = accessToken - } - } - - suspend fun saveAccessToken(accessToken: String) { - context.dataStore.edit { preferences -> - preferences[PreferenceKeys.accessToken] = accessToken - } - } - - suspend fun deleteAccessToken() { - context.dataStore.edit { preferences -> - preferences.remove(PreferenceKeys.accessToken) - } - } - - suspend fun saveRefreshToken(refreshToken: String) { - context.dataStore.edit { preferences -> - preferences[PreferenceKeys.refreshToken] = refreshToken - } - } - - suspend fun saveAppMode(appMode: AppMode) { - context.dataStore.edit { preferences -> - preferences[PreferenceKeys.appMode] = appMode.name - } - } - - suspend fun saveFcmToken(fcmToken: String) { - context.dataStore.edit { preferences -> - preferences[PreferenceKeys.fcmToken] = fcmToken - } - } - - suspend fun saveSocialProvider(provider: String) { - context.dataStore.edit { preferences -> - preferences[PreferenceKeys.socialProvider] = provider - } - } - - val accessTokenFlow: Flow = context.dataStore.data - .map { preferences -> - preferences[PreferenceKeys.accessToken] - } - - val appModeFlow: Flow = context.dataStore.data - .map { preferences -> - AppMode.valueOf(preferences[PreferenceKeys.appMode].toString()) - } - .catch { - emit(AppMode.LOGIN) - } - - val refreshTokenFlow: Flow = context.dataStore.data - .map { preferences -> - preferences[PreferenceKeys.accessToken] - } - - val fcmTokenFlow: Flow = context.dataStore.data - .map { preferences -> - preferences[PreferenceKeys.fcmToken] - } - - val socialTokenFlow: Flow = context.dataStore.data - .map { preferences -> - preferences[PreferenceKeys.socialToken] - } - - val socialProviderFlow: Flow = context.dataStore.data - .map { preferences -> - preferences[PreferenceKeys.socialProvider] - } -} diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepositoryImpl.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepositoryImpl.kt new file mode 100644 index 000000000..681a66a1b --- /dev/null +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepositoryImpl.kt @@ -0,0 +1,102 @@ +package com.kusitms.connectdog.core.data.repository + +import android.content.Context +import android.util.Log +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.preferencesDataStore +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import com.kusitms.connectdog.domain.usecase.login.AppMode +import com.kusitms.connectdog.domain.usecase.login.SocialLoginProvider +import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.map +import javax.inject.Inject + +object PreferenceKeys { + val accessToken = stringPreferencesKey("access_token") + val refreshToken = stringPreferencesKey("refresh_token") + val socialToken = stringPreferencesKey("social_token") + val fcmToken = stringPreferencesKey("fcm_token") + val appMode = stringPreferencesKey("app_mode") + val socialProvider = stringPreferencesKey("social_provider") +} + +private val Context.dataStore: DataStore by preferencesDataStore(name = "ConnectDogDataStore") + +class DataStoreRepositoryImpl @Inject constructor( + @ApplicationContext private val context: Context +) : DataStoreRepository { + override suspend fun updateAccessToken(accessToken: String) { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.accessToken] = accessToken + } + } + + override suspend fun updateRefreshToken(refreshToken: String) { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.accessToken] = refreshToken + } + } + + override suspend fun updateAppMode(appMode: AppMode) { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.appMode] = appMode.toString() + } + } + + override suspend fun updateFcmToken(fcmToken: String) { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.fcmToken] = fcmToken + } + } + + override suspend fun updateSocialToken(token: String) { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.socialToken] = token + } + } + + override suspend fun updateSocialLoginProvider(provider: SocialLoginProvider) { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.socialProvider] = provider.toString() + } + } + + override suspend fun getFcmToken(): Flow = context.dataStore.data.map { preferences -> + preferences[PreferenceKeys.fcmToken] + } + + override suspend fun getRefreshToken(): Flow = context.dataStore.data.map { preferences -> + preferences[PreferenceKeys.refreshToken] + } + + override suspend fun getAccessToken(): Flow = context.dataStore.data.map { preferences -> + preferences[PreferenceKeys.accessToken] + } + + override suspend fun getAppMode(): Flow = context.dataStore.data + .map { preferences -> + AppMode.valueOf(preferences[PreferenceKeys.appMode].toString()) + } + .catch { + emit(AppMode.LOGIN) + } + + override suspend fun getSocialToken(): Flow = context.dataStore.data.map { preferences -> + preferences[PreferenceKeys.socialToken] + } + + override suspend fun getSocialLoginProvider(): Flow { + TODO("Not yet implemented") + } + + override suspend fun deleteAccessToken() { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.fcmToken] = "" + } + } +} \ No newline at end of file diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepository.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepository.kt deleted file mode 100644 index 13a7416c6..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepository.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.kusitms.connectdog.core.data.repository - -import com.kusitms.connectdog.core.data.api.model.EmailDto -import com.kusitms.connectdog.core.data.api.model.LoginResponseItem -import com.kusitms.connectdog.core.data.api.model.NormalLoginBody -import com.kusitms.connectdog.core.data.api.model.SocialLoginBody -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailAuthDto - -interface LoginRepository { - suspend fun postLoginData( - loginBody: NormalLoginBody - ): LoginResponseItem - - suspend fun postSocialLoginData( - socialLoginBody: SocialLoginBody - ): LoginResponseItem - - suspend fun postIntermediatorLoginData( - loginBody: NormalLoginBody - ): LoginResponseItem - - suspend fun volunteerEmailSearch(phone: String): EmailDto - - suspend fun interEmailSearch(phone: String): EmailDto - - suspend fun volunteerPasswordSearchAuth(email: String): EmailAuthDto - - suspend fun interPasswordSearchAuth(email: String): EmailAuthDto - - suspend fun logout() -} diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepositoryImpl.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepositoryImpl.kt index c32491a3c..6be9774d5 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepositoryImpl.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepositoryImpl.kt @@ -2,59 +2,41 @@ package com.kusitms.connectdog.core.data.repository import com.kusitms.connectdog.core.data.api.ApiService import com.kusitms.connectdog.core.data.api.InterApiService -import com.kusitms.connectdog.core.data.api.model.EmailDto -import com.kusitms.connectdog.core.data.api.model.LoginResponseItem -import com.kusitms.connectdog.core.data.api.model.NormalLoginBody -import com.kusitms.connectdog.core.data.api.model.PhoneDto -import com.kusitms.connectdog.core.data.api.model.SocialLoginBody -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailAuthDto +import com.kusitms.connectdog.core.model.login.LoginResult +import com.kusitms.connectdog.core.model.login.NormalLogin +import com.kusitms.connectdog.core.model.login.SocialLogin +import com.kusitms.connectdog.domain.repository.LoginRepository import javax.inject.Inject internal class LoginRepositoryImpl @Inject constructor( - private val api: ApiService, - private val interApi: InterApiService + private val volunteerApi: ApiService, + private val intermediatorApi: InterApiService ) : LoginRepository { - override suspend fun postLoginData( - loginBody: NormalLoginBody - ): LoginResponseItem { - return api.postLoginData( - loginBody - ) + override suspend fun volunteerNormalLogin( + email: String, + password: String + ): Result = runCatching { + val body = NormalLogin(email, password) + return@runCatching volunteerApi.normalLogin(body) } - override suspend fun postSocialLoginData( - socialLoginBody: SocialLoginBody - ): LoginResponseItem { - return api.postSocialLoginData( - socialLoginBody - ) + override suspend fun intermediatorNormalLogin( + email: String, + password: String + ): Result = runCatching { + val body = NormalLogin(email, password) + return@runCatching intermediatorApi.normalLogin(body) } - override suspend fun postIntermediatorLoginData(loginBody: NormalLoginBody): LoginResponseItem { - return api.postIntermediatorLoginData(loginBody) + override suspend fun socialLogin( + accessToken: String, + provider: String + ): Result = runCatching{ + val body = SocialLogin(accessToken, provider) + return@runCatching volunteerApi.postSocialLoginData(body) } - override suspend fun volunteerEmailSearch(phone: String): EmailDto { - val body = PhoneDto(phone = phone) - return api.volunteerEmailSearch(body) - } - - override suspend fun interEmailSearch(phone: String): EmailDto { - val body = PhoneDto(phone = phone) - return interApi.interEmailSearch(body) - } - - override suspend fun volunteerPasswordSearchAuth(email: String): EmailAuthDto { - val body = EmailDto(email = email) - return api.volunteerPasswordSearchAuth(body) - } - - override suspend fun interPasswordSearchAuth(email: String): EmailAuthDto { - val body = EmailDto(email = email) - return interApi.interPasswordSearchAuth(body) - } - - override suspend fun logout() { - return api.logout() + override suspend fun logout() = runCatching { + return@runCatching volunteerApi.logout() } } diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepository.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepository.kt index 424bfc5f9..ea986c287 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepository.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepository.kt @@ -1,20 +1,20 @@ package com.kusitms.connectdog.core.data.repository -import com.kusitms.connectdog.core.data.api.model.IsDuplicateNicknameResponse import com.kusitms.connectdog.core.data.api.model.MyInfoResponseItem import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorAccountInfo import com.kusitms.connectdog.core.data.api.model.volunteer.BadgeResponse import com.kusitms.connectdog.core.data.api.model.volunteer.BookmarkResponseItem -import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody import com.kusitms.connectdog.core.data.api.model.volunteer.UserInfoResponse import com.kusitms.connectdog.core.data.api.model.volunteer.VolunteerAccountInfo +import com.kusitms.connectdog.core.model.signup.IsDuplicated +import com.kusitms.connectdog.core.model.signup.Nickname interface MyPageRepository { suspend fun getMyInfo(): MyInfoResponseItem suspend fun getUserInfo(): UserInfoResponse suspend fun getBadge(): List suspend fun getBookmarkData(): List - suspend fun postNickname(nickname: IsDuplicateNicknameBody): IsDuplicateNicknameResponse + suspend fun postNickname(nickname: Nickname): IsDuplicated suspend fun updateUserInfo(userInfo: UserInfoResponse) suspend fun updateNotification() suspend fun getVolunteerAccountInfo(): VolunteerAccountInfo diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepositoryImpl.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepositoryImpl.kt index 0c11391ac..57d033f1e 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepositoryImpl.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepositoryImpl.kt @@ -2,14 +2,14 @@ package com.kusitms.connectdog.core.data.repository import com.kusitms.connectdog.core.data.api.ApiService import com.kusitms.connectdog.core.data.api.InterApiService -import com.kusitms.connectdog.core.data.api.model.IsDuplicateNicknameResponse import com.kusitms.connectdog.core.data.api.model.MyInfoResponseItem import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorAccountInfo import com.kusitms.connectdog.core.data.api.model.volunteer.BadgeResponse import com.kusitms.connectdog.core.data.api.model.volunteer.BookmarkResponseItem -import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody import com.kusitms.connectdog.core.data.api.model.volunteer.UserInfoResponse import com.kusitms.connectdog.core.data.api.model.volunteer.VolunteerAccountInfo +import com.kusitms.connectdog.core.model.signup.IsDuplicated +import com.kusitms.connectdog.core.model.signup.Nickname import javax.inject.Inject internal class MyPageRepositoryImpl @Inject constructor( @@ -32,7 +32,7 @@ internal class MyPageRepositoryImpl @Inject constructor( return api.getBookmarkData() } - override suspend fun postNickname(nickname: IsDuplicateNicknameBody): IsDuplicateNicknameResponse { + override suspend fun postNickname(nickname: Nickname): IsDuplicated { return api.postNickname(nickname) } diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepository.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepository.kt index f7cad69a1..aa05293e5 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepository.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepository.kt @@ -1,28 +1,8 @@ package com.kusitms.connectdog.core.data.repository -import com.kusitms.connectdog.core.data.api.model.AuthDto -import com.kusitms.connectdog.core.data.api.model.IsDuplicateNicknameResponse -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberBody -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberResponse -import com.kusitms.connectdog.core.data.api.model.intermediator.DuplicateDto -import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorSignUpBody -import com.kusitms.connectdog.core.data.api.model.intermediator.NameDto -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailCertificationBody -import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody -import com.kusitms.connectdog.core.data.api.model.volunteer.NormalVolunteerSignUpBody import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordCheckResponse -import com.kusitms.connectdog.core.data.api.model.volunteer.SocialVolunteerSignUpBody -import java.io.File interface SignUpRepository { - suspend fun postNickname(nickname: IsDuplicateNicknameBody): IsDuplicateNicknameResponse - suspend fun postEmail(email: EmailCertificationBody): AuthDto - suspend fun postNormalVolunteerSignUp(signUp: NormalVolunteerSignUpBody) - suspend fun postSocialVolunteerSignUp(signUp: SocialVolunteerSignUpBody) - suspend fun postIntermediatorSignUp(signUp: IntermediatorSignUpBody, file: File) - suspend fun getVolunteerPhoneNumberDuplicated(body: IsDuplicatePhoneNumberBody): IsDuplicatePhoneNumberResponse - suspend fun getInterMediatorPhoneNumberDuplicated(body: IsDuplicatePhoneNumberBody): IsDuplicatePhoneNumberResponse - suspend fun isDuplicateInterNickName(body: NameDto): DuplicateDto suspend fun checkVolunteerPassword(password: String): PasswordCheckResponse suspend fun checkInterPassword(password: String): PasswordCheckResponse suspend fun changeVolunteerPassword(password: String) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepositoryImpl.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepositoryImpl.kt index 7d86c8b93..fdf8e5201 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepositoryImpl.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepositoryImpl.kt @@ -1,89 +1,125 @@ package com.kusitms.connectdog.core.data.repository -import com.google.gson.Gson import com.kusitms.connectdog.core.data.api.ApiService import com.kusitms.connectdog.core.data.api.InterApiService -import com.kusitms.connectdog.core.data.api.model.AuthDto -import com.kusitms.connectdog.core.data.api.model.IsDuplicateNicknameResponse -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberBody -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberResponse -import com.kusitms.connectdog.core.data.api.model.intermediator.DuplicateDto -import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorSignUpBody -import com.kusitms.connectdog.core.data.api.model.intermediator.NameDto -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailCertificationBody -import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody -import com.kusitms.connectdog.core.data.api.model.volunteer.NormalVolunteerSignUpBody import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordCheckResponse -import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordDto -import com.kusitms.connectdog.core.data.api.model.volunteer.SocialVolunteerSignUpBody -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import java.io.File +import com.kusitms.connectdog.core.model.signup.IsDuplicated +import com.kusitms.connectdog.core.model.signup.Name +import com.kusitms.connectdog.core.model.signup.Nickname +import com.kusitms.connectdog.core.model.signup.NormalVolunteerDetail +import com.kusitms.connectdog.core.model.signup.SocialVolunteerDetail +import com.kusitms.connectdog.domain.repository.SignUpRepository import javax.inject.Inject internal class SignUpRepositoryImpl @Inject constructor( private val volunteerApi: ApiService, private val intermediatorApi: InterApiService -) : SignUpRepository { - override suspend fun postNickname(nickname: IsDuplicateNicknameBody): IsDuplicateNicknameResponse { - return volunteerApi.postNickname(nickname) +) : SignUpRepository, com.kusitms.connectdog.core.data.repository.SignUpRepository { + override suspend fun getVolunteerNicknameDuplication( + nickname: String + ): Result = runCatching { + val body = Nickname(nickname) + return@runCatching volunteerApi.postNickname(body) } - override suspend fun postEmail(email: EmailCertificationBody): AuthDto { - return volunteerApi.postEmail(email) + override suspend fun getIntermediatorNicknameDuplication( + name: String + ): Result = runCatching { + val body = Name(name) + return@runCatching intermediatorApi.checkIsDuplicateName(body) } - override suspend fun postNormalVolunteerSignUp(signUp: NormalVolunteerSignUpBody) { - volunteerApi.postNormalVolunteerSignUp(signUp) - } - - override suspend fun postSocialVolunteerSignUp(signUp: SocialVolunteerSignUpBody) { - return volunteerApi.postSocialVolunteerSignUp(signUp) - } - - override suspend fun postIntermediatorSignUp(signUp: IntermediatorSignUpBody, image: File) { - val jsonBody = RequestBody.create( - "application/json; charset=utf-8".toMediaTypeOrNull(), - Gson().toJson(signUp) + override suspend fun initNormalVolunteerSignUp( + email: String, + password: String, + nickname: String, + profileImageNum: Int, + isOptionAgr: Boolean, + phone: String, + name: String + ): Result = runCatching { + val body = NormalVolunteerDetail( + email = email, + password = password, + nickname = nickname, + profileImageNum = profileImageNum, + isOptionAgr = isOptionAgr, + phone = phone, + name = name ) - - val fileBody = RequestBody.create("multipart/form-data".toMediaTypeOrNull(), image) - - val file = MultipartBody.Part.createFormData("profileImage", image.name, fileBody) - - return intermediatorApi.intermediatorSignUp(jsonBody, file) - } - - override suspend fun getVolunteerPhoneNumberDuplicated(body: IsDuplicatePhoneNumberBody): IsDuplicatePhoneNumberResponse { - return volunteerApi.getIsDuplicatePhoneNumber(body) + volunteerApi.postNormalVolunteerSignUp(body) } - override suspend fun getInterMediatorPhoneNumberDuplicated(body: IsDuplicatePhoneNumberBody): IsDuplicatePhoneNumberResponse { - return intermediatorApi.getIsDuplicatePhoneNumber(body) + override suspend fun initSocialVolunteerSignUp( + nickname: String, + profileImageNum: Int, + isOptionAgr: Boolean, + phone: String, + name: String + ): Result = runCatching { + val body = SocialVolunteerDetail( + nickname = nickname, + profileImageNum = profileImageNum, + isOptionAgr = isOptionAgr, + phone = phone, + name = name + ) + return@runCatching volunteerApi.postSocialVolunteerSignUp(body) } - override suspend fun isDuplicateInterNickName(body: NameDto): DuplicateDto { - return intermediatorApi.checkIsDuplicateName(body) - } +// override suspend fun postIntermediatorSignUp(signUp: IntermediatorSignUpBody, image: File) { +// val jsonBody = RequestBody.create( +// "application/json; charset=utf-8".toMediaTypeOrNull(), +// Gson().toJson(signUp) +// ) +// +// val fileBody = RequestBody.create("multipart/form-data".toMediaTypeOrNull(), image) +// val file = MultipartBody.Part.createFormData("profileImage", image.name, fileBody) +// +// return intermediatorApi.intermediatorSignUp(jsonBody, file) +// } +// +// override suspend fun getVolunteerPhoneNumberDuplicated(body: IsDuplicatePhoneNumberBody): IsDuplicatePhoneNumberResponse { +// return volunteerApi.getIsDuplicatePhoneNumber(body) +// } +// +// override suspend fun getInterMediatorPhoneNumberDuplicated(body: IsDuplicatePhoneNumberBody): IsDuplicatePhoneNumberResponse { +// return intermediatorApi.getIsDuplicatePhoneNumber(body) +// } +// +// override suspend fun checkVolunteerPassword(password: String): PasswordCheckResponse { +// val body = PasswordDto(password) +// return volunteerApi.checkVolunteerPassword(body) +// } +// +// override suspend fun checkInterPassword(password: String): PasswordCheckResponse { +// val body = PasswordDto(password) +// return intermediatorApi.checkInterPassword(body) +// } +// +// override suspend fun changeVolunteerPassword(password: String) { +// val body = PasswordDto(password) +// volunteerApi.changeVolunteerPassword(body) +// } +// +// override suspend fun changeInterPassword(password: String) { +// val body = PasswordDto(password) +// intermediatorApi.changeInterPassword(body) +// } override suspend fun checkVolunteerPassword(password: String): PasswordCheckResponse { - val body = PasswordDto(password) - return volunteerApi.checkVolunteerPassword(body) + TODO("Not yet implemented") } override suspend fun checkInterPassword(password: String): PasswordCheckResponse { - val body = PasswordDto(password) - return intermediatorApi.checkInterPassword(body) + TODO("Not yet implemented") } override suspend fun changeVolunteerPassword(password: String) { - val body = PasswordDto(password) - volunteerApi.changeVolunteerPassword(body) + TODO("Not yet implemented") } override suspend fun changeInterPassword(password: String) { - val body = PasswordDto(password) - intermediatorApi.changeInterPassword(body) + TODO("Not yet implemented") } } diff --git a/core/designsystem/build/generated/source/buildConfig/debug/com/kusitms/connectdog/core/designsystem/BuildConfig.java b/core/designsystem/build/generated/source/buildConfig/debug/com/kusitms/connectdog/core/designsystem/BuildConfig.java new file mode 100644 index 000000000..5fb8a9d0e --- /dev/null +++ b/core/designsystem/build/generated/source/buildConfig/debug/com/kusitms/connectdog/core/designsystem/BuildConfig.java @@ -0,0 +1,10 @@ +/** + * Automatically generated file. DO NOT MODIFY + */ +package com.kusitms.connectdog.core.designsystem; + +public final class BuildConfig { + public static final boolean DEBUG = Boolean.parseBoolean("true"); + public static final String LIBRARY_PACKAGE_NAME = "com.kusitms.connectdog.core.designsystem"; + public static final String BUILD_TYPE = "debug"; +} diff --git a/core/designsystem/build/generated/source/buildConfig/release/com/kusitms/connectdog/core/designsystem/BuildConfig.java b/core/designsystem/build/generated/source/buildConfig/release/com/kusitms/connectdog/core/designsystem/BuildConfig.java new file mode 100644 index 000000000..37f0ec558 --- /dev/null +++ b/core/designsystem/build/generated/source/buildConfig/release/com/kusitms/connectdog/core/designsystem/BuildConfig.java @@ -0,0 +1,10 @@ +/** + * Automatically generated file. DO NOT MODIFY + */ +package com.kusitms.connectdog.core.designsystem; + +public final class BuildConfig { + public static final boolean DEBUG = false; + public static final String LIBRARY_PACKAGE_NAME = "com.kusitms.connectdog.core.designsystem"; + public static final String BUILD_TYPE = "release"; +} diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/ActionRow.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/ActionRow.kt new file mode 100644 index 000000000..932f80cae --- /dev/null +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/ActionRow.kt @@ -0,0 +1,40 @@ +package com.kusitms.connectdog.core.designsystem.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.kusitms.connectdog.core.designsystem.theme.Gray2 + +@Composable +fun ActionRow( + vararg items: Pair Unit> +) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + items.forEachIndexed { index, item -> + Text( + modifier = Modifier.clickable { item.second() }, + text = item.first, + fontSize = 12.sp, + color = Gray2 + ) + if (index != items.lastIndex) { + Text( + modifier = Modifier.padding(horizontal = 16.dp), + text = "|", + fontSize = 12.sp, + color = Gray2 + ) + } + } + } +} \ No newline at end of file diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Banner.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Banner.kt index 6ae0bed2f..bf02d0901 100644 --- a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Banner.kt +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Banner.kt @@ -2,6 +2,7 @@ package com.kusitms.connectdog.core.designsystem.component import android.widget.Toast import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row @@ -14,6 +15,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource @@ -24,6 +26,7 @@ import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.kusitms.connectdog.core.designsystem.R +import com.kusitms.connectdog.core.designsystem.theme.Gray5 import com.kusitms.connectdog.core.designsystem.theme.PetOrange @Composable @@ -34,8 +37,11 @@ fun BannerGuideline( Row( modifier = Modifier + .padding(horizontal = 20.dp) + .padding(vertical = 12.dp) .fillMaxWidth() .defaultMinSize(minHeight = 84.dp) + .clip(RoundedCornerShape(12.dp)) .background(MaterialTheme.colorScheme.primary) .padding(horizontal = 20.dp), verticalAlignment = Alignment.CenterVertically, diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/CheckBox.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/CheckBox.kt new file mode 100644 index 000000000..aa46874d0 --- /dev/null +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/CheckBox.kt @@ -0,0 +1,78 @@ +package com.kusitms.connectdog.core.designsystem.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.kusitms.connectdog.core.designsystem.R +import com.kusitms.connectdog.core.designsystem.theme.Gray1 +import com.kusitms.connectdog.core.designsystem.theme.Gray2 +import com.kusitms.connectdog.core.designsystem.theme.Gray4 +import com.kusitms.connectdog.core.designsystem.theme.PetOrange + +@Composable +fun CheckBox( + text: String, + checked: Boolean, + onClick: () -> Unit, + hasDetail: Boolean, + onDetailClick: () -> Unit = {} +) { + var isChecked by remember { mutableStateOf(checked) } + if (checked != isChecked) isChecked = checked + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp) + .clickable { + onClick() + isChecked = !isChecked + }, + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + painter = painterResource(id = R.drawable.ic_checked), + contentDescription = null, + tint = if (isChecked) PetOrange else Gray4, + modifier = Modifier.size(24.dp) + ) + Spacer(modifier = Modifier.width(12.dp)) + Text( + text = text, + fontSize = 14.sp, + fontWeight = FontWeight.Medium, + color = if (isChecked) Color.Black else Gray2 + ) + Spacer(modifier = Modifier.weight(1f)) + if (hasDetail) { + Text( + modifier = Modifier.clickable { onDetailClick() }, + text = "보기", + style = TextStyle(textDecoration = TextDecoration.Underline), + fontSize = 14.sp, + fontWeight = FontWeight.Medium, + color = if (isChecked) Gray1 else Gray2, + ) + } + } +} diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Line.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Line.kt new file mode 100644 index 000000000..981fa6d84 --- /dev/null +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Line.kt @@ -0,0 +1,31 @@ +package com.kusitms.connectdog.core.designsystem.component + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp + +@Composable +fun HorizontalLine( + height: Int, + color: Color +) { + Canvas( + modifier = Modifier + .fillMaxWidth() + .height(height.dp) + .padding(horizontal = 20.dp) + ) { + drawLine( + color = color, + start = Offset(0f, 0f), + end = Offset(size.width, 0f), + strokeWidth = 1f + ) + } +} \ No newline at end of file diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/SearchBar.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/SearchBar.kt new file mode 100644 index 000000000..d886bf4df --- /dev/null +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/SearchBar.kt @@ -0,0 +1,82 @@ +package com.kusitms.connectdog.core.designsystem.component + +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.kusitms.connectdog.core.designsystem.R +import com.kusitms.connectdog.core.designsystem.theme.Gray1 +import com.kusitms.connectdog.core.designsystem.theme.Gray3 +import com.kusitms.connectdog.core.designsystem.theme.Gray5 + +@Composable +fun SearchBar( + onClick: () -> Unit, +) { + Row( + modifier = Modifier + .padding(horizontal = 20.dp) + .padding(vertical = 12.dp) + .fillMaxWidth() + .border( + width = 1.dp, + color = Gray5, + shape = RoundedCornerShape(90.dp) + ) + .clickable { onClick() }, + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier + .padding(start = 20.dp) + .size(24.dp), + imageVector = Icons.Filled.Search, + tint = Gray3, + contentDescription = "Navigate to Search" + ) + Spacer(modifier = Modifier.width(5.dp)) + Text( + modifier = Modifier.padding(vertical = 10.dp), + text = buildAnnotatedString { + withStyle( + SpanStyle( + color = Gray1, + fontSize = 12.sp, + fontWeight = FontWeight.Medium + ) + ) { + append(stringResource(id = R.string.search_bar_title)) + } + withStyle( + SpanStyle( + color = Gray3, + fontSize = 10.sp, + fontWeight = FontWeight.Medium + ) + ) { + append(stringResource(id = R.string.search_bar_subtitle)) + } + }, + lineHeight = 15.sp + ) + } +} \ No newline at end of file diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/TopAppBar.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/TopAppBar.kt index 02a86c0e2..1f39a61cd 100644 --- a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/TopAppBar.kt +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/TopAppBar.kt @@ -100,9 +100,11 @@ fun ConnectDogTopAppBar( } } - Row(modifier = Modifier.align(Alignment.CenterEnd)) { - actionButtons() - } + Row( + modifier = Modifier.align(Alignment.CenterEnd), + content = { actionButtons() } + ) + if (titleRes != null) { Text( text = stringResource(id = titleRes), diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/theme/Color.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/theme/Color.kt index 4898a1844..8e3ef6fc8 100644 --- a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/theme/Color.kt +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/theme/Color.kt @@ -23,6 +23,9 @@ val Gray7 = Color(0xFFF5F5F5) val Gray8 = Color(0xFFFAFAFA) val Gray9 = Color(0xFFAEAEAE) val Gray10 = Color(0xFF969696) +val Gray60 = Color(0XFF878787) +val Gray80 = Color(0XFF5F5F5F) +val Gray100 = Color(0XFF242424) val Brown1 = Color(0xFF5B3816) val Brown1_5 = Color(0xFFDDD7D1) diff --git a/core/designsystem/src/main/res/values/strings.xml b/core/designsystem/src/main/res/values/strings.xml index f7c58638a..b81cdcf97 100644 --- a/core/designsystem/src/main/res/values/strings.xml +++ b/core/designsystem/src/main/res/values/strings.xml @@ -1,7 +1,5 @@ - 227799f94d3661c7d84b79daba3b0eaa - 일정 모집자명 @@ -55,4 +53,8 @@ 봉사 건을 완료 처리 하시겠습니까? 봉사가 모두 종료되었나요?\n완료 처리 시 봉사자에게도\n완료 푸시 알림이 전송됩니다. 완료 + + + 딱 맞는 이동봉사를 찾아보세요!\n + 출발지·도착지·일정 \ No newline at end of file diff --git a/core/model/build.gradle.kts b/core/model/build.gradle.kts index 35f9740d4..1d739c52b 100644 --- a/core/model/build.gradle.kts +++ b/core/model/build.gradle.kts @@ -1,24 +1,10 @@ -import com.kusitms.connectdog.Configuration - @Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed plugins { - alias(libs.plugins.com.android.library) - alias(libs.plugins.org.jetbrains.kotlin.android) - alias(libs.plugins.ktlint) + id("java-library") + alias(libs.plugins.org.jetbrains.kotlin.jvm) } -android { - namespace = "com.kusitms.connectdog.core.model" - compileSdk = Configuration.compileSdk - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = "1.8" - } -} - -dependencies { -} +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} \ No newline at end of file diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome$Companion.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome$Companion.class new file mode 100644 index 0000000000000000000000000000000000000000..c8faa722665b4618ea25b04b21aa5d920fbe2068 GIT binary patch literal 1340 zcmbtTOHUI~6#nk?$x!G^k%tcy#1^Fk)ff{ViPjiv3MOKj5TfSNjyQDYj+wb_ToPkU zT)AG(#)6~e5@s=G|4XBv)MHErXv5N=&mOve=Ry6c$31=o4Vh2@F}7(-%(H@IPQv25I2 zS|NA@0fz9DB`i6^5XfZ9F@zA-5k!O`C?8lp!%XRa4xVI)*e>OxwMSriS+we62jUq~fW>C|D3RB{8oA1K_S8X=$}38IT= zy9p8}q6E<-DUu>DMl$`!QR((k2I162x}a7kgg&y>v16n)((2Cr>drK7Bzs!HHki^F zz){KtFiu&02NcIB(M*u9;Vkl`rzw7nYL71>P{fHM28%d}Q)FVOh+&*w1oJV1Gm8lO P(0wF)Wpw(;_{jbQSm zcvw%w=To_%jKOo+`N>=+I~LE*=-Ei?H3d#2+|V(_;M#*R42%-~=srH8Ac<)g9GDSP zQa{@eZ>3Xyr~LJq9Q?9&qM^sp#d=x8)-P$1u@mB|>z%4Z4MWckrQ)3HT>Noe8j(JIsQHoodzpO|ykwI3t|4n@}x(MdHNSQgvv>ug16o)B9V7d&Gu zFK%irdHB(RGiCra5vFiPtF!F`j&G3RzzSW>9)U`%(pA|FKpWcWuDHG*owlHcQjoI< zlyKUT!nUNwQc_hB$sW{&Zfba0yix)a`&*H0^8DzrEgC8!bUTEoKYt*fb zD#hbbRh9Z4EU4}Cg+u#l*V~LF!+2qm621wl^3B&o%-_ECyvfucOY#nmNN{MHqG^`; z0eX9YTmfcUaonMzdGbo;c}|xe-G}6qzVyqnJaMOzI{l eoFrT9_#^e?k8_N3400qn9^fg_Wujl9|L{NVA-#$K delta 1126 zcma)5O=}ZT6g_X!W?qw-&PQal4jMIWgAF#-idCZvqnlVt1;H*7C}KbSs@A?#t1jwB zU04vg=%1(yMOPw0T^8K4GsOR_V1dDpsgscZxuI|d{&kCk zQ=zjC|8rJb^F(8%DN0$czuN{5PS=-k#q#EM-?!W3OsJTn|0m`wa)_{Jx2!z7)wHL~ zR`S5PL$qP{v3uXyOM4&kLnNX`JZ_pMuQgwnx!=jAn=%iExLIJj_H0^qN<8VOlVZ+o z=eZYfT9CT@jXgRv%Q7sB-L&EQv#Wfi2hJ~X62T)rH7sL|<14P-;QwZ>h)4nR1uPV> zh?|_^RspwhrwE~N7fVGPQphOWQ;^luR&W)La8BnEIiKs-6{Z#P3it7tsU=fS@^|SE D-8O)i diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.class new file mode 100644 index 0000000000000000000000000000000000000000..426b4ae61e73b26a13a91d64361108c55bad727e GIT binary patch literal 3050 zcmbtW-E$LF6#w1L*EUJpZJ^&23RG#6$d;mjwjiZ~4W)SmcfFo+s^9bPR-a7!|}XZUp3b(xl-r0 zBTVi%uH@2oNuGD*e4|pCWY85M#YKnCaJcNsitU(d>s8Zsq*Zr##mqU%jj#(MhB!la zp=1@x0m5}&=T(agw=wgn@5(HRB--Ohpo1a7x1!f!FoZ_OmXe4d6-O8c7*ac9OF~C? z8#MGJVfa!XLs*t=j_Uku^qd2C5 zIzby&y8gCjnAj}SwsSPPxu?&w>~PBtJI}^+q!~uGPLS=a)5$Y^#2MEqaCwCnq+7om zLzbbp%FC9oRz64)k~@+%+PAIc3{d7QS#pcB+$mNpF_L%Pa-+7(5ok%!D+?Fz)~sF3 zms{+c3EdIF46jrcY-vp|?$T(_!)!-FMT6Zg#%~)-~70c^Y zb?dT%+Oyd-v6Gm_CDm+Z7$UALsYcb>QvySVu6)q?sEEACB`1Gcbv;D!GxgHd3kH{*gf`ADb*G|+ zHlU4%Xbh|I#lxs(M6R|OZE80A@_vZqcvBuS5+u`NUDy1Dp5!ehV|Mj`ktBom3Ek)z z2=}pZHv95{g6JfzK{6w`%ZGcwZge%B>O^=TtVfL)DLqESBv9%`?8T4KlnRsj7zH2k z?l6Xd*Brc)Wok2nHyVz#t5(igw}nlWo8G#3s2i%ghM_ZWJJx)ox?mSKt(N znJ^VsLrUE<6!a%Fi_#dQF{N&tZMwKh3|VMcA`6Q~wK)beskUe6%%-~Noqmdg>C9vF zrn8UH|1*8oaMObe(`6VU&@jP9FhKIBq#yPnXg)|Y0t=`pNfFR+i?r=pz{=;=g+mw$ zSeW#MDuzh<7xex_g6~g-0rI7MBz=RxM{AH>IJ_%R|8}6roRhsli9|$q&AV%ye{OivGwdx4i){ z{ilTjQ8CqMREa#B&isH#_)+E$Xx}3edX(9KHm5vf>3N0^Jf-qN^Zw0wSUJ<6qD>$i z)Bnc77_?4r7bx$9+f4mgT*ejRp^_X^JNY6BAuQ8d!y-PTu}InvDaEtP2<4E=;c5;a zAx|Raa+t@pWiWy3_;?uy1O^3e2kCa{3d M$&*f=Cg{oh3!Y)OlK=n! literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/Email.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Email.class similarity index 76% rename from core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/Email.class rename to core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Email.class index 6fff8624496fa8d4cf10d0f65f8da0c0274b0e96..ede7fbecd26a879cd684eb910852181564bc9882 100644 GIT binary patch delta 87 zcmZn>{x8IP>ff$?3=9mm3}K86I+Ohwl~@u>OENZ^NHQ|&P4;6{26HEuG1@aaP2R?6 Z4&i=cRAOq@KuFs$1%M?sPiFea1^}268$|#B delta 92 zcmew_)FRA#>ff$?3=9mm3}K86x|97Fl~{A~(=+on8cQ-V>QDA%REF>;moVBhI#1rh aXb$DSXH;Tp)j(2U#S{RM+T6$VkqrPbs~tW7 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/EmailAuthCode.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/EmailAuthCode.class new file mode 100644 index 0000000000000000000000000000000000000000..83d28a418031aac0f1d5c84c82ffe8c596ea678b GIT binary patch literal 2496 zcmbVO-BTM?6#w1bd@M^K3kCVARSQBsYByl5AGB3KkYJz{5J!1%F3Ac@HoGxHI_jejjt@N48Erdt#zFe#-{d%+n_WUE89T#Fvgh8j=lst3oqNwo{{Hvrp8#%S zgW*QetC;1wZ;Og=7CqOsilXFg)3Ron6|ZDDCa;SfbH2iDXNFdDq>FsBTi!(17u*$e%HOxvJVaTx#Ew^51cRpm^#pCtPQRs8?Dom!o5IaZ_H zYu3DkdSSmdu@iU~@5z28_oyd!WUsgOX=upMQwXOAof0o`!O20X?5RYV$%iH%U|?m^ ze`CvCj#edVv%{lMX{^YJ%aAPCuC-FHY+1E+c|fwTUXeQ+yk^UNs2qD9t2uSgfOf43UMw&3YUrk~ zdG%V+TCgSXP>8Y7CL3ec^Mo&Iyc+bEk4b9yNaL`2<@hD4%e0G;jFZ$Pb=oOdpXS*wskK1uQ(>0SzaNDk1Byu&!3&^k_cq!FkG zgBT)18O9_X6&=ycZ|HwWivU~Z1j3b=iNGMlY|Xd_!%d*k=YiM@ooNJ8+A@o`NlLQG zfb1VoKF>bJ6`4-}6Yxqlc_rJ_ua%?GfmiSXd$YJ&`C_f^q9%hfAEX!1`(f0{%HIxwvsX*qhLyc?ypf65)d1gVqCYtq{ zpnpquD6wXZ-XS9uYYl(`)=6&C>-Xsbey|BOkC{AX^O(bjw8VTK3;2i(d@Lfr3B$*L pk0l>k;~DcY=wryou#XWRHyg^^K5~u4sE?2FDFu-C`x<>;{}1k4L#6-# literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Phone.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Phone.class new file mode 100644 index 0000000000000000000000000000000000000000..6e7d6ee1ff4234d687eda6064131ee69fdc1d9cb GIT binary patch literal 2431 zcmb7G-A^1<6#w0s{TPOY9Vp0Gty&Nk78yXTACzjrB8v+}K#cNWF1sT;?Ci|CbC<}A zAu;Kn(5R0-7$11hMBAn&2I-rBlQEt_X1VU$qT-tc&vmVWD0+LO)-1E)6)nf)bx|_cOP*^b!5EBve!xwKyL;x{-FmMD*=~pM*}y3MH#hj>6Y@jaMvkWEg8MBCK+* zRaq&d(4nIpoeXMbd^?3W3>`6aF?3%HNI}DuHYn&}h>4QzGfd?#Lm+ji?O7rqlc6Uw zelZ7wPKZ@v!4)%OAX9vu754^HvhTe;wTi{}e7lclnjCI)N<1Xmg>Boj;3@Ofu}XZkp;TqOZh#>a}PE zhdOs|WJC8PW>c8PjE>jw1`V(ERh>J;%DLfvTI}b<`2P(rO)lScEP1wh&AKC@o;!gJ z>=fR?yK(~M@Oz>pr?+|XB1eX{HSFRWu>Ex(sO6WvpM&>p$>$95CJ{ap~(`@<4eU$=JWbGiGk=_}C+-DnI z4S0=88jNXiBXRn3A}wp4WwMiaaQzai!3a#1X;6nY>aMUWR?a=JeVa(XeRhk|T@mhi zI&ZtyTD`Js)wbluNJ6~=ceZ)Wmg~qk@+?;4{yYcTu_<_=yvnOln7--NYXxh`mcRoM z#&(Npj0MjVzNqnPI9EPqXu4y;CUwh;lv-S+Rf1%aq$XRYm4Y=|X5n}WOa?u1I-D&%#YCb>?w7s42leYB$JD9^{FC+TbiiMr5_0dkaSOtKN# zh)?{6-d{)wv1LslT#1s@8L!} znW!CIdOs$ba8^u6h~9z_ChwF+){xmC-vhjP+-N3@*P?ia8`OWe8()x=gF7~n{R#2d zarQ4LKOn9iXHTH4%2Fojd4!vRF(x4u$oh4tN$nr>Bxx=8EaYpf!Pgl5*||l9H8^^k zoK$QE0C{YY+@a6!(E)sa2Wk$tb6Ch>5g(9>J2@=jLvrx3jNA?kAALSnd}zTt;iKQj ffR8~RLq2W<#(5vpfimplBYZ*$Y(2^5>SL}k|Cs*HN%Xf)8lk81f8P687|EqDoq~dHHP+0-C1eE)0G)Kh=@TZ zu^9n{;FIGDrQUKzn-62nht~;b-mctcxb>2`K6E&z|F2TEBZ@UHN)(P#W?!Ka348+u z{gzfU9fl{FLn3&omdZ8d*6Ymi!9)6uqaPKUK1Et<8fTHdj%w<8#0I9k?9y2rj@I7Onkqgf8M>DQU2 zhK|Zvzk>fbxs3jmui(3{(x0TnyjMq5lH2Jh(_50C-IKd_?v6<#?8>QBSdn_A zkw8jTg1y0RHWDH#>`~9Y3rk95u1$#xiP`7(0&_8?-TR+^>S#I*DG8Dz!?G-SM#rK= z`DR_(H%!WGu2WHj*)ds3x<=US^DhJBEJfT-q8ZU$M27^u+}Q+5rl5L*vaGZ%Cp|}m z)MrXclw^IM4R%avd-h{EEfPgbl+qV+Z#jmZ)-!yrMEk05xn?;=S7{Fp`l~-a8B8$SCOr$ywR39rVndW~cC8prB2j)_k! zGPaBE6lu4rH+`55;8ij#yiSqNFujMUr|?y-klVdZr(@e zMsT7}=`RYSe;^Y0f#!wCM|kJ6U4FX3PkVf?g$34Ogyz^klr1R&iJF{fnn9PA7+czV zbi3pTxsPEC=cV)9+is z5n$<%dV*wbR$mKAX!~2*g5(_yj;@UbG#}YnR#}SUB9LpRr_nB~?og86~K8{|F kZjK&~V;sjhPH^;dOmfU{oOdNN94q*QT*~Bflz!QN0UlS*tN;K2 literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/IsDuplicated.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/IsDuplicated.class new file mode 100644 index 0000000000000000000000000000000000000000..b2547f04b3b575c2dccb8d76461d3e256acecea5 GIT binary patch literal 2135 zcmbVN-%}e^6#nk+CfRHPY|_$Fg7pWnCZV!Gt<^#+g^Gj$bV`R>@a2-Muw=6vvp0;q zI6OH06CCS{Gd?(u!-LMKovAYp(l`Gm$MM|k7Pg2l%xvyG=j{2u^W&bo`Rkvje*n0J z4;Zf3{HE3D1deD1R?YW3yC&-XCW&p^YWj8CwE}0;>$I$DaJSQPof;Q*Jq5;KZu1>( zx!l{dKHS(QTnZ{fa?0@>ahpLat(8|9)KYmhiv&^zH0TUjC&t6T*0L~=Nkc)FFk;II z7;Y?{DXYnDv^55U;4R;?Juyz4HNUmXaFfzGGwtxA-`=#gZL!hjju%+m^L)XDO*j5Oh^*x%AIbIWfdpCub87?+?!w$_4 z9I-`GAh;*!puaA~Vn-}Xw%GFP^W3Yuc2HdO{YIxX8FPzLj9Fd)-rsH6r?{`j{KILb zM*gRQS?;8S=6C5eq|ZvEd8X@hs{ZuXDi(pfq<> z%8AKEmka2cHOT(CBegM->U1xDJlMNzC4%T>frGsX zWsJ@A zU#SE%$eJOUk(?#DN6PndNAxm-L5-*qhd(5HWyTXs){*Fbk{J5p<2l-(JEn!b?^|>{ zd%4rxu-o@#17+X*8h2ND+mU)?EZpmO!fD!7Z^sE7vfnwr(F{E+g4Y^LycKyDPkMjE z+q`KDyZr*pSn)gUnmy;pu$Lmt>M8u@jPHv;w0SEW_5kB_FSYJT<>lv)BwbdEB(1ke zo1^y%?MCGZ(v`xm==qs61@F=uPkXNF!XAmF9(ZGvc&pr=}uN z`2{`uB!qM_B#3I7)@Wd1>=;NtRVe6l!t{UxbPDxAt+2X zeUxlEO7;$U$ZXC7W*QeUK(eH|LPWAzxgqU~$IxZ^QhVA@2f)qVOfs zWL<{zeu@%s96zkmh~meh5~7R>tupF0Vv-CQ$?)(o5)ZVnX)>M$wh-??CL&`P!PO{* zPiU7XRjiDBkA${A@+XvUkWlwW4xlVa)~odUR$5}r2Go@PH*zULPZK(9R`IA=MT|n8 z*x#Q kGa10>uE_vqfLwrlfRO;B0m@x_p}S7eScZf8Iz_nrFX%Vo^8f$< literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Name.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Name.class new file mode 100644 index 0000000000000000000000000000000000000000..31625ffe40d042988cfd9dea1dfa58f57a5d3952 GIT binary patch literal 2431 zcmb7G-%}e^6#njRek@BMn-t_%ty&NQX}f@0e^9Cgiv$C$fH=y7b4k`@$!0fZZy0%T zc(H#%M}73c@qvdrqiv_oI7r|8n;ge;v)d3##tt(i=iZZZzVn^$-gAe)|9$c&fO%{& zTrGH2v(oTwQT5G&=ekxw6ulBH>y}ydik4&gcFAqj%r#!M;$RHMF5ly(!`+g3XJ?n< z<4_r5H*D7yHyQdf`ICSRQMcXF+$2>R&3pBdxoe4?I=5Zl20oqz>aHOGqsl`ZAMe zYcS}9So2)V6*E+(;MMjS7TX(oCh9p$%jRM_v45E%Az{ag)>pjY2!`)6=fpb8JJ;q4 z6`wpOXaXa+C<(sCpb0N%lekK?GV)%`vq=qO3}Yu3%y##@ie(0|i=JEHVu=@oSKp6g zoME8KD^}qC%ob%@`GUKG4(|JQMMIQTOO(ChGIxuP<&Wh(uhOV>xHoN`o=V)@uUQ?! zx7*@d%ADz7kvq=05dWq&r5p zI(KShgYYkSpzcl#;238^eH@4hO)2c{A zba-@dSyu)XT``Uhbox__UR}{*WV^{qzb37Ad`}xZI+#_a*+Ne`W+=nTw0itgOfe!W zT}E8)mY?2JS1uSDttn8`lpu)QjND!1)@L=NdpI)4rrGk-`zj?S$lF6}M(f@Hw@w~WdMkn> zPv&jcT5D8ytoo)r7pbRL;LaAW+j1W|$DYS(y`QH*do~0wR91N{Ow%{KM!jGy*%Ejt z#MtV<##rz?;fp%21!Lu7hDJNmJfpOHNU6hB+QrDm$!fA=+9_D0U7oB$*2t#29wRyR z2o{GFW}y@YF+_o~j7dJy z8qulW(EorI0k-4>!j+hbARxqSXPm-t3uyFtAojv!dhCd{Wbrmx*=#as_75nZXCL8` zdlY0rJ=+yG=j8PZ#imZKyfi%3&dgMSMt0+|FSMA5nmhW#qPD_!#i9;zMhG$9xR> g81gafW5mbxrgPrMbaOH4<70eE1?2s{LZ8?F1MGY&2><{9 literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Nickname.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Nickname.class new file mode 100644 index 0000000000000000000000000000000000000000..87e38acf39b011740ed62851e52a9387762c024a GIT binary patch literal 2471 zcmbVO-%}e^6#njRek@BM3kCUAs}_VnY8R;1ACzjrQi6e2Kpf@4xop;C$!0fZZy0%T zcRN&+`Qrj!*uIFIMWV zJHw!P(N-EXhD&8%xQ=IT?^I036L!txu9@>BXy8~u5<2Z?m29gVA>89NYLgNf##;Lb z8=X0;vlLS3(9w=g1~oIjkwP4Xju^Tax=$CRpy5Ir6!b8}M9B#luI2x?ki@jTXp19V z8G16~r}tve3AyTfwkM`&JIk-`GTdn;b|mmQT98B&Ix%^fAtj+l3ig-0?h1x)Gv~lN z-G8nn6rI5MIe=3b!bREWYji(^A5tdCj?~K>-I-Z7u3>~>Uin9^|#Z_;qvU)8xws+<_^qh>!R#s6!#X|nm2Ys=~8HT$-N zdf|9Bu~T>#@5%9`^0+Tba9V%14g{of0o_!Kpy0?5ISU$uCWQfq|7N{u=Wr3F6&CaqASM1o=$&?(Wxt1f^0ik8P}xM4)1II2Yb`XB%AB#P8iCdGN~T^ zm{5$^Qk#*KtHo#c)ujuDMm{BKni3{am{GWm!uqskv=7Gm*(6(h_CTe=6h%A8XXJN= zAP?ATR})^NmIh;5+(;b$oJh-_rjzh1NK z1xEr8L>L=qbYsl~HA(g<=Zs(sw6R%2pwt^EBCe6niPGA=^hQs*d*gnEWJNkH$t_=*Ivh z%56-Fk=}?;{EFU(F=ClId0Ooa&%W^2b?7;FL!KM%xSSWFKewJp1No2(?84$1xw z<+JQ#T$25SFd?sWlUMo-{aQI1ZFmK*Qn5rIC2T2s*TvX3-$Rp3^Ap)exE$iI(oZT_ zJ7o_y>0}~0y3Bq`GU2$HP!RnLL7042n!AR|HuigjxAvQ4!g?*LXSh!M!_)YJteoAk ziR@2^$M&;-Liqu4bw7ImWm&dzg+5PkqY;crNCmQg9cohh8$C%{%QFl08f)q`M*kGu zq{f;Wy+cVV)*1kLtdrfOpWmko_`xRB9B$<>m%}_hBp0`HSil`h2(XCUCX4`m0hR)2 ljqgN&{s0331_KNQxZViP2AFI(!vQ|RC$xdQ-&g4K`oC`nJEH&q literal 0 HcmV?d00001 diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.class new file mode 100644 index 0000000000000000000000000000000000000000..6bb57833ee17b7ef6336985b916d04966fa507bb GIT binary patch literal 5350 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 F=)Z_Jss#W5 literal 0 HcmV?d00001 diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab index b3ee9da30bce849bc8cd2f1fcf590264891270b5..af59e3f83a1c4379c4575973708790ec8e7f7987 100644 GIT binary patch literal 4096 zcmeH@KS~2p5Qiu0-&lx<1`m-!#KuYwU?C*LB9%FT#U5Y_53r<3VPzYzPT>_)hzOoR z$Qq-9i6(yj7PBGM))q4`eDmJC_jvPN9^b4N%xp(Fi;chPNR3D(igYJCv!FV?lV%oa zZ*RJo-_QDayx04uI#3eZV&eza^vKl&&cx?2bi|V$Yz1cFH=K)|FSrv&BPi=r2jYbo z4dF?={e;6svp{T#d}xj(vwg8DZok8|Sbu}kvROQUQ0%_KgSaW~u9#K&5R1(hNW{kk lYO7{NF>fyKxdAue2Hb!fa070@4Y&a};0D})8~85et;>sdT?Zuqhj(;uas(WD^q;CK&D}-IL?lr4LtY{0`}RU(e#6^LuOvKfszS zk#!E~zJUQbe*s(a_ylTsvlclbhYw&!u415BFpDB!N_NNtIlcq!qFMh2%*f>xIFqMK g@}I0XsU`z5AOkWW12P~3G9UvoAOkWW1OH^;3xTpj761SM diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream index cad3c73a06bc24fb11aad87b27fafb5e1e1ee087..f8106000665f1e23f38e2ee9ff7de09c0bd863ac 100644 GIT binary patch delta 357 zcmZorXi#7bo5<+NnOItqp&yWupEsGGF?_NLvzK^rW_n&}fxc(4OKCw)W^!UlYKmTV z2}m&)Sg~tvVrI_dM&?My7@*iBMq$QiAT12l=9ihAotK!K3e*CUo?O8q%oqn`h$8el z0U;xk;%-E~S$XFojL@;$zGJN-Kb+VOqm8OEMgj zlT(X}L-Mmz^MED=1J!W5RwU*Y!>Rg^ww5vLI8yRy2`_1;O Gq3i(AO?i$0 delta 124 zcmZorXi#7bpUCJrxs!!&atT`izfXR8W?oQgacNG8UUo?gNNOG{&tzUE_Q@^GJ{-xZ zc_4AHmNMoDfR$m9a1SfI+d$sw$f Pn>TX!vu{4Yky9+ z?^*0pT9A{OoLG{Y0#XCh$^z0lc@2BaF^!G30{eg~0Z@<|bz5I0B7v&QF0T@n?_Nyq86kk>xluLm5IL*nxhfxk;%- zE~S${u*GjQWM*PH!OTz&QX>O43}#MvW=V!)a&l^MaY%l4Y97eRn;SUg87Ir|?1F2N zgt{*{KRGioCoDgwG_NETXn1PL4lViE#CL6FN0_pu=_9Ui6V2~UH`!a!pb@Ds5 zL=2<+@{4k@7zOkZH!Luq0m1Z%W%2^9aA0_eF_wZn0AvYpsW|8779{3n=7XIK0JQCs A1poj5 delta 95 zcmaE&c};SH;pV>_%uJK>`Qj#f3nWfH%e-%LJ$uw-XU3?_$JlZiffD;C=L+tde2guE xH77qkGjH-PrkKfd86zgM2xd+eW8S{`G`Bn>P+!F41*~acb9(p_C%@v^1posMB}V`N diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i index ff098fe18ad98c7bc2348c953509859fe0b98609..57ca4489029f15753953d24d453494c72d639aa3 100644 GIT binary patch delta 304 zcmZo@U}|V!VquVAV4gU!h2sMQ14Hq?;B6ZxO0Z0BkYHh9-^;miqF@Av1S11OZQ``c z8z)*Yb0`2gD|-Z%Y@Eo+!VYBLVsJ~HIPt*b1}T=!D!eY790owaE5FNoH%=5_VO%h| zQObSthI$s33Yqf$&4#=ktdkquSy&#QU-@g}#2-wPH`uW<8?BezJW;AZfI|bQHMaeW zGEm(OuE`VfSvGI6JHs(qftO`-i@OdBhX7Fi;n($^KzRo)jvqkxYCXKuvT>pZGsg)a z=Paw(VxZIxR*nuJPi(Wy!-*3=aNGd0>$eMwPn@`6@&<1fmVb-$?gOp6z&H7VG0WyD q`A=9mEP&?jjz|ZYYr)Df1E^t-Z`5QU?*j`52T(3Oi}TGyK@R{_O=V61 delta 210 zcmZo@U}|V!VqxHCV4gU!Wl{nQOYy$oZJP~wD_A%>7#J986Q^C?IMITc;{=eivPWPE zQ0fB90C`#u@3d^3=)pX> zL5hXtEUVaJpoKeFIc5N*#5T)31S-rIn5ZB)d4nCx<|+A4Sb-Kyi^`hnk)B+Ufo6z3-m$|0 jTU_vq-a(|sE0*}e0!Peo!4K*qzrh&aSmG0>Ky~^L=;=Xr delta 128 zcmZorXix~8?X#PY0SJUa1Plm37!r&O3=Kf$e;@#fAgcjNF@P`(faFv`oQZ+fjHf5| j7EAnNVqlmD)M>=bz%Uy~rvd31Kzef_V?W>I2F6GL*2f!e diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream index 6c9008d7c79cd4b0ce2154b32660b5cbaaf082d4..34a22a011956bf0f4ef5a79236f05d2c904ec625 100644 GIT binary patch delta 284 zcmZorXi(U2fr-&>BBPRQVrfZ+o+FTO&QD1V&n(GsOioTME)L1hPR-K+D&PhyaLrB3 z%rOCSg%MnsCWNYhjQqS*Tc9c#uqrUuuQWF)waBHkASW|9u_QA;&v^1hCXLDJ%*BkR zK$RlJndy0@1$v&vFeRxexhz|im1_IIHm=Vk{k1$K@f3=9mscDrRZ3ZCF(RM>1N zUCzj10aU~wuotLd1tW(Bkh7$TL2ja;#pW4u8-zI|fC5Jrt}WOoXu!k~0OV|+cQ9q6 z;02b=5tbIr92`KAl*#?iCkh5keql3#BLT?YJ8eP0=8rZ4Qj7+hCx(kNayS45IoNV1 zZWNT@*nA=(gNMTdD3Yx^<=;j@0glNN!dX}nP2~Sg6x85|07?|9SGQ~wv|!r2quhf7 E0NnOEZvX%Q delta 118 zcmZo@U}|V!Vqp+wVBXwlYs0nKflGmXa{yxp>*NGM7M6cYp89WgWOQWNY$#pM2o&GI zIC+8%3(Jxw2DyoX7Mo|tZ4d^E3b1dEu(V*Fs1Pyvh0TP;6Ktg>Do8L2Y@Qe{4$`E+ VvH3(o2G8aRwjErXca(c@003%jCPV-L diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab index 8d8c42afd8dcbc8f4ea5fc11eb2f391953d50523..430bfd301f2993fb1be0c7ff7527b0e77e23a39b 100644 GIT binary patch delta 205 zcmZorXix~8?X#PYk%56h7Kq_M0K&=uN;CkO|A7D`0#m~RWP|j8FbKf(+XLB569cW8 zdcIEVE6U(!W?+!~_5Z&OkUsG9|NlZD9S@}E0ckcMeFsR-`SJh10MI-eAngLA?|lFN vzXC|t0O@r=S_(+t0n!J){r}I$%D|8WqBBPRQVrfZ+o+FTO&QD1V&n(GsOioTME)L1hPR-K+D&PhyaLrB3 z%rOCSg%MnsCWNYhjQqS*Tc9c#uqrUuuQWF)waBHkASW|9u_QA;&v^1hCXLDJ%*BkR zK$RlJndy0@1$v&vFeRxexhz|im1_IIHm=Vk{k1$K@f3=9mscDrRZ3ZCF(RM>1N zUCzj10aU~wuotLd1tW(Bkh7$TL2ja;#pW4u8-zI|fC5Jrt}WOoXu!k~0OV|+cQ9q6 z;02b=5tbIr92`KAl*#?iCkh5keql3#BLT?YJ8eP0=8rZ4Qj7+hCx(kNayS45IoNV1 zZWNT@*nA=(gNMTdD3Yx^<=;j@0glNN!dX}nP2~Sg6x85|07?|9SGQ~wv|!r2quhf7 E0NnOEZvX%Q delta 118 zcmZo@U}|V!Vqp+wVBXwlYs0nKflGmXa{yxp>*NGM7M6cYp89WgWOQWNY$#pM2o&GI zIC+8%3(Jxw2DyoX7Mo|tZ4d^E3b1dEu(V*Fs1Pyvh0TP;6Ktg>Do8L2Y@Qe{4$`E+ VvH3(o2G8aRwjErXca(c@003%jCPV-L diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab index 8d8c42afd8dcbc8f4ea5fc11eb2f391953d50523..f49073638263d6e3be54a5a7fddf900ea8bb227d 100644 GIT binary patch delta 201 zcmZorXi)H-?X#PYk%56h7Kq_M0K&=uN;CkO|A7D`0#gH055pjF5CF+pP4u;A>iIgc zuPB3`nSnv_*Z==EK>EPX|NjetbUcur2c+46^c^5Q=g0s50xS#+HbB}1NZF;0v|L+0PxR delta 125 zcmZorXi)H-?X#PY0SJUa1Plm37!r&O3=Kf$e;@#fAgcjNF@P`(faFvs`r0!U|DV`b lB=L`lfkErn|NlnJ3=F4!{{No_q_cqZ=0e7PzR3-YkpRh~8;$?~ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream index 9029099e6850a19f1864c72325dc9606b02e3641..02cd99cb1449d12db89c6762069ce5a932456e8e 100644 GIT binary patch delta 284 zcmZorXi(U2fr-&>BBPRQVrfZ+z9W!u&QD1V&n(GsOioTME)L1hPR-K+D&PhyaLrB3 z%rOCSg%MnsCWNYhjQqS*Tc9c#uqrUuuQWF)waBHkASW|9u_QA;&v^1hCXLDJ%*BkR zK$RlJndy0@1^S-FFeRxex9c^Fsa;+yW067#Oz4URlim6rJdMycDQTf_?J=`v6u(g~@`h z?>Q`h5_OL^y#(55z{H^ewBOk3nmT@pz#g@bqj#99;}-?d<8@|FYrAev^k=51s4Ec;x9b_ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab index 4554491caae70c9a0f2721e2f7dd1a6ce75d7cb8..d2a3d164f4da75a97e05344ab2b2b661274881ff 100644 GIT binary patch delta 224 zcmX}m!3qIk5C`ztwOrKtoDxysVaO_*Ib4jb-lA5WuEDJRl< z0d?v9)OU}Q(!`)Es)UK O&c2uZVaulCjQuaw>_Jli delta 133 zcmZorXi)H-?X#PY0SH7u1Plm37z&IG3=Kf$e;@#fAgcjNF@P`(faEME`r0$y`aQ9) vNZ}t71H*&!|Nk2?GcYVX`~QC$kiLET|NmJ)n)B5E|CBBPRQVrfZ+z9W!u&QD1V&n(GsOioTME)L1hPR-K+D&PhyaLrB3 z%rOCSg%MnsCWNYhjQqS*Tc9c#uqrUuuQWF)waBHkASW|9u_QA;&v^1hCXLDJ%*BkR zK$RlJndy0@1^S-FFeRxexyZtnTL z|NX3X{3$*Dc82~ac1vHy)r?Z~+|`&)GAh%!?|PIgA~&0)3*y%F$u(-Epw%c3QO|vma2w@n2@4yZi{dZ!$yv5u+@nw09-V@)=9MKu9s$!D(r0@ZK zAf1=cc?F$?t97GVbMyY$Adz2t-FVX|)Qm=@aHG?zHY#&d+aypiJ5GxDA)XTV3-g2B z;dvptp&Z_@XeTqR-9f{>tDbp?XeNQi`r{q7!%qC$*i;|iW%jBz!irfAU%mS$UbHHG_D{XB>P%cq{z01w%3>_xc0nC6j8S1FPbV~Sm{ zq=V&@l(tiJ`IN2>agHTRj7Mb&x_st=J~40(EuT>^<6wHhygt<5j6Gn+{WxIEcW16} z9pcoCyK6fz!2L&B0uE%D%;R)k=pW+xVf|IJb>*;GtL_<{swFuHR@<(}+=n#1ZS7T! z+Sc1mB*SasSV=y=BVH;$A-*Z(VxIie4hg~JZn%Ns&-g_#T?&gxWK{fC)=sj;dtUm7 zpyAKy)3}EV?P{fQ*et9Jw8Dv=>n(l>zevvjtMAiJ__|S-gI611KzJfA-qX?^aJ#do zKT8Z}vB{#FRo%OZ36jBvvyj>U%HX;k4}CrN~={jYTH)r zu+cGrT(bi(N-40h1Qlx>W70<0!$~M zN8ub#ip6YF{PnmlW@(~pV}UpVKRi8%1=5I01g&fuL6o8(N&{m9*1_e+KJFxgJOr+D zDixM4#Hkk*kuEipgcfcl=g}i=1P*DG$os47AYhBkBM|7%n~?uG@wrFbMk_n#)j{l* z)4@RyKpaLc_BdewG5RHU^y2sOBs&Yq@!t_osuNMKoN_LU7tymcyHrLkIeAxoj{0&C zHcp;GH52Pf@Z_QQ9lGJaY}K1a1K=gzI^5T_Qx8@n#aIs}xZ9*n*lmw diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i index 6f03108c314f09c3a53aaee6fc95506ef1666d23..8ec266e88e13abdb5ccc38bd500060d2d92346ac 100644 GIT binary patch delta 252 zcmZo@U}|V!VquVDVBRR`!^k1Q$iTp~JKbQSpaF*gkX;p-XSw+xs|L&F9jqSA905R~ zpEu5_ZJx;3!N}nN9c^Fsa;+yW067#Oz4URlim6rJdMycDQTf_?J=`v6u(g~@`h z?>Q`h5_OL^y#(55z{H^ewBOk3nmT@pz#g@bqj#99;}-?d<8^-x;C&)4q#+q`E&97cc3^2&*q5I69t9&I8hJK)nV)dL58{`0M|F9ySJsIY2rKNQVRI6F^!B mNNcb&Fr5DR|9=CJ?g7$wfV3x&cI9AT`1#}i|ILhy2lxO-#y;TbpX*>V` delta 45 zcmZorXi(U2ftfLUBBLjNPJVi3p1x~tVrGtBc1bKyXz~x%3!67`__J?5z>&`k0C24k AiU0rr diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len index 1e061838fa6f03a369ee91f44cd453a5241ede2b..8effc88fc1a38d8dd030f21fcb6b6ed7efa706a0 100644 GIT binary patch literal 8 McmZQz00EA50071Sw*UYD literal 8 McmZQz00CAf002|~NB{r; diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len index cf8a30a1c969e61b953bddf5da4778377335bdd6..6a294aa5b14ac464848e0bfb5de63659bfa3bedc 100644 GIT binary patch literal 8 McmZQz00Bk^002q=LI3~& literal 8 LcmZQz0D~U@0RRB` diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at index b623d48dcde03d113fbe91e99c3dcda24e47d7cb..a98c4f7bcf4907493d4c896cff35896ce00b38d7 100644 GIT binary patch delta 440 zcmX@jd7Xd5US?)L2D`}zn3ePrOG`5J9f5>%eoAV1W=V!)a&l^MaY%l4Y960nc791t zW?p=5eoARhsttn+!lIk6-)W%4>^6IrOZ zUt%u0!Hx`uAcGZQDl(I^^DtGx0tcolzbH2`CoDgwG_NET=!n!3OuwUP3C>T>B&4OD c!3gA*iPHoaZJ-QE73ciig2cSceDuHv0EZu-!2kdN delta 26 icmcc4f0}c{Ugn8gRk?HW(=+q*U2_vNb0+h%-U9%VNeWf~ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i index f73dadd2a95b62aec3ac5d15e3aab6c5d5144799..c2555187b4d6c537f6ff3d32054ff0d77ab1ef57 100644 GIT binary patch delta 217 zcmZo@U}|V!VquVAV4gU!Wn+f|%j6B-EG+DMIX6xejAUnIV5m);c6sAO3+Bxp90DvH z7C@0(3~s3tCmz_W!0W-uVE`1k^1Hlu<3s_L$qiB-92!7@3Yqf$&4#=ktQ-TQ2yc9^`1c04qTgmgmQ3k{9s^UsNXIu zK5^oP$qf=LEdLhg-3RKpz_)oq{tH$P1)z@I5$PZu7OWf(fQt9{Mok9tKCo~I0OiuN KINwYZ^Z)?Z=SRH& delta 129 zcmZo@U}|V!VqxHCV4gU!Wn+f|%S43)jt2}347G{VE^nM@!MxdnLx5%Cf)kq+cs)2b zE|6g2xB--X?)+JM3HdKrfh-Fyjt@W;=~ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/counters.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/counters.tab index 4fef5ef89..1911a39b6 100644 --- a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/counters.tab +++ b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/counters.tab @@ -1,2 +1,2 @@ -15 +25 0 \ No newline at end of file diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab index fe54fd70754eacd70d278653abce57bf141b6f1f..780441c2ef447bef0f3c61ea2a346f11f4168836 100644 GIT binary patch delta 192 zcmZorXi)H-?X#PYk%56h0*K*20K#$rN;CkO|A7D`0#m~RWP|j8Fbsg?ye9hEGuln; z4NkBGDrp1ingFC5fb@GHT?M4wSQ!{ffb=>bod=|O*cccxfOHm+P6E;=fOHIy)?jB~ e2m{g$Kso?O-vQEIK-!gqfx!hxZ)RjXzy|;TbpX*>V` delta 45 zcmZorXi(U2ftfLUBBLjNPJVi3p1x~tVrGtBc1bKyXz~x%3!67`__J?5z>&`k0C24k AiU0rr diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len index 1e061838fa6f03a369ee91f44cd453a5241ede2b..8effc88fc1a38d8dd030f21fcb6b6ed7efa706a0 100644 GIT binary patch literal 8 McmZQz00EA50071Sw*UYD literal 8 McmZQz00CAf002|~NB{r; diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len index cf8a30a1c969e61b953bddf5da4778377335bdd6..6a294aa5b14ac464848e0bfb5de63659bfa3bedc 100644 GIT binary patch literal 8 McmZQz00Bk^002q=LI3~& literal 8 LcmZQz0D~U@0RRB` diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at index 3763557f4e133063db1be5f879f8d4ba4a2d37c0..ae69ecd25e6c23a2e9d99fddd6858a40ad760c93 100644 GIT binary patch delta 67 qcmeBXJkB_w+lGY!2>8LI0GJd6lR{up7)*+QNl`E<1}4S9qyzxNpaYix delta 6 NcmX@k*v&Yh8vqE80&oBT diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i index ed8fa62ab3b4da6e4f97b3d6e29395f78476e909..eafbf6baf94325d30e9d919ada48aff97e477abb 100644 GIT binary patch delta 220 zcmZo@U}|V!VquVAVBUO@aS!9>1B?L@90H6C49`D(3;_xqV4o}?#lq6XW_cCJGvMN| z0LtxRNZqng(13BXhpqu5#}5VuhWqk+PHz-+0P5FIVB*jKs+pmqm^4waf1B?L@93L1M7@mLn7y=YB5Z>&eYrwcs!2>9#pTM+H zA%c%|BD0ZXdn%;>BG1G|2H!-?%)Fel!iR3 delta 120 zcmZorXi)H-?X#PY0SNd(1Plm37(aki0}%fQ0+0x@8b+Wn5W@k;5b24&_Kd|7d&5Qg de*gc^3lz}<(jb|0zyAN<9LTtyZ*l@-Bmln38o~eo diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream index fbebe849c1a1a4cf2d621f53ec975a5c522de6d3..9a50599738266fe81e0b8669abc7b2bde8771728 100644 GIT binary patch delta 34 pcmZorXi$)3U}R!uVP#|I;N;@w;pO8O5EK#?5fu}c*eLj%9{@kR1U>)& delta 27 icmZorXi(s1U}R!uVP#|I;N;@w;pN+?c%Ofwfe-*Q90W`N diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len index 933d5532f46fad8a388cd1eda7b7501d90c98111..1df5122b7b2b57326bdb43fe107c6b21833cc148 100644 GIT binary patch literal 8 LcmZQz00T(?03iSx literal 8 LcmZQz00Vvi02crd diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len index cf8a30a1c969e61b953bddf5da4778377335bdd6..42df8b93f29a8c8b6c75bd279770190db7c41baf 100644 GIT binary patch literal 8 McmZQz00Bl1002?|N&o-= literal 8 LcmZQz0D~U@0RRB` diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at index ae70a8d7175adb19e3b6a8d26557fde6c8c1ac62..d5feb11f68f064f884422ecfb505ac8ac0b7a97c 100644 GIT binary patch delta 317 zcmbQp{Z43uI16(oL&juACQqfr(vl2)MS4Ppsu(_s9p^2>^7y BZA$-7W0y9h-9 delta 19 acmZo@U}|V!Vq)N%$W*uSicbB+2O$7G9|s!% diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab index 2ea84b0b615b2eeda58ce97e7265cdb2d3009867..766bd3702de2b4be99dc7905efd8e79c0fda265e 100644 GIT binary patch literal 4096 zcmeIxU1(2X90%|-FN-A>7Zfe(@4{+pSxvIqlGTLOBoj5tOY>Hn@>dLN6I1gVVzOk5 z%r5@PYgk!A)ZZ?a5XCN*D3o1D+m6pE%B5VNUp?n@eoxPH>U^Jb&M&<;F(U|qO-5AX zqDyvk34+wI8&g3)B;UmsvHy7{@7x6lmv5PBt znQM8GHEd-aPjNSovWd-XVIxnoo^4F>3Tv6-7T)Cw_OOD_S3%=AyRa}tkn8V_?8o0!YJ zEaWa0vyNrl$_iGoij`c)CEUz1?qCV`a6S*PkVlwDpHp0M0&xOy0&xOy0&xOy0&xOy M0&xOy0{@l3FNLI?Qvd(} delta 205 zcmZorXi)H-?X#PY0SGKX1Plm37#>Uv3=Kf$e;@#fAgf^n@ v(mp`?3Xrw}(szNh3XpyVq=kU=dmzmMq<;YEOMn0W-@K98pJ(#{=1fKa{*_95BYj84bP*N~FoXGjbPbpxbUHr}%wU<}>j!3Rp8B91%$Q>3 zV+d!+?6%`&1d04@bLs~(p7&2q0WgxLccC2sDc@@0`LCX%*d3* F0|3 delta 66 zcmZorXi(Tt&B($0Kf0!I^@R_U-!p2;`#)Xsk8z5Xk6~5Wj}u^q97EF*Fk{ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at index c9c04602a391f012ff514fd306f305c704ef101b..cb8b4f3dfd5e1411e23e0e9caf977f2e0ee63f5f 100644 GIT binary patch literal 984 zcma)*+e*Vg5Qfuq(>6Vyn+q@U2EK*#Mkos2hjyug7)j#$iEpBBA$s9I|HQZ@Z87kF zyO~pGH`7aRZIhkN;v2h7vt4|ZX7R>m`9ogVr(&Jt_t(kuUGn&1Z;Lcb_SSgvkPXrw z(*pQV6Kc`kBn=tNe`6Zh1W+3a>C@;o_aSRZotF5aF6|xl#xU@aDiS4?B(ekjMQe`s z=u-PFyJkh-;X%K&2PdcE}5lgbE#b^dyE;8eR4n!)y~`M;Y@vK01Y9H*32V0 znn{ky2|1M#o?Pn$nx62_;9Ei~xk%kHaz@U{1-T?w{7%y5;$QKaRpx31WsGz_)$HJH z1XUefsNeGrCI?3LTb~!6x0;}hn|*X*5Ky~m*s2@DzJAWoyvpxHye?@hGVf9)G9O(o d0A7?|GMSP2*2VRl-+#(~DKc-moR6(}e*jd#BjW%7 delta 120 zcmcb?zL{l14P!hH3j+}Ff=NCB5Str_c|c-7%m)_d29ua7feILyfS4JG*+f7*5MTsi ZRv=~vV$R9?nG_feCO=>@WCI(*2>{@c2YCPh diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab_i index d314f4ab39dad6177349578a192922d0f2c93ac2..34e4b21315188543d66e59bffdacf8a22ac7de5c 100644 GIT binary patch delta 878 zcmXX^ZAep57{2H3ifQLN0iv)R~`12hmf$r$F}4Gc?mUrD=ov0@H$LrL)k_$Pf9${0A+9TU72) zl=WX4w+KE#LDa?Cms>K!bBqY+qJh?9^Db)t0nXTjIyBf0q7 zf`|6$BcR)_cRj)si;)53ew{ocxQ8ZC53g`%py(>gnao!~VQ|gfbQL&*nPb%!>FD(; z{KRkHUaUsXrx93kSJs`!rXfx0yU;ZWs_{tttGz}5{<^7?PX!;LBGlizHka9a2G>wm zTiTD#Atv?ukV*rPCm&RvkYl@j4k||z|8e)%?m&br)Mra)R|+1cG=f`)dixN>rNxk0 zRGe(W1CY5!pGqDOZ(|p>V;z@9S(xSJxU|ix>8sMTb8T0%KxsxUIK55%O>ib1GSY12 zkpb%0^Cca2*wO9Nw1$_x@9UN;xS44MGWHvLuPen95Zh zEMhY@Ad+;U?M^_$tSOL)*@OiMy^cK`an)xA@-tthHLiA{uZD!B5qMwOdPaUoMK5u~ zbVPzec+1ra1T(H8ynISrC(ocoeA4Ws2-jLrowH~@LzwB~ZV7kM67hLT zhi_LuTpd7XsZ5|V+osUV{xNL9ayHinqPs_7bA1}sY^I^*)c5!kG@>>Y#vv8dSU^9Q zi1vohH3K};8b!Y<1#8>KpB`JrpJ6?l#2#D%R-uC8ap>&m5w5ZGVh!1j3}MN@oMv|f zM^%B^zOUfHjj%qJQaAJNe@`MPQu^Ut-lJHV2yK$m&zGTzaaaVrW1TPw-R@RT53ob1 HocQDyZYqu` diff --git a/core/model/build/kotlin/compileKotlin/cacheable/last-build.bin b/core/model/build/kotlin/compileKotlin/cacheable/last-build.bin index 5e2dabde74f0c27b03ddbe495d9329cf7cae549e..94bc580e12e04db6bccd3da9296f916e87f855c7 100644 GIT binary patch literal 18 YcmZ4UmVvdLhk=1{a+j>*0tO%e05V1dJ^%m! literal 18 YcmZ4UmVvdLhk=1{a)R%NKMX(s05~iKPXGV_ diff --git a/core/model/build/kotlin/compileKotlin/local-state/build-history.bin b/core/model/build/kotlin/compileKotlin/local-state/build-history.bin index 0a322d558880b4cd18c40938a1b4cabe619e09de..498de98188e7ad5441ee9c3ed1ada2269dfc9796 100644 GIT binary patch literal 504 zcmZ4UmVvd3fr0To0|YPu*^@g@>TQMcK@{WUE?LI~j6fDE1A9(>VoGLSI)hDeey(12 zX>n#rZn0i+eqLT`a!E>lI*?hEs+XIelA5FEn3tDdnwOlKo0?bRk)NBY=bWEgkeHX5 zpT{6*6YS`#>+J6r91;}j9O55jN1=h72(yhycNv2Kx?33(37Ue<6Xe*njy{TF F003S-t^5E0 literal 31 dcmZ4UmVvcgk^ur385kHRC-{E&1LZR?003nx1zi9D diff --git a/core/model/build/kotlin/modeljar-classes.txt b/core/model/build/kotlin/modeljar-classes.txt index a32193c37..af6b32e85 100644 --- a/core/model/build/kotlin/modeljar-classes.txt +++ b/core/model/build/kotlin/modeljar-classes.txt @@ -1 +1 @@ -/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Announcement.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Application.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/ConnectDogResult.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Loading.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Success.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Yet.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example$Grade.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/InterApplication.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/IntermediatorManage.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Recent.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Review.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Volunteer.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/Email.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/LoginResult.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/NormalLogin.class:/Users/kangseunggu/Desktop/final/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/SocialLogin.class \ No newline at end of file +/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Announcement.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome$Companion.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Application.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/ConnectDogResult.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Loading.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Success.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Yet.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example$Grade.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/InterApplication.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/IntermediatorManage.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Recent.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Review.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Volunteer.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Email.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/EmailAuthCode.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Phone.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/PhoneNumberDuplication.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/LoginResult.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/NormalLogin.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/SocialLogin.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/IsDuplicated.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Name.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Nickname.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/SocialVolunteerDetail.class \ No newline at end of file diff --git a/core/model/build/libs/model.jar b/core/model/build/libs/model.jar index e5477cc0d1acf5c969ecd5655deec1ccc6e4a3ed..a073bc6a1ec41860d66fc4099434f06dfd665798 100644 GIT binary patch delta 19159 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 diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/AnnouncementHome.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/AnnouncementHome.kt index 832df94df..2cf4fe7ea 100644 --- a/core/model/src/main/java/com/kusitms/connectdog/core/model/AnnouncementHome.kt +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/AnnouncementHome.kt @@ -7,4 +7,15 @@ data class AnnouncementHome( val postId: Int, val dogName: String, val pickUpTime: String -) +) { + companion object { + fun loading() = AnnouncementHome( + imageUrl = "", + location = "이동봉사 위치", + date = "YY.mm.dd(요일)", + postId = -1, + dogName = "", + pickUpTime = "" + ) + } +} diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.kt new file mode 100644 index 000000000..31dc7af29 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.kt @@ -0,0 +1,6 @@ +package com.kusitms.connectdog.core.model.auth + +data class AuthCodeWithAccessToken( + val authCode: String, + val accessToken: String +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Email.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Email.kt new file mode 100644 index 000000000..064699b06 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Email.kt @@ -0,0 +1,5 @@ +package com.kusitms.connectdog.core.model.auth + +data class Email( + val email: String +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/EmailAuthCode.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/EmailAuthCode.kt new file mode 100644 index 000000000..04d98c3e8 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/EmailAuthCode.kt @@ -0,0 +1,5 @@ +package com.kusitms.connectdog.core.model.auth + +data class EmailAuthCode( + val authCode: String +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Phone.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Phone.kt new file mode 100644 index 000000000..64223e00e --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Phone.kt @@ -0,0 +1,5 @@ +package com.kusitms.connectdog.core.model.auth + +data class Phone( + val phone: String +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/PhoneNumberDuplication.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/PhoneNumberDuplication.kt new file mode 100644 index 000000000..62d544830 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/PhoneNumberDuplication.kt @@ -0,0 +1,7 @@ +package com.kusitms.connectdog.core.model.auth + +data class PhoneNumberDuplication( + val isDuplicated: Boolean, + val socialType: String?, + val email: String? +) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/LoginResponseItem.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/login/LoginResult.kt similarity index 51% rename from core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/LoginResponseItem.kt rename to core/model/src/main/java/com/kusitms/connectdog/core/model/login/LoginResult.kt index 81e0364c3..500b1798c 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/LoginResponseItem.kt +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/login/LoginResult.kt @@ -1,6 +1,6 @@ -package com.kusitms.connectdog.core.data.api.model +package com.kusitms.connectdog.core.model.login -data class LoginResponseItem( +data class LoginResult( val accessToken: String, val refreshToken: String, val roleName: String diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/login/NormalLogin.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/login/NormalLogin.kt new file mode 100644 index 000000000..69b0c2a9d --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/login/NormalLogin.kt @@ -0,0 +1,6 @@ +package com.kusitms.connectdog.core.model.login + +data class NormalLogin( + val email: String, + val password: String +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/login/SocialLogin.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/login/SocialLogin.kt new file mode 100644 index 000000000..459c63dd7 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/login/SocialLogin.kt @@ -0,0 +1,6 @@ +package com.kusitms.connectdog.core.model.login + +data class SocialLogin( + val accessToken: String, + val provider: String +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/IsDuplicated.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/IsDuplicated.kt new file mode 100644 index 000000000..b58fad5a6 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/IsDuplicated.kt @@ -0,0 +1,5 @@ +package com.kusitms.connectdog.core.model.signup + +data class IsDuplicated( + val isDuplicated: Boolean +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Name.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Name.kt new file mode 100644 index 000000000..62b06c51a --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Name.kt @@ -0,0 +1,5 @@ +package com.kusitms.connectdog.core.model.signup + +data class Name( + val name: String +) \ No newline at end of file diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Nickname.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Nickname.kt new file mode 100644 index 000000000..e67ebdb44 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Nickname.kt @@ -0,0 +1,5 @@ +package com.kusitms.connectdog.core.model.signup + +data class Nickname( + val nickname: String +) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/NormalVolunteerSignUpBody.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.kt similarity index 65% rename from core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/NormalVolunteerSignUpBody.kt rename to core/model/src/main/java/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.kt index 9911b7c0e..878e24e48 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/NormalVolunteerSignUpBody.kt +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.kt @@ -1,6 +1,6 @@ -package com.kusitms.connectdog.core.data.api.model.volunteer +package com.kusitms.connectdog.core.model.signup -data class NormalVolunteerSignUpBody( +data class NormalVolunteerDetail( val email: String, val password: String, val nickname: String, diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/SocialVolunteerSignUpBody.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/SocialVolunteerDetail.kt similarity index 58% rename from core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/SocialVolunteerSignUpBody.kt rename to core/model/src/main/java/com/kusitms/connectdog/core/model/signup/SocialVolunteerDetail.kt index 47a6d5a10..a8ad32489 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/SocialVolunteerSignUpBody.kt +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/SocialVolunteerDetail.kt @@ -1,6 +1,6 @@ -package com.kusitms.connectdog.core.data.api.model.volunteer +package com.kusitms.connectdog.core.model.signup -data class SocialVolunteerSignUpBody( +data class SocialVolunteerDetail( val nickname: String, val profileImageNum: Int, val isOptionAgr: Boolean = true, diff --git a/core/util/src/main/java/com/kusitms/connectdog/core/util/Constants.kt b/core/util/src/main/java/com/kusitms/connectdog/core/util/Constants.kt index 8835173b3..f44f19fb4 100644 --- a/core/util/src/main/java/com/kusitms/connectdog/core/util/Constants.kt +++ b/core/util/src/main/java/com/kusitms/connectdog/core/util/Constants.kt @@ -1,18 +1,20 @@ package com.kusitms.connectdog.core.util -enum class AppMode { - LOGIN, - VOLUNTEER, - INTERMEDIATOR -} +import androidx.annotation.DrawableRes -enum class UserType { - SOCIAL_VOLUNTEER, - NORMAL_VOLUNTEER, - INTERMEDIATOR +enum class UserType( + @DrawableRes val topBarTitleRes: Int, +) { + SOCIAL_VOLUNTEER(R.string.volunteer_signup), + NORMAL_VOLUNTEER(R.string.volunteer_signup), + INTERMEDIATOR(R.string.intermediator_signup) } enum class SocialType { GUEST, VOLUNTEER +} + +enum class AccountType { + EMAIL, PASSWORD } \ No newline at end of file diff --git a/core/util/src/main/res/values/string.xml b/core/util/src/main/res/values/string.xml new file mode 100644 index 000000000..e03158634 --- /dev/null +++ b/core/util/src/main/res/values/string.xml @@ -0,0 +1,5 @@ + + + 이동봉사자 회원가입 + 이동봉사 모집자 회원가입 + \ No newline at end of file diff --git a/data/src/main/java/com/kusitms/connectdog/data/model/remote/request/NormalLoginDto.kt b/data/src/main/java/com/kusitms/connectdog/data/model/remote/request/NormalLoginDto.kt deleted file mode 100644 index ce8dc8496..000000000 --- a/data/src/main/java/com/kusitms/connectdog/data/model/remote/request/NormalLoginDto.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.kusitms.connectdog.data.model.remote.request - -data class NormalLoginDto( - val email: String, - val password: String -) diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index 7afdbc404..61b8c213b 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -5,6 +5,13 @@ plugins { } java { - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +dependencies { + implementation(projects.core.model) + + implementation(libs.kotlinx.coroutines.core) + implementation(libs.javax.inject) } \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/repository/AuthRepository.kt b/domain/src/main/java/com/kusitms/connectdog/domain/repository/AuthRepository.kt new file mode 100644 index 000000000..c9e7edbbe --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/repository/AuthRepository.kt @@ -0,0 +1,19 @@ +package com.kusitms.connectdog.domain.repository + +import com.kusitms.connectdog.core.model.auth.AuthCodeWithAccessToken +import com.kusitms.connectdog.core.model.auth.Email +import com.kusitms.connectdog.core.model.auth.EmailAuthCode +import com.kusitms.connectdog.core.model.auth.PhoneNumberDuplication + + +interface AuthRepository { + suspend fun getEmailAuthCode(email: String): Result + suspend fun searchVolunteerEmail(phone: String): Result + suspend fun searchIntermediatorEmail(phone: String): Result + + suspend fun emailAuthForVolunteerPasswordReset(email: String): Result + suspend fun emailAuthForIntermediatorPasswordReset(email: String): Result + + suspend fun getVolunteerPhoneNumberDuplication(phone: String): Result + suspend fun getIntermediatorPhoneNumberDuplication(phone: String): Result +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/repository/DataStoreRepository.kt b/domain/src/main/java/com/kusitms/connectdog/domain/repository/DataStoreRepository.kt new file mode 100644 index 000000000..556836fc4 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/repository/DataStoreRepository.kt @@ -0,0 +1,23 @@ +package com.kusitms.connectdog.domain.repository + +import com.kusitms.connectdog.domain.usecase.login.AppMode +import com.kusitms.connectdog.domain.usecase.login.SocialLoginProvider +import kotlinx.coroutines.flow.Flow + +interface DataStoreRepository { + suspend fun updateAccessToken(accessToken: String) + suspend fun updateRefreshToken(refreshToken: String) + suspend fun updateAppMode(appMode: AppMode) + suspend fun updateFcmToken(fcmToken: String) + suspend fun updateSocialToken(token: String) + suspend fun updateSocialLoginProvider(provider: SocialLoginProvider) + + suspend fun getAccessToken(): Flow + suspend fun getRefreshToken(): Flow + suspend fun getFcmToken(): Flow + suspend fun getAppMode(): Flow + suspend fun getSocialToken(): Flow + suspend fun getSocialLoginProvider(): Flow + + suspend fun deleteAccessToken() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/repository/LoginRepository.kt b/domain/src/main/java/com/kusitms/connectdog/domain/repository/LoginRepository.kt new file mode 100644 index 000000000..a12904072 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/repository/LoginRepository.kt @@ -0,0 +1,22 @@ +package com.kusitms.connectdog.domain.repository + +import com.kusitms.connectdog.core.model.login.LoginResult + +interface LoginRepository { + suspend fun volunteerNormalLogin( + email: String, + password: String + ): Result + + suspend fun socialLogin( + accessToken: String, + provider: String + ): Result + + suspend fun intermediatorNormalLogin( + email: String, + password: String + ): Result + + suspend fun logout(): Result +} diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/repository/SignUpRepository.kt b/domain/src/main/java/com/kusitms/connectdog/domain/repository/SignUpRepository.kt new file mode 100644 index 000000000..bba542245 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/repository/SignUpRepository.kt @@ -0,0 +1,26 @@ +package com.kusitms.connectdog.domain.repository + +import com.kusitms.connectdog.core.model.signup.IsDuplicated + +interface SignUpRepository { + suspend fun getVolunteerNicknameDuplication(nickname: String): Result + suspend fun getIntermediatorNicknameDuplication(nickname: String): Result + + suspend fun initNormalVolunteerSignUp( + email: String, + password: String, + nickname: String, + profileImageNum: Int, + isOptionAgr: Boolean = true, + phone: String, + name: String + ): Result + + suspend fun initSocialVolunteerSignUp( + nickname: String, + profileImageNum: Int, + isOptionAgr: Boolean = true, + phone: String, + name: String + ): Result +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetAppModeUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetAppModeUseCase.kt new file mode 100644 index 000000000..2d00c8dc2 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetAppModeUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetAppModeUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke() = repository.getAppMode() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetFcmTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetFcmTokenUseCase.kt new file mode 100644 index 000000000..b3dc3d2af --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetFcmTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetFcmTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke() = repository.getFcmToken() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/UpdateFcmTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/UpdateFcmTokenUseCase.kt new file mode 100644 index 000000000..325ec5cd9 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/UpdateFcmTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class UpdateFcmTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke(fcmToken: String) = repository.updateFcmToken(fcmToken) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForIntermediatorPasswordResetUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForIntermediatorPasswordResetUseCase.kt new file mode 100644 index 000000000..b08536f73 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForIntermediatorPasswordResetUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class EmailAuthForIntermediatorPasswordResetUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(email: String) = repository.emailAuthForIntermediatorPasswordReset(email) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForVolunteerPassowordResetUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForVolunteerPassowordResetUseCase.kt new file mode 100644 index 000000000..0e1d039b3 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForVolunteerPassowordResetUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class EmailAuthForVolunteerPasswordResetUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(email: String) = repository.emailAuthForVolunteerPasswordReset(email) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetEmailAuthCodeUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetEmailAuthCodeUseCase.kt new file mode 100644 index 000000000..32fdfeb17 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetEmailAuthCodeUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetEmailAuthCodeUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(email: String) = repository.getEmailAuthCode(email) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetIntermediatorPhoneNumberDuplicationUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetIntermediatorPhoneNumberDuplicationUseCase.kt new file mode 100644 index 000000000..3ab598a16 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetIntermediatorPhoneNumberDuplicationUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetIntermediatorPhoneNumberDuplicationUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(phone: String) = repository.getIntermediatorPhoneNumberDuplication(phone) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetVolunteerPhoneNumberDuplicationUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetVolunteerPhoneNumberDuplicationUseCase.kt new file mode 100644 index 000000000..017a0fe3e --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetVolunteerPhoneNumberDuplicationUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetVolunteerPhoneNumberDuplicationUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(phone: String) = repository.getVolunteerPhoneNumberDuplication(phone) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchIntermediatorEmailUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchIntermediatorEmailUseCase.kt new file mode 100644 index 000000000..235f1f81b --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchIntermediatorEmailUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class SearchIntermediatorEmailUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(phone: String) = repository.searchIntermediatorEmail(phone) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchVolunteerEmailUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchVolunteerEmailUseCase.kt new file mode 100644 index 000000000..4fbd29486 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchVolunteerEmailUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class SearchVolunteerEmailUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(phone: String) = repository.searchVolunteerEmail(phone) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/DeleteAccessTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/DeleteAccessTokenUseCase.kt new file mode 100644 index 000000000..47ab7ab99 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/DeleteAccessTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class DeleteAccessTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke() = repository.deleteAccessToken() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/IntermediatorLoginUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/IntermediatorLoginUseCase.kt new file mode 100644 index 000000000..00bf11ac0 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/IntermediatorLoginUseCase.kt @@ -0,0 +1,15 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.LoginRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class IntermediatorLoginUseCase @Inject constructor( + val repository: LoginRepository +) { + suspend operator fun invoke( + email: String, + password: String + ) = repository.intermediatorNormalLogin(email, password) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/LogoutUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/LogoutUseCase.kt new file mode 100644 index 000000000..1ff46c68f --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/LogoutUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.LoginRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class LogoutUseCase @Inject constructor( + val repository: LoginRepository +) { + suspend operator fun invoke() = repository.logout() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/SocialLoginUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/SocialLoginUseCase.kt new file mode 100644 index 000000000..56f6a6c9d --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/SocialLoginUseCase.kt @@ -0,0 +1,15 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.LoginRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class SocialLoginUseCase @Inject constructor( + val repository: LoginRepository +) { + suspend operator fun invoke( + accessToken: String, + provider: String + ) = repository.socialLogin(accessToken, provider) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAccessTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAccessTokenUseCase.kt new file mode 100644 index 000000000..dee3a01d7 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAccessTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class UpdateAccessTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke(accessToken: String) = repository.updateAccessToken(accessToken) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAppModeUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAppModeUseCase.kt new file mode 100644 index 000000000..9e2235977 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAppModeUseCase.kt @@ -0,0 +1,18 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +enum class AppMode { + LOGIN, + VOLUNTEER, + INTERMEDIATOR +} + +@Singleton +class UpdateAppModeUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke(appMode: AppMode) = repository.updateAppMode(appMode) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateRefreshTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateRefreshTokenUseCase.kt new file mode 100644 index 000000000..9509c7d9f --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateRefreshTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class UpdateRefreshTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke(refreshToken: String) = repository.updateRefreshToken(refreshToken) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialProviderUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialProviderUseCase.kt new file mode 100644 index 000000000..aa68bb5a8 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialProviderUseCase.kt @@ -0,0 +1,16 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +enum class SocialLoginProvider { + KAKAO, NAVER +} + +@Singleton +class UpdateSocialProviderUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke(provider: SocialLoginProvider) = repository.updateSocialLoginProvider(provider) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialTokenUseCase.kt new file mode 100644 index 000000000..0ef69fd00 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class UpdateSocialTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke(token: String) = repository.updateSocialToken(token) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/VolunteerLoginUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/VolunteerLoginUseCase.kt new file mode 100644 index 000000000..1d7723c15 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/VolunteerLoginUseCase.kt @@ -0,0 +1,15 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.LoginRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class VolunteerLoginUseCase @Inject constructor( + val repository: LoginRepository +) { + suspend operator fun invoke( + email: String, + password: String + ) = repository.volunteerNormalLogin(email, password) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetIntermediatorNameDuplication.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetIntermediatorNameDuplication.kt new file mode 100644 index 000000000..5829ea14c --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetIntermediatorNameDuplication.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.signup + +import com.kusitms.connectdog.domain.repository.SignUpRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetIntermediatorNameDuplication @Inject constructor( + val repository: SignUpRepository +) { + suspend operator fun invoke(name: String) = repository.getIntermediatorNicknameDuplication(name) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialProviderUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialProviderUseCase.kt new file mode 100644 index 000000000..05250ee68 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialProviderUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.signup + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetSocialProviderUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke() = repository.getSocialLoginProvider() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialTokenUseCase.kt new file mode 100644 index 000000000..5810aa490 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.signup + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetSocialTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke() = repository.getSocialToken() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetVolunteerNicknameDuplication.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetVolunteerNicknameDuplication.kt new file mode 100644 index 000000000..3831db639 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetVolunteerNicknameDuplication.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.signup + +import com.kusitms.connectdog.domain.repository.SignUpRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetVolunteerNicknameDuplication @Inject constructor( + val repository: SignUpRepository +) { + suspend operator fun invoke(nickname: String) = repository.getVolunteerNicknameDuplication(nickname) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitNormalVolunteerSignUpUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitNormalVolunteerSignUpUseCase.kt new file mode 100644 index 000000000..bc6a96e50 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitNormalVolunteerSignUpUseCase.kt @@ -0,0 +1,28 @@ +package com.kusitms.connectdog.domain.usecase.signup + +import com.kusitms.connectdog.domain.repository.SignUpRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class InitNormalVolunteerSignUpUseCase @Inject constructor( + val repository: SignUpRepository +) { + suspend operator fun invoke( + email: String, + password: String, + nickname: String, + profileImageNum: Int, + isOptionAgr: Boolean = true, + phone: String, + name: String + ) = repository.initNormalVolunteerSignUp( + email = email, + password = password, + nickname = nickname, + profileImageNum = profileImageNum, + isOptionAgr = isOptionAgr, + phone = phone, + name = name + ) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitSocialVolunteerSignUpUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitSocialVolunteerSignUpUseCase.kt new file mode 100644 index 000000000..7a6bcc20c --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitSocialVolunteerSignUpUseCase.kt @@ -0,0 +1,28 @@ +package com.kusitms.connectdog.domain.usecase.signup + +import com.kusitms.connectdog.domain.repository.SignUpRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class InitSocialVolunteerSignUpUseCase @Inject constructor( + val repository: SignUpRepository +) { + suspend operator fun invoke( + email: String, + password: String, + nickname: String, + profileImageNum: Int, + isOptionAgr: Boolean = true, + phone: String, + name: String + ) = repository.initNormalVolunteerSignUp( + email = email, + password = password, + nickname = nickname, + profileImageNum = profileImageNum, + isOptionAgr = isOptionAgr, + phone = phone, + name = name + ) +} \ No newline at end of file diff --git a/feature/home/build.gradle.kts b/feature/home/build.gradle.kts index 27f91e5c9..f3436e00e 100644 --- a/feature/home/build.gradle.kts +++ b/feature/home/build.gradle.kts @@ -46,7 +46,7 @@ android { } dependencies { - + implementation(projects.domain) implementation(project(":core:model")) implementation(project(":core:data")) implementation(project(":core:designsystem")) diff --git a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/HomeViewModel.kt b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/HomeViewModel.kt index 0c2a29df0..cac60d7d6 100644 --- a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/HomeViewModel.kt +++ b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/HomeViewModel.kt @@ -4,8 +4,8 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.kusitms.connectdog.core.data.api.model.FcmTokenRequestBody -import com.kusitms.connectdog.core.data.repository.DataStoreRepository import com.kusitms.connectdog.core.data.repository.HomeRepository +import com.kusitms.connectdog.domain.usecase.GetFcmTokenUseCase import com.kusitms.connectdog.feature.home.state.AnnouncementUiState import com.kusitms.connectdog.feature.home.state.ReviewUiState import dagger.hilt.android.lifecycle.HiltViewModel @@ -14,7 +14,6 @@ import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn @@ -24,14 +23,12 @@ import javax.inject.Inject private val TAG = "HomeViewModel" @HiltViewModel -class HomeViewModel -@Inject -constructor( +class HomeViewModel @Inject constructor( private val homeRepository: HomeRepository, - private val dataStoreRepository: DataStoreRepository + private val getFcmTokenUseCase: GetFcmTokenUseCase, ) : ViewModel() { init { - postFcmToken() +// postFcmToken() } private val _errorFlow = MutableSharedFlow() @@ -94,11 +91,8 @@ constructor( ) private fun postFcmToken() = viewModelScope.launch { - val token = dataStoreRepository.fcmTokenFlow.first() - try { - token?.let { homeRepository.postFcmToken(FcmTokenRequestBody(it)) } - } catch (e: Exception) { - Log.d("fcm post", e.message.toString()) + getFcmTokenUseCase().collect { + it?.let { homeRepository.postFcmToken(FcmTokenRequestBody(it)) } } } } diff --git a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/screen/HomeScreen.kt b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/screen/HomeScreen.kt index 875cad7db..848dcf6c4 100644 --- a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/screen/HomeScreen.kt +++ b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/screen/HomeScreen.kt @@ -1,13 +1,10 @@ package com.kusitms.connectdog.feature.home.screen +import android.annotation.SuppressLint import androidx.activity.compose.BackHandler import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -23,47 +20,37 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.outlined.Notifications -import androidx.compose.material3.Divider -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton -import androidx.compose.material3.LocalMinimumInteractiveComponentEnforcement import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.ColorPainter -import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.withStyle -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.kusitms.connectdog.core.designsystem.component.BannerGuideline import com.kusitms.connectdog.core.designsystem.component.ConnectDogReview +import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.NetworkImage import com.kusitms.connectdog.core.designsystem.component.ReviewType +import com.kusitms.connectdog.core.designsystem.component.SearchBar +import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType import com.kusitms.connectdog.core.designsystem.component.text.TextWithIcon -import com.kusitms.connectdog.core.designsystem.theme.ConnectDogTheme -import com.kusitms.connectdog.core.designsystem.theme.Gray1 import com.kusitms.connectdog.core.designsystem.theme.Gray2 import com.kusitms.connectdog.core.designsystem.theme.Gray3 -import com.kusitms.connectdog.core.designsystem.theme.Gray5 import com.kusitms.connectdog.core.model.AnnouncementHome import com.kusitms.connectdog.core.model.Review import com.kusitms.connectdog.feature.home.HomeViewModel @@ -95,29 +82,24 @@ internal fun HomeRoute( viewModel.errorFlow.collectLatest { throwable -> onShowErrorSnackBar(throwable) } } - Column( - modifier = Modifier.fillMaxSize() - ) { - TopAppBar( - onClickSearch = onNavigateToFilterSearch, - onNotificationClick = onNavigateToNotification - ) - HomeScreen( - announcementUiState = announcementUiState, - reviewUiState = reviewUiState, - onNavigateToSearch = onNavigateToSearch, - onNavigateToReview = onNavigateToReview, - onNavigateToDetail = onNavigateToDetail, - onNavigateToGuide = onNavigateToGuide, - onNavigateToReviewDetail = onNavigateToReviewDetail - ) - } + HomeScreen( + announcementUiState = announcementUiState, + reviewUiState = reviewUiState, + onNavigateToFilterSearch = onNavigateToFilterSearch, + onNavigateToSearch = onNavigateToSearch, + onNavigateToReview = onNavigateToReview, + onNavigateToDetail = onNavigateToDetail, + onNavigateToGuide = onNavigateToGuide, + onNavigateToReviewDetail = onNavigateToReviewDetail + ) } +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable private fun HomeScreen( announcementUiState: AnnouncementUiState, reviewUiState: ReviewUiState, + onNavigateToFilterSearch: () -> Unit, onNavigateToSearch: () -> Unit, onNavigateToReview: () -> Unit, onNavigateToDetail: (Long) -> Unit, @@ -125,195 +107,40 @@ private fun HomeScreen( onNavigateToReviewDetail: (Long) -> Unit ) { val scrollState = rememberScrollState() - Column( - modifier = Modifier - .verticalScroll(scrollState) - .fillMaxSize() - ) { - BannerGuideline(onNavigateToGuide) - MoveContent(onClick = { onNavigateToSearch() }, titleRes = R.string.home_navigate_search) - AnnouncementContent(announcementUiState, onClick = onNavigateToDetail) - MoveContent(onClick = { onNavigateToReview() }, titleRes = R.string.home_navigate_review) - ReviewContent(uiState = reviewUiState, onClick = onNavigateToReviewDetail) - Spacer(modifier = Modifier.height(90.dp)) - } -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun TopAppBar( - onClickSearch: () -> Unit, - onNotificationClick: () -> Unit -) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(start = 20.dp, end = 20.dp, top = 16.dp, bottom = 16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - SearchBar( - onClick = onClickSearch, - modifier = Modifier.weight(1f) - ) - Spacer(modifier = Modifier.width(20.dp)) - CompositionLocalProvider(LocalMinimumInteractiveComponentEnforcement provides false) { - IconButton( - onClick = onNotificationClick, - modifier = Modifier.size(24.dp) - ) { - Icon( - imageVector = Icons.Outlined.Notifications, - contentDescription = "Navigate to Search" - ) - } - } - } -} -@Composable -private fun SearchBar( - onClick: () -> Unit, - modifier: Modifier -) { - Box( - modifier = modifier - .height(50.dp) - .border( - width = 1.dp, - color = Gray5, - shape = RoundedCornerShape(90.dp) - ) - .clickable { onClick() }, - contentAlignment = Alignment.CenterStart - ) { - Icon( - modifier = Modifier - .padding(start = 20.dp) - .size(24.dp), - imageVector = Icons.Filled.Search, - tint = Gray3, - contentDescription = "Navigate to Search" - ) - Text( - modifier = Modifier.padding(start = 52.dp), - text = buildAnnotatedString { - withStyle( - SpanStyle( - color = Gray1, - fontSize = 12.sp, - fontWeight = FontWeight.Medium - ) - ) { - append(stringResource(id = R.string.search_bar_title_1)) + Scaffold( + topBar = { + ConnectDogTopAppBar( + titleRes = null, + navigationType = TopAppBarNavigationType.HOME, + actionButtons = { + IconButton(onClick = {}) { + Icon( + imageVector = Icons.Outlined.Notifications, + contentDescription = "Navigate to Search", + modifier = Modifier.clickable { } + ) + } } - withStyle( - SpanStyle( - color = Gray3, - fontSize = 10.sp, - fontWeight = FontWeight.Medium - ) - ) { - append(stringResource(id = R.string.search_bar_title_2)) - } - }, - lineHeight = 15.sp - ) - } -} - -@Composable -private fun StatisticBanner(modifier: Modifier) { - Column(horizontalAlignment = Alignment.End, modifier = modifier) { - Row( - modifier = Modifier.padding(end = 10.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - painter = painterResource(id = R.drawable.ic_info), - contentDescription = "info icon", - modifier = Modifier.padding(2.dp), - tint = Gray3 - ) - Text( - text = stringResource(id = R.string.home_counting_guide), - style = MaterialTheme.typography.labelMedium, - color = Gray3 ) } - Spacer(modifier = Modifier.size(6.dp)) - Box( + ) { + Column( modifier = Modifier - .fillMaxWidth() - .background( - color = MaterialTheme.colorScheme.primaryContainer, - shape = RoundedCornerShape(12.dp) - ) + .verticalScroll(scrollState) + .fillMaxSize() + .padding(top = 48.dp, bottom = 90.dp) ) { - Divider( - color = MaterialTheme.colorScheme.onPrimary, - modifier = Modifier - .height(80.dp) - .width(1.dp) - .align(Alignment.Center) - ) - Row( - horizontalArrangement = Arrangement.SpaceEvenly, - verticalAlignment = Alignment.Bottom, - modifier = Modifier - .height(80.dp) - .fillMaxWidth() - ) { - StatisticInfoItem( - modifier = Modifier.weight(1f), - number = "105", - descriptionRes = R.string.home_need_move_description, - painter = painterResource(id = R.drawable.img_man_dog) - ) - StatisticInfoItem( - modifier = Modifier.weight(1f), - number = "22", - descriptionRes = R.string.home_moved_description, - painter = painterResource(id = R.drawable.img_woman) - ) - } + SearchBar(onClick = onNavigateToFilterSearch) + BannerGuideline(onNavigateToGuide) + MoveContent(onClick = { onNavigateToSearch() }, titleRes = R.string.home_navigate_search) + AnnouncementContent(announcementUiState, onClick = onNavigateToDetail) + MoveContent(onClick = { onNavigateToReview() }, titleRes = R.string.home_navigate_review) + ReviewContent(uiState = reviewUiState, onClick = onNavigateToReviewDetail) } } } -@Composable -private fun StatisticInfoItem( - modifier: Modifier = Modifier, - number: String = "0", - descriptionRes: Int, - painter: Painter -) { - Row { - Column(horizontalAlignment = Alignment.Start) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text( - text = number, - style = MaterialTheme.typography.titleSmall, - fontSize = 20.sp, - color = MaterialTheme.colorScheme.onSurface - ) - Text( - text = stringResource(id = R.string.home_dog_unit), - style = MaterialTheme.typography.labelMedium, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.onSurface, - modifier = Modifier.padding(start = 2.dp) - ) - } - Text( - text = stringResource(id = descriptionRes), - style = MaterialTheme.typography.labelMedium, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.onSurface - ) - } - Image(painter = painter, contentDescription = "mandog") - } -} @Composable fun MoveContent( @@ -334,7 +161,7 @@ fun MoveContent( ) IconButton(onClick = { onClick() }) { Icon( - painter = painterResource(id = com.kusitms.connectdog.core.designsystem.R.drawable.ic_right_arrow), + painter = painterResource(id = R.drawable.ic_right_arrow), contentDescription = "move to another screen", modifier = Modifier.size(24.dp), tint = Gray2 @@ -405,9 +232,7 @@ fun AnnouncementLoading( modifier: Modifier, arrangement: Arrangement.Horizontal ) { - val list = List(4) { - AnnouncementHome("", "이동봉사 위치", "YY.mm.dd(요일)", -1, "", "") - } + val list = List(4) { AnnouncementHome.loading() } LazyRow(horizontalArrangement = arrangement, modifier = modifier) { items(list) { AnnouncementCardContent(announcementHome = it, onClick = {}) @@ -509,22 +334,3 @@ private fun ReviewCardContent( ConnectDogReview(review = review, modifier = Modifier.width(272.dp), type = ReviewType.HOME) } } - -@Preview -@Composable -private fun HomeScreenPreview() { - ConnectDogTheme { - Column(modifier = Modifier.background(Color.White)) { - TopAppBar(onClickSearch = {}, onNotificationClick = {}) - HomeScreen( - announcementUiState = AnnouncementUiState.Empty, - reviewUiState = ReviewUiState.Empty, - {}, - {}, - {}, - {}, - {} - ) - } - } -} diff --git a/feature/home/src/main/res/values/string.xml b/feature/home/src/main/res/values/string.xml index 4f9e04082..2773f2773 100644 --- a/feature/home/src/main/res/values/string.xml +++ b/feature/home/src/main/res/values/string.xml @@ -43,8 +43,6 @@ 이동했어요! 지금 필요한 이동봉사 공고 생생한 이동봉사 후기 - 딱 맞는 이동봉사를 찾아보세요!\n - 출발지·도착지·일정 이동봉사 후기 diff --git a/feature/intermediator/build.gradle.kts b/feature/intermediator/build.gradle.kts index 19f2de1f9..569104159 100644 --- a/feature/intermediator/build.gradle.kts +++ b/feature/intermediator/build.gradle.kts @@ -46,7 +46,7 @@ android { } dependencies { - + implementation(projects.domain) implementation(project(":core:model")) implementation(project(":core:data")) implementation(project(":core:designsystem")) diff --git a/feature/intermediator/src/main/java/com/kusitms/connectdog/feature/intermediator/viewmodel/InterHomeViewModel.kt b/feature/intermediator/src/main/java/com/kusitms/connectdog/feature/intermediator/viewmodel/InterHomeViewModel.kt index 9e9dba5d2..7cc10eadb 100644 --- a/feature/intermediator/src/main/java/com/kusitms/connectdog/feature/intermediator/viewmodel/InterHomeViewModel.kt +++ b/feature/intermediator/src/main/java/com/kusitms/connectdog/feature/intermediator/viewmodel/InterHomeViewModel.kt @@ -4,7 +4,6 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.kusitms.connectdog.core.data.api.model.FcmTokenRequestBody -import com.kusitms.connectdog.core.data.repository.DataStoreRepository import com.kusitms.connectdog.core.data.repository.InterManagementRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -15,12 +14,12 @@ import javax.inject.Inject @HiltViewModel class InterHomeViewModel @Inject constructor( - private val dataStoreRepository: DataStoreRepository, +// private val dataStoreRepository: DataStoreRepository, private val repository: InterManagementRepository ) : ViewModel() { - init { - postFcmToken() - } +// init { +// postFcmToken() +// } private val _profileImage = MutableStateFlow("") val profileImage: StateFlow get() = _profileImage @@ -67,11 +66,11 @@ class InterHomeViewModel @Inject constructor( } private fun postFcmToken() = viewModelScope.launch { - val token = dataStoreRepository.fcmTokenFlow.first() - try { - token?.let { repository.postFcmToken(FcmTokenRequestBody(it)) } - } catch (e: Exception) { - Log.d("fcm post", e.message.toString()) - } +// val token = dataStoreRepository.fcmTokenFlow.first() +// try { +// token?.let { repository.postFcmToken(FcmTokenRequestBody(it)) } +// } catch (e: Exception) { +// Log.d("fcm post", e.message.toString()) +// } } } diff --git a/feature/login/build.gradle.kts b/feature/login/build.gradle.kts index 945feb1e5..e1f0491ef 100644 --- a/feature/login/build.gradle.kts +++ b/feature/login/build.gradle.kts @@ -1,3 +1,6 @@ +import org.jetbrains.kotlin.konan.properties.Properties +import com.kusitms.connectdog.Configuration + @Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed plugins { alias(libs.plugins.com.android.library) @@ -9,10 +12,20 @@ plugins { android { namespace = "com.kusitms.connectdog.feature.login" - compileSdk = 33 + compileSdk = Configuration.minSdk defaultConfig { - minSdk = 30 + minSdk = Configuration.minSdk + + val localProperties = Properties() + val localPropertiesFile = rootProject.file("local.properties") + if (localPropertiesFile.exists()) { localPropertiesFile.inputStream().use { localProperties.load(it) } } + + val naverClientId: String = localProperties.getProperty("NAVER_CLIENT_ID") ?: "" + val naverClientSecret: String = localProperties.getProperty("NAVER_CLIENT_SECRET") ?: "" + + buildConfigField("String", "NAVER_CLIENT_ID", "\"$naverClientId\"") + buildConfigField("String", "NAVER_CLIENT_SECRET", "\"$naverClientSecret\"") testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") @@ -37,6 +50,7 @@ android { buildFeatures { compose = true + buildConfig = true } composeOptions { kotlinCompilerExtensionVersion = "1.4.3" @@ -44,13 +58,13 @@ android { } dependencies { - - implementation(project(":core:designsystem")) - implementation(project(":core:util")) + implementation(projects.domain) + implementation(projects.core.model) + implementation(projects.core.designsystem) + implementation(projects.core.util) + implementation(projects.core.data) implementation(libs.androidx.core.splashscreen) - implementation(project(mapOf("path" to ":core:data"))) - kapt(libs.hilt.compiler) implementation(libs.hilt.android) @@ -81,6 +95,4 @@ dependencies { implementation(libs.kakao.oauth) implementation(libs.naver.oauth) - - implementation(libs.androidx.junit.ktx) } diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/LoginNavigation.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/navigation/LoginNavigation.kt similarity index 72% rename from feature/login/src/main/java/com/kusitms/connectdog/feature/login/LoginNavigation.kt rename to feature/login/src/main/java/com/kusitms/connectdog/feature/login/navigation/LoginNavigation.kt index d94e15894..ab068e802 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/LoginNavigation.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/navigation/LoginNavigation.kt @@ -1,20 +1,22 @@ -package com.kusitms.connectdog.feature.login +package com.kusitms.connectdog.feature.login.navigation import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavType import androidx.navigation.compose.composable import androidx.navigation.navArgument +import com.kusitms.connectdog.core.util.AccountType import com.kusitms.connectdog.core.util.UserType import com.kusitms.connectdog.feature.login.screen.EmailSearchResultScreen import com.kusitms.connectdog.feature.login.screen.EmailSearchScreen import com.kusitms.connectdog.feature.login.screen.LoginRoute import com.kusitms.connectdog.feature.login.screen.NormalLoginScreen -import com.kusitms.connectdog.feature.login.screen.PasswordSearchAuthScreen -import com.kusitms.connectdog.feature.login.screen.PasswordSearchScreen +import com.kusitms.connectdog.feature.login.screen.EmailAuthForPasswordResetScreen +import com.kusitms.connectdog.feature.login.screen.NoAccountScreen +import com.kusitms.connectdog.feature.login.screen.PasswordResetScreen fun NavController.navigateToLoginRoute() { - navigate(LoginRoute.route) { + navigate(LoginRoute.ROUTE) { popUpTo(graph.id) { inclusive = true } @@ -22,11 +24,11 @@ fun NavController.navigateToLoginRoute() { } fun NavController.navigateNormalLogin(userType: UserType) { - navigate("${LoginRoute.normal_login}/$userType") + navigate("${LoginRoute.NORMAL_LOGIN}/$userType") } fun NavController.navigateEmailSearch(userType: UserType) { - navigate("${LoginRoute.email_search}/$userType") + navigate("${LoginRoute.EMAIL_SEARCH}/$userType") } fun NavController.navigateEmailSearchComplete(email: String) { @@ -38,7 +40,11 @@ fun NavController.navigatePasswordSearchAuth(userType: UserType) { } fun NavController.navigatePasswordSearch(userType: UserType) { - navigate("${LoginRoute.password_search}/$userType") + navigate("${LoginRoute.PASSWORD_SEARCH}/$userType") +} + +fun NavController.navigateToNoAccount(accountType: AccountType) { + navigate("${LoginRoute.NO_ACCOUNT}/$accountType") } fun NavGraphBuilder.loginNavGraph( @@ -55,9 +61,10 @@ fun NavGraphBuilder.loginNavGraph( onNavigateToPasswordSearchAuth: (UserType) -> Unit, onNavigateToLoginRoute: () -> Unit, onSendMessage: (String) -> Unit, - onVerifyCode: (String, (Boolean) -> Unit) -> Unit + onVerifyCode: (String, (Boolean) -> Unit) -> Unit, + onNavigateToNoAccount: (AccountType) -> Unit ) { - composable(route = LoginRoute.route) { + composable(route = LoginRoute.ROUTE) { LoginRoute( finish, onNavigateToNormalLogin, @@ -70,7 +77,7 @@ fun NavGraphBuilder.loginNavGraph( } composable( - route = "${LoginRoute.normal_login}/{type}", + route = "${LoginRoute.NORMAL_LOGIN}/{type}", arguments = listOf( navArgument("type") { type = NavType.EnumType(UserType::class.java) @@ -79,17 +86,15 @@ fun NavGraphBuilder.loginNavGraph( ) { NormalLoginScreen( onBackClick = onBackClick, - userType = it.arguments!!.getSerializable("type") as UserType, onNavigateToSignUp = onNavigateToSignup, onNavigateToVolunteerHome = onNavigateToVolunteer, - onNavigateToIntermediatorHome = onNavigateToIntermediatorHome, onNavigateToEmailSearch = onNavigateToEmailSearch, onNavigateToPasswordSearch = onNavigateToPasswordSearchAuth ) } composable( - route = "${LoginRoute.email_search}/{type}", + route = "${LoginRoute.EMAIL_SEARCH}/{type}", arguments = listOf( navArgument("type") { type = NavType.EnumType(UserType::class.java) @@ -122,14 +127,14 @@ fun NavGraphBuilder.loginNavGraph( } composable( - route = "${LoginRoute.password_search}/{type}", + route = "${LoginRoute.PASSWORD_SEARCH}/{type}", arguments = listOf( navArgument("type") { type = NavType.EnumType(UserType::class.java) } ) ) { - PasswordSearchScreen( + PasswordResetScreen( onBackClick = onBackClick, userType = it.arguments!!.getSerializable("type") as UserType, imeHeight = imeHeight, @@ -145,20 +150,36 @@ fun NavGraphBuilder.loginNavGraph( } ) ) { - PasswordSearchAuthScreen( + EmailAuthForPasswordResetScreen( onBackClick = onBackClick, imeHeight = imeHeight, onNavigateToPasswordSearch = onNavigateToPasswordSearch, - userType = it.arguments!!.getSerializable("type") as UserType + onNavigateToNoAccount = onNavigateToNoAccount, + userType = it.arguments!!.getSerializable("type") as UserType, + ) + } + + composable( + route = "${LoginRoute.NO_ACCOUNT}/{accountType}", + arguments = listOf( + navArgument("accountType") { + type = NavType.EnumType(AccountType::class.java) + } + ) + ) { + NoAccountScreen( + accountType = it.arguments!!.getSerializable("accountType") as AccountType, + onNavigateToLoginRoute = onNavigateToLoginRoute ) } } object LoginRoute { - const val route = "login" - const val normal_login = "normal_login" - const val email_search = "email_search" - const val password_search = "password_search" + const val ROUTE = "login" + const val NORMAL_LOGIN = "normal_login" + const val EMAIL_SEARCH = "email_search" + const val PASSWORD_SEARCH = "password_search" const val email_search_complete = "email_search_complete" const val password_search_auth = "password_search_auth" + const val NO_ACCOUNT = "no_account" } diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordSearchAuthScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailAuthForPasswordResetScreen.kt similarity index 57% rename from feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordSearchAuthScreen.kt rename to feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailAuthForPasswordResetScreen.kt index 0f549f390..39f818a5d 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordSearchAuthScreen.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailAuthForPasswordResetScreen.kt @@ -11,11 +11,9 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType @@ -23,21 +21,23 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton -import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextFieldWithButton +import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.Gray5 -import com.kusitms.connectdog.core.designsystem.theme.PetOrange -import com.kusitms.connectdog.core.designsystem.theme.Red1 +import com.kusitms.connectdog.core.util.AccountType import com.kusitms.connectdog.core.util.UserType import com.kusitms.connectdog.feature.login.R -import com.kusitms.connectdog.feature.login.viewmodel.PasswordSearchAuthViewModel +import com.kusitms.connectdog.feature.login.state.EmailAuthForPasswordResetSideEffect +import com.kusitms.connectdog.feature.login.viewmodel.EmailAuthForPasswordResetViewModel +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable -fun PasswordSearchAuthScreen( +fun EmailAuthForPasswordResetScreen( onBackClick: () -> Unit, onNavigateToPasswordSearch: (UserType) -> Unit, + onNavigateToNoAccount: (AccountType) -> Unit, imeHeight: Int, userType: UserType ) { @@ -53,6 +53,7 @@ fun PasswordSearchAuthScreen( Content( imeHeight = imeHeight, onNavigateToPasswordSearch = onNavigateToPasswordSearch, + onNavigateToNoAccount = onNavigateToNoAccount, userType = userType ) } @@ -62,15 +63,21 @@ fun PasswordSearchAuthScreen( private fun Content( imeHeight: Int, onNavigateToPasswordSearch: (UserType) -> Unit, + onNavigateToNoAccount: (AccountType) -> Unit, userType: UserType, - viewModel: PasswordSearchAuthViewModel = hiltViewModel() + viewModel: EmailAuthForPasswordResetViewModel = hiltViewModel() ) { val focusManager = LocalFocusManager.current val interactionSource = remember { MutableInteractionSource() } - val context = LocalContext.current - val isValidEmail by viewModel.isValidEmail.collectAsState() - val isEmailVerified by viewModel.isEmailVerified.collectAsState() - val isEmailError by viewModel.isEmailError.collectAsState() + + val uiState by viewModel.collectAsState() + + viewModel.collectSideEffect { + when(it) { + EmailAuthForPasswordResetSideEffect.NavigateToFail -> onNavigateToNoAccount(AccountType.PASSWORD) + EmailAuthForPasswordResetSideEffect.NavigateToPasswordReset -> onNavigateToPasswordSearch(userType) + } + } Column( modifier = Modifier @@ -78,7 +85,7 @@ private fun Content( .padding(top = 80.dp, bottom = 24.dp) .padding(horizontal = 20.dp) .clickable( - onClick = { focusManager.clearFocus() }, + onClick = focusManager::clearFocus, indication = null, interactionSource = interactionSource ) @@ -90,43 +97,29 @@ private fun Content( lineHeight = 28.sp ) Spacer(modifier = Modifier.height(40.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.email, - width = 62, - height = 27, - textFieldLabel = "이메일", + ConnectDogTextField( + text = uiState.email, + label = "이메일", placeholder = "이메일 입력", - buttonLabel = "인증 요청", - isError = (isValidEmail ?: false) || (isEmailError == true), - onTextChanged = { - viewModel.updateEmail(it) - viewModel.updateEmailValidity() - }, - borderColor = if (isValidEmail == false) PetOrange else Gray5, - onClick = { viewModel.postEmail(context, userType) }, - padding = 5 + onTextChanged = viewModel::onEmailChanged, ) Spacer(modifier = Modifier.height(12.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.certificationNumber, - width = 62, - height = 27, - textFieldLabel = "인증 번호", - placeholder = "숫자 6자리", - buttonLabel = "인증 확인", - keyboardType = KeyboardType.Text, - onTextChanged = { viewModel.updateCertificationNumber(it) }, - borderColor = if (viewModel.isEmailVerified.value == true) PetOrange else if (viewModel.isEmailVerified.value == false) Red1 else Gray5, - onClick = { viewModel.checkCertificationNumber(context) }, - padding = 5, - isError = isEmailVerified == false - ) + if(uiState.isSendAuthCode) { + ConnectDogTextField( + text = uiState.inputAuthCode, + label = "인증 번호", + placeholder = "숫자 6자리", + keyboardType = KeyboardType.Text, + onTextChanged = viewModel::onInputAuthCodeChanged, + isError = uiState.isAuthCodeError + ) + } Spacer(modifier = Modifier.weight(1f)) ConnectDogBottomButton( - onClick = { onNavigateToPasswordSearch(userType) }, - content = "인증 완료", - enabled = isEmailVerified == true + onClick = { viewModel.onNextButtonClick(userType) }, + content = uiState.bottomButtonText, + enabled = uiState.enableNext ) - Spacer(modifier = Modifier.height(imeHeight.dp)) + Spacer(modifier = Modifier.height((imeHeight+32).dp)) } } diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchResultScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchResultScreen.kt index ae2bde448..4e7f06e9b 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchResultScreen.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchResultScreen.kt @@ -28,7 +28,7 @@ import com.kusitms.connectdog.feature.login.R @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable -internal fun EmailSearchResultScreen( +fun EmailSearchResultScreen( onBackClick: () -> Unit, email: String, navigateToLoginRoute: () -> Unit diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchScreen.kt index 8debff384..2f671f1f2 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchScreen.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchScreen.kt @@ -1,34 +1,40 @@ package com.kusitms.connectdog.feature.login.screen import android.annotation.SuppressLint -import android.widget.Toast +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton -import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextFieldWithButton +import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType +import com.kusitms.connectdog.core.designsystem.theme.Gray60 +import com.kusitms.connectdog.core.designsystem.theme.Gray80 +import com.kusitms.connectdog.core.designsystem.theme.Red1 import com.kusitms.connectdog.core.util.UserType import com.kusitms.connectdog.feature.login.R -import com.kusitms.connectdog.feature.login.viewmodel.SearchViewModel +import com.kusitms.connectdog.feature.login.state.EmailSearchSideEffect +import com.kusitms.connectdog.feature.login.viewmodel.EmailSearchViewModel +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable @@ -39,7 +45,7 @@ fun EmailSearchScreen( onSendMessageClick: (String) -> Unit, onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, userType: UserType, - viewModel: SearchViewModel = hiltViewModel() + viewModel: EmailSearchViewModel = hiltViewModel() ) { Scaffold( topBar = { @@ -68,15 +74,15 @@ private fun Content( onSendMessageClick: (String) -> Unit, onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, userType: UserType, - viewModel: SearchViewModel + viewModel: EmailSearchViewModel ) { - val context = LocalContext.current - val isSendNumber by remember { viewModel.isSendNumber }.collectAsState() - val isCertified by remember { viewModel.isCertified }.collectAsState() + val uiState by viewModel.collectAsState() - LaunchedEffect(key1 = viewModel) { - viewModel.findEmail.collect { - it?.let { navigateToCompleteScreen(it) } + viewModel.collectSideEffect { sideEffect -> + when(sideEffect) { + is EmailSearchSideEffect.NavigateToEmailSearchResult -> { + uiState.email?.let { navigateToCompleteScreen(it) } + } } } @@ -87,68 +93,66 @@ private fun Content( ) { Spacer(modifier = Modifier.height(80.dp)) Text( - text = "휴대폰 번호 인증을\n진행해주세요", + text = stringResource(id = R.string.email_auth_title), fontSize = 20.sp, fontWeight = FontWeight.Bold, lineHeight = 25.sp ) Spacer(modifier = Modifier.height(40.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.phoneNumber, - width = 62, - height = 27, - textFieldLabel = "휴대폰 번호", + ConnectDogTextField( + text = uiState.phoneNumber, + label = stringResource(id = R.string.phone_number), keyboardType = KeyboardType.Number, placeholder = "- 빼고 입력", - buttonLabel = "인증 요청", - onTextChanged = { if (it.length <= 11) viewModel.updatePhoneNumber(it) }, - onClick = { - if (viewModel.phoneNumber.isEmpty()) { - Toast.makeText(context, "휴대폰 번호를 입력해주세요", Toast.LENGTH_SHORT).show() - } else if (viewModel.phoneNumber.length == 11) { - onSendMessageClick(viewModel.phoneNumber) - Toast.makeText(context, "인증번호를 전송하였습니다.", Toast.LENGTH_SHORT).show() - viewModel.updateIsSendNumber(true) - } else { - Toast.makeText(context, "올바른 휴대폰 번호를 입력해주세요", Toast.LENGTH_SHORT).show() - } - }, - padding = 5 + onTextChanged = viewModel::onPhoneNumberChanged, ) Spacer(modifier = Modifier.height(12.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.certificationNumber, - width = 62, - height = 27, - textFieldLabel = "인증번호", - keyboardType = KeyboardType.Number, - placeholder = "인증번호 6자리", - buttonLabel = "인증 확인", - onTextChanged = { if (it.length <= 6) viewModel.updateCertificationNumber(it) }, - onClick = { - if (!isSendNumber) { - Toast.makeText(context, "먼저 인증번호를 전송해주세요", Toast.LENGTH_SHORT).show() - } else { - if (viewModel.certificationNumber.isEmpty()) { - Toast.makeText(context, "인증 번호를 입력해주세요", Toast.LENGTH_SHORT).show() - } else if (viewModel.certificationNumber.length == 6) { - onVerifyCodeClick(it) { viewModel.updateIsCertified(it) } - } else { - Toast.makeText(context, "인증 번호는 6자리로 입력해주세요", Toast.LENGTH_SHORT).show() - } - } - }, - padding = 5 - ) + if(uiState.isSendAuthCode) { + ConnectDogTextField( + text = uiState.authCode, + label = "인증번호", + keyboardType = KeyboardType.Number, + placeholder = "인증번호 6자리", + onTextChanged = viewModel::onAuthCodeChanged, + isError = (uiState.isAuthCodeError == true) + ) + if(uiState.isAuthCodeError == true) { + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = "올바른 인증번호를 입력해주세요", + fontSize = 10.sp, + color = Red1 + ) + } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 12.dp), + horizontalArrangement = Arrangement.Center + ) { + Text( + text = "인증번호가 오지 않는다면?", + color = Gray60, + fontSize = 12.sp + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + modifier = Modifier.clickable { }, + text = "재발송", + fontSize = 12.sp, + color = Gray80, + fontWeight = FontWeight.SemiBold + ) + } + } Spacer(modifier = Modifier.weight(1f)) ConnectDogBottomButton( - content = "다음", - enabled = isCertified, - onClick = { viewModel.test(userType = userType, context = context) }, - modifier = - Modifier + modifier = Modifier .fillMaxWidth() - .height(56.dp) + .height(56.dp), + content = uiState.bottomButtonText, + enabled = uiState.enableNext, + onClick = { viewModel.onNextClick(userType, onSendMessageClick, onVerifyCodeClick) }, ) Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/LoginScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/LoginScreen.kt index 6a34c0c59..3c4f246a7 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/LoginScreen.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/LoginScreen.kt @@ -15,14 +15,12 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Tab import androidx.compose.material3.TabRow import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -41,6 +39,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import com.google.accompanist.pager.ExperimentalPagerApi import com.google.accompanist.pager.HorizontalPager import com.google.accompanist.pager.rememberPagerState +import com.kusitms.connectdog.core.designsystem.component.ActionRow import com.kusitms.connectdog.core.designsystem.component.ConnectDogIconBottomButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField @@ -49,12 +48,14 @@ import com.kusitms.connectdog.core.designsystem.theme.Gray2 import com.kusitms.connectdog.core.designsystem.theme.KAKAO import com.kusitms.connectdog.core.designsystem.theme.NAVER import com.kusitms.connectdog.core.designsystem.theme.PetOrange -import com.kusitms.connectdog.core.util.SocialType import com.kusitms.connectdog.core.util.UserType import com.kusitms.connectdog.feature.login.R +import com.kusitms.connectdog.feature.login.state.LoginSideEffect import com.kusitms.connectdog.feature.login.viewmodel.LoginViewModel -import com.kusitms.connectdog.feature.login.viewmodel.Provider import kotlinx.coroutines.launch +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect +import com.kusitms.connectdog.core.designsystem.R.drawable as DR @Composable internal fun LoginRoute( @@ -94,7 +95,7 @@ fun LoginScreen( modifier = Modifier .fillMaxSize() .clickable( - onClick = { focusManager.clearFocus() }, + onClick = focusManager::clearFocus, indication = null, interactionSource = interactionSource ) @@ -115,11 +116,11 @@ fun LoginScreen( ) Spacer(modifier = Modifier.weight(1f)) Image( - painter = painterResource(id = com.kusitms.connectdog.core.designsystem.R.drawable.ic_main), - contentDescription = null, modifier = Modifier .fillMaxWidth() - .aspectRatio(1f) + .aspectRatio(1f), + painter = painterResource(id = DR.ic_main), + contentDescription = null, ) } } @@ -135,9 +136,7 @@ private fun LoginContent( onNavigateToPasswordSearch: (UserType) -> Unit ) { val pages = listOf("이동봉사자 회원", "이동봉사 모집자 회원") - Column( - modifier = Modifier.height(340.dp) - ) { + Column { val pagerState = rememberPagerState() val coroutineScope = rememberCoroutineScope() @@ -146,8 +145,8 @@ private fun LoginContent( .height(37.dp) .fillMaxWidth(0.5f) .padding( - start = if (pagerState.currentPage == 0) 0.dp else 10.dp, - end = if (pagerState.currentPage == 0) 10.dp else 0.dp + start = if (pagerState.currentPage == 0) 0.dp else 33.dp, + end = if (pagerState.currentPage == 0) 33.dp else 0.dp ) .align(if (pagerState.currentPage == 0) Alignment.End else Alignment.Start) ) { @@ -160,8 +159,7 @@ private fun LoginContent( } TabRow( - modifier = Modifier - .padding(start = 10.dp, end = 10.dp), + modifier = Modifier.padding(horizontal = 10.dp), selectedTabIndex = pagerState.currentPage ) { pages.forEachIndexed { index, title -> @@ -177,17 +175,15 @@ private fun LoginContent( ) }, selected = pagerState.currentPage == index, - onClick = { - coroutineScope.launch { - pagerState.scrollToPage(index) - } - } + onClick = { coroutineScope.launch { pagerState.scrollToPage(index) } } ) } } + HorizontalPager( + modifier = Modifier.height(400.dp), count = pages.size, - state = pagerState + state = pagerState, ) { when (it) { 0 -> Volunteer( @@ -213,33 +209,32 @@ private fun Volunteer( onNavigateToSignup: (UserType) -> Unit, onNavigateToVolunteerHome: () -> Unit, viewModel: LoginViewModel = hiltViewModel() -) { +) { val context = LocalContext.current - val socialType by viewModel.socialType.collectAsState() - socialType?.let { - when (it) { - SocialType.VOLUNTEER -> onNavigateToVolunteerHome() - SocialType.GUEST -> onNavigateToSignup(UserType.SOCIAL_VOLUNTEER) + viewModel.collectSideEffect { sideEffect -> + when (sideEffect) { + is LoginSideEffect.NavigateToHome -> onNavigateToVolunteerHome() + is LoginSideEffect.NavigateToSignUp -> onNavigateToSignup(UserType.SOCIAL_VOLUNTEER) } } Column( - horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .fillMaxHeight() - .padding(top = 32.dp) + .padding(top = 25.dp), + horizontalAlignment = Alignment.CenterHorizontally, ) { Spacer(modifier = Modifier.height(20.dp)) ConnectDogIconBottomButton( - iconId = R.drawable.ic_kakao, - contentDescription = "kakao login", - onClick = { viewModel.initSocialLogin(Provider.KAKAO, context) }, - content = stringResource(id = R.string.kakao_login), modifier = Modifier .fillMaxWidth() .padding(horizontal = 20.dp), color = KAKAO, + iconId = R.drawable.ic_kakao, + contentDescription = "kakao login", + onClick = { viewModel.initKakaoLogin(context) }, + content = stringResource(id = R.string.kakao_login), textColor = Color(0xFF373737) ) Spacer(modifier = Modifier.height(10.dp)) @@ -250,11 +245,14 @@ private fun Volunteer( color = NAVER, iconId = R.drawable.ic_naver, contentDescription = "naver login", - onClick = { viewModel.initSocialLogin(Provider.NAVER, context) }, + onClick = { viewModel.initNaverLogin(context) }, content = stringResource(id = R.string.naver_login) ) Spacer(modifier = Modifier.height(30.dp)) - SignUpOrLogin(onNavigateToSignup, onNavigateToNormalLogin, UserType.NORMAL_VOLUNTEER) + ActionRow( + stringResource(id = R.string.email_signup) to { onNavigateToSignup(UserType.NORMAL_VOLUNTEER) }, + stringResource(id = R.string.email_login) to { onNavigateToNormalLogin(UserType.NORMAL_VOLUNTEER) } + ) } } @@ -266,11 +264,12 @@ private fun Intermediator( onNavigateToPasswordSearch: (UserType) -> Unit, viewModel: LoginViewModel = hiltViewModel() ) { - val isLoginSuccessful by viewModel.isLoginSuccessful.collectAsState() + val uiState by viewModel.collectAsState() - LaunchedEffect(key1 = viewModel) { - viewModel.isLoginSuccessful.collect { - if (it == true) { onNavigateToIntermediatorHome() } + viewModel.collectSideEffect { + when(it) { + is LoginSideEffect.NavigateToHome -> onNavigateToIntermediatorHome() + is LoginSideEffect.NavigateToSignUp -> null } } @@ -278,70 +277,38 @@ private fun Intermediator( verticalArrangement = Arrangement.Top, horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier - .padding(top = 32.dp, start = 20.dp, end = 20.dp) .fillMaxHeight() + .padding(top = 25.dp) + .padding(horizontal = 20.dp) ) { ConnectDogTextField( - text = viewModel.email, - label = "이메일", - placeholder = "이메일 입력", + text = uiState.email, + label = stringResource(id = R.string.email), + placeholder = stringResource(id = R.string.input_email), keyboardType = KeyboardType.Text, - onTextChanged = { viewModel.updateEmail(it) }, - isError = (isLoginSuccessful == false) + onTextChanged = viewModel::onEmailChanged, + isError = (uiState.isLoginSuccessful == false) ) Spacer(modifier = Modifier.height(12.dp)) ConnectDogTextField( - text = viewModel.password, - label = "비밀번호", - placeholder = "비밀번호 입력", + text = uiState.password, + label = stringResource(id = R.string.password), + placeholder = stringResource(id = R.string.input_password), keyboardType = KeyboardType.Password, - onTextChanged = { viewModel.updatePassword(it) }, - isError = (isLoginSuccessful == false) + onTextChanged = viewModel::onPasswordChanged, + isError = (uiState.isLoginSuccessful == false) ) Spacer(modifier = Modifier.height(12.dp)) ConnectDogNormalButton( - modifier = Modifier - .fillMaxWidth(), + modifier = Modifier.fillMaxWidth(), content = stringResource(id = R.string.login), - onClick = { - viewModel.initIntermediatorLogin() - } + onClick = viewModel::initIntermediatorLogin ) Spacer(modifier = Modifier.height(30.dp)) - AccountFind( - onNavigateToSignup = onNavigateToSignup, - onNavigateToEmailSearch = { onNavigateToEmailSearch(UserType.INTERMEDIATOR) }, - onNavigateToPasswordSearch = { onNavigateToPasswordSearch(UserType.INTERMEDIATOR) }, - userType = UserType.INTERMEDIATOR - ) - } -} - -@Composable -private fun SignUpOrLogin( - onNavigateToSignup: (UserType) -> Unit, - onNavigateToNormalLogin: (UserType) -> Unit, - userType: UserType -) { - Row { - Text( - modifier = Modifier.clickable { onNavigateToSignup(userType) }, - text = "이메일로 회원가입", - fontSize = 12.sp, - color = Gray2 - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - text = "|", - fontSize = 12.sp, - color = Gray2 - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - modifier = Modifier.clickable { onNavigateToNormalLogin(userType) }, - text = "이메일 로그인", - fontSize = 12.sp, - color = Gray2 + ActionRow( + stringResource(id = R.string.email_signup) to { onNavigateToSignup(UserType.INTERMEDIATOR) }, + stringResource(id = R.string.email_search) to { onNavigateToEmailSearch(UserType.INTERMEDIATOR) }, + stringResource(id = R.string.password_search) to { onNavigateToPasswordSearch(UserType.INTERMEDIATOR) } ) } } diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NoAccountScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NoAccountScreen.kt new file mode 100644 index 000000000..509f37a34 --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NoAccountScreen.kt @@ -0,0 +1,57 @@ +package com.kusitms.connectdog.feature.login.screen + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton +import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar +import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType +import com.kusitms.connectdog.core.designsystem.theme.Gray100 +import com.kusitms.connectdog.core.designsystem.theme.Gray60 +import com.kusitms.connectdog.core.util.AccountType +import com.kusitms.connectdog.feature.login.R + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun NoAccountScreen( + accountType: AccountType, + onNavigateToLoginRoute: () -> Unit, +) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 20.dp) + .padding(vertical = 32.dp), + ) { + Spacer(modifier = Modifier.height(48.dp)) + Text( + text = stringResource(id = R.string.no_account_title), + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + color = Gray100 + ) + Spacer(modifier = Modifier.height(12.dp)) + Text( + text = stringResource(id = R.string.no_account_subtitle), + fontSize = 15.sp, + fontWeight = FontWeight.Normal, + color = Gray60 + ) + Spacer(modifier = Modifier.weight(1f)) + ConnectDogBottomButton( + content = "처음으로 돌아가기", + onClick = onNavigateToLoginRoute + ) + } +} \ No newline at end of file diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NormalLoginScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NormalLoginScreen.kt index 728995ed1..c86a4b302 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NormalLoginScreen.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NormalLoginScreen.kt @@ -4,70 +4,59 @@ import android.annotation.SuppressLint import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel -import com.kusitms.connectdog.core.designsystem.R +import com.kusitms.connectdog.core.designsystem.R as DR +import com.kusitms.connectdog.core.designsystem.component.ActionRow import com.kusitms.connectdog.core.designsystem.component.ConnectDogErrorCard import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.Gray2 import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.feature.login.R +import com.kusitms.connectdog.feature.login.state.LoginSideEffect import com.kusitms.connectdog.feature.login.viewmodel.LoginViewModel - -private const val TAG = "EmailLoginScreen" +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable internal fun NormalLoginScreen( - userType: UserType, onBackClick: () -> Unit, onNavigateToSignUp: (UserType) -> Unit, onNavigateToVolunteerHome: () -> Unit, - onNavigateToIntermediatorHome: () -> Unit, onNavigateToEmailSearch: (UserType) -> Unit, onNavigateToPasswordSearch: (UserType) -> Unit, viewModel: LoginViewModel = hiltViewModel() ) { val focusManager = LocalFocusManager.current val interactionSource = remember { MutableInteractionSource() } - val isLoginSuccessful by viewModel.isLoginSuccessful.collectAsState() - LaunchedEffect(key1 = viewModel) { - viewModel.isLoginSuccessful.collect { - if (it == true) { - when (userType) { - UserType.INTERMEDIATOR -> onNavigateToIntermediatorHome() - else -> onNavigateToVolunteerHome() - } - } + viewModel.collectSideEffect { + when (it) { + is LoginSideEffect.NavigateToHome -> onNavigateToVolunteerHome() + is LoginSideEffect.NavigateToSignUp -> null } } @@ -80,11 +69,7 @@ internal fun NormalLoginScreen( ), topBar = { ConnectDogTopAppBar( - titleRes = when (userType) { - UserType.SOCIAL_VOLUNTEER -> R.string.volunteer_login - UserType.NORMAL_VOLUNTEER -> R.string.volunteer_login - UserType.INTERMEDIATOR -> R.string.intermediator_login - }, + titleRes = DR.string.volunteer_login, navigationType = TopAppBarNavigationType.BACK, navigationIconContentDescription = "Navigation icon", onNavigationClick = onBackClick @@ -96,8 +81,6 @@ internal fun NormalLoginScreen( onNavigateToSignUp = onNavigateToSignUp, onNavigateToEmailSearch = onNavigateToEmailSearch, onNavigateToPasswordSearch = onNavigateToPasswordSearch, - userType = userType, - isLoginSuccessful = isLoginSuccessful ) } } @@ -108,9 +91,9 @@ private fun Content( onNavigateToSignUp: (UserType) -> Unit, onNavigateToEmailSearch: (UserType) -> Unit, onNavigateToPasswordSearch: (UserType) -> Unit, - userType: UserType, - isLoginSuccessful: Boolean? ) { + val uiState by viewModel.collectAsState() + Column( modifier = Modifier .fillMaxSize() @@ -122,54 +105,57 @@ private fun Content( .padding(horizontal = 20.dp) ) { ConnectDogTextField( - text = viewModel.email, - label = "이메일", - placeholder = "이메일 입력", + text = uiState.email, + label = stringResource(id = R.string.email), + placeholder = stringResource(id = R.string.email), keyboardType = KeyboardType.Text, - onTextChanged = { viewModel.updateEmail(it) }, - isError = isLoginSuccessful?.let { !it } ?: run { false } + onTextChanged = viewModel::onEmailChanged, + isError = uiState.isLoginSuccessful?.let { !it } ?: run { false } ) Spacer(modifier = Modifier.height(12.dp)) ConnectDogTextField( - text = viewModel.password, - label = "비밀번호", - placeholder = "비밀번호 입력", + text = uiState.password, + label = stringResource(id = R.string.password), + placeholder = stringResource(id = R.string.input_password), keyboardType = KeyboardType.Password, - onTextChanged = { viewModel.updatePassword(it) }, - isError = isLoginSuccessful?.let { !it } ?: run { false } + onTextChanged = viewModel::onPasswordChanged, + isError = uiState.isLoginSuccessful?.let { !it } ?: run { false } ) Spacer(modifier = Modifier.height(12.dp)) ConnectDogNormalButton( - content = "로그인", + content = stringResource(id = R.string.login), color = MaterialTheme.colorScheme.primary, - onClick = { viewModel.initVolunteerLogin() }, + onClick = viewModel::initVolunteerLogin, modifier = Modifier .fillMaxWidth() .height(56.dp) ) Spacer(modifier = Modifier.height(30.dp)) - AccountFind( - onNavigateToSignup = onNavigateToSignUp, - onNavigateToEmailSearch = onNavigateToEmailSearch, - onNavigateToPasswordSearch = onNavigateToPasswordSearch, - userType = userType + ActionRow( + stringResource(id = R.string.email_signup) to { onNavigateToSignUp(UserType.NORMAL_VOLUNTEER) }, + stringResource(id = R.string.email_search) to { onNavigateToEmailSearch(UserType.NORMAL_VOLUNTEER) }, + stringResource(id = R.string.password_search) to { + onNavigateToPasswordSearch( + UserType.NORMAL_VOLUNTEER + ) + } ) } Spacer(modifier = Modifier.height(30.dp)) Box( modifier = Modifier.fillMaxSize() ) { - if (isLoginSuccessful?.let { !it } ?: run { false }) { + if (uiState.isLoginSuccessful?.let { !it } ?: run { false }) { ConnectDogErrorCard( modifier = Modifier .zIndex(1f) .align(Alignment.TopCenter) .padding(horizontal = 20.dp), - errorMessage = R.string.login_error + errorMessage = DR.string.login_error ) } Image( - painter = painterResource(id = R.drawable.ic_main_large), + painter = painterResource(id = DR.drawable.ic_main_large), contentDescription = null, modifier = Modifier .fillMaxWidth() @@ -179,49 +165,3 @@ private fun Content( } } } - -@Composable -fun AccountFind( - onNavigateToSignup: (UserType) -> Unit, - onNavigateToEmailSearch: (UserType) -> Unit, - onNavigateToPasswordSearch: (UserType) -> Unit, - userType: UserType -) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - Text( - modifier = Modifier.clickable { onNavigateToSignup(userType) }, - text = "이메일로 회원가입", - fontSize = 12.sp, - color = Gray2 - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - text = "|", - fontSize = 12.sp, - color = Gray2 - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - modifier = Modifier.clickable { onNavigateToEmailSearch(UserType.NORMAL_VOLUNTEER) }, - text = "이메일 찾기", - fontSize = 12.sp, - color = Gray2 - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - text = "|", - fontSize = 12.sp, - color = Gray2 - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - modifier = Modifier.clickable { onNavigateToPasswordSearch(UserType.NORMAL_VOLUNTEER) }, - text = "비밀번호 찾기", - fontSize = 12.sp, - color = Gray2 - ) - } -} diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordSearchScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordResetScreen.kt similarity index 96% rename from feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordSearchScreen.kt rename to feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordResetScreen.kt index 9b3a3f3da..1c21c7634 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordSearchScreen.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordResetScreen.kt @@ -30,11 +30,11 @@ import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationTyp import com.kusitms.connectdog.core.designsystem.theme.Gray3 import com.kusitms.connectdog.core.util.UserType import com.kusitms.connectdog.feature.login.R -import com.kusitms.connectdog.feature.login.viewmodel.PasswordSearchViewModel +import com.kusitms.connectdog.feature.login.viewmodel.PasswordResetViewModel @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable -fun PasswordSearchScreen( +fun PasswordResetScreen( onBackClick: () -> Unit, imeHeight: Int, navigateToLoginRoute: () -> Unit, @@ -60,7 +60,7 @@ fun PasswordSearchScreen( @Composable private fun Content( imeHeight: Int, - viewModel: PasswordSearchViewModel = hiltViewModel(), + viewModel: PasswordResetViewModel = hiltViewModel(), navigateToLoginRoute: () -> Unit, userType: UserType ) { diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailAuthForPasswordResetUiState.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailAuthForPasswordResetUiState.kt new file mode 100644 index 000000000..f0693f5a6 --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailAuthForPasswordResetUiState.kt @@ -0,0 +1,36 @@ +package com.kusitms.connectdog.feature.login.state + +import com.kusitms.connectdog.core.util.emptyString + +data class EmailAuthForPasswordResetUiState( + val email: String, + val inputAuthCode: String, + val authCode: String, + val isSendAuthCode: Boolean, + val isValidEmail: Boolean, + val isEmailError: Boolean, + val accessToken: String, + val bottomButtonText: String, + val enableNext: Boolean, + val isAuthCodeError: Boolean, +) { + companion object { + fun empty() = EmailAuthForPasswordResetUiState( + email = emptyString(), + inputAuthCode = emptyString(), + authCode = emptyString(), + accessToken = emptyString(), + isSendAuthCode = false, + isValidEmail = false, + bottomButtonText = "인증 요청", + enableNext = false, + isEmailError = false, + isAuthCodeError = false, + ) + } +} + +sealed class EmailAuthForPasswordResetSideEffect { + object NavigateToFail: EmailAuthForPasswordResetSideEffect() + object NavigateToPasswordReset: EmailAuthForPasswordResetSideEffect() +} \ No newline at end of file diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailSearchUiState.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailSearchUiState.kt new file mode 100644 index 000000000..f35b5ea23 --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailSearchUiState.kt @@ -0,0 +1,29 @@ +package com.kusitms.connectdog.feature.login.state + +import com.kusitms.connectdog.core.util.emptyString + +data class EmailSearchUiState( + val phoneNumber: String, + val isSendAuthCode: Boolean, + val authCode: String, + val email: String?, + val enableNext: Boolean, + val bottomButtonText: String, + val isAuthCodeError: Boolean? +) { + companion object { + fun empty() = EmailSearchUiState( + phoneNumber = emptyString(), + authCode = emptyString(), + isSendAuthCode = false, + email = null, + enableNext = false, + bottomButtonText = "인증 요청", + isAuthCodeError = null + ) + } +} + +sealed class EmailSearchSideEffect { + object NavigateToEmailSearchResult: EmailSearchSideEffect() +} \ No newline at end of file diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/LoginUiState.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/LoginUiState.kt new file mode 100644 index 000000000..b0579c688 --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/LoginUiState.kt @@ -0,0 +1,28 @@ +package com.kusitms.connectdog.feature.login.state + +import com.kusitms.connectdog.core.util.SocialType +import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.core.util.emptyString + +data class LoginUiState( + val email: String, + val password: String, + val isLoginSuccessful: Boolean?, + val socialType: SocialType?, + val socialToken: String +) { + companion object { + fun empty() = LoginUiState( + email = emptyString(), + password = emptyString(), + isLoginSuccessful = null, + socialType = null, + socialToken = emptyString() + ) + } +} + +sealed class LoginSideEffect { + object NavigateToHome: LoginSideEffect() + data class NavigateToSignUp(val userType: UserType): LoginSideEffect() +} \ No newline at end of file diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/PasswordResetUiState.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/PasswordResetUiState.kt new file mode 100644 index 000000000..57235515c --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/PasswordResetUiState.kt @@ -0,0 +1,19 @@ +package com.kusitms.connectdog.feature.login.state + +import com.kusitms.connectdog.core.util.emptyString + +data class PasswordResetUiState( + val password: String, + val passwordCheck: String, + val isValidPassword: Boolean? +) { + companion object { + fun empty() = PasswordResetUiState( + password = emptyString(), + passwordCheck = emptyString(), + isValidPassword = null + ) + } +} + +sealed class PasswordResetSideEffect \ No newline at end of file diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailAuthForPasswordResetViewModel.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailAuthForPasswordResetViewModel.kt new file mode 100644 index 000000000..d54ae0436 --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailAuthForPasswordResetViewModel.kt @@ -0,0 +1,93 @@ +package com.kusitms.connectdog.feature.login.viewmodel + +import android.util.Patterns +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.auth.EmailAuthForIntermediatorPasswordResetUseCase +import com.kusitms.connectdog.domain.usecase.auth.EmailAuthForVolunteerPasswordResetUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateAccessTokenUseCase +import com.kusitms.connectdog.feature.login.state.EmailAuthForPasswordResetSideEffect +import com.kusitms.connectdog.feature.login.state.EmailAuthForPasswordResetUiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.postSideEffect +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container +import javax.inject.Inject + +@HiltViewModel +class EmailAuthForPasswordResetViewModel @Inject constructor( + private val emailAuthForVolunteerPasswordResetUseCase: EmailAuthForVolunteerPasswordResetUseCase, + private val emailAuthForIntermediatorPasswordResetUseCase: EmailAuthForIntermediatorPasswordResetUseCase, + private val updateAccessTokenUseCase: UpdateAccessTokenUseCase +) : ContainerHost, + ViewModel() { + override val container: Container = + container(EmailAuthForPasswordResetUiState.empty()) + private val state: EmailAuthForPasswordResetUiState + get() = container.stateFlow.value + + fun onEmailChanged(email: String) { + intent { reduce { state.copy(email = email) } } + checkValidEmail() + enableNextButton() + } + + fun onInputAuthCodeChanged(inputAuthCode: String) { + if (inputAuthCode.length <= 8) intent { reduce { state.copy(inputAuthCode = inputAuthCode) } } + enableNextButton() + } + + fun onNextButtonClick(userType: UserType) { + if(!state.isSendAuthCode) { + sendAuthCode(userType) + intent { reduce { state.copy(enableNext = false) } } + intent { reduce { state.copy(bottomButtonText = "인증 확인") } } + } else if(state.inputAuthCode != state.authCode){ + intent { reduce { state.copy(isAuthCodeError = true) } } + } else { + intent { postSideEffect(EmailAuthForPasswordResetSideEffect.NavigateToPasswordReset) } + } + } + + private fun sendAuthCode(userType: UserType) = when (userType) { + UserType.INTERMEDIATOR -> getIntermediatorEmailAuthCode() + else -> getVolunteerEmailAuthCode() + } + + private fun getVolunteerEmailAuthCode() = viewModelScope.launch { + emailAuthForVolunteerPasswordResetUseCase(state.email).onSuccess { + intent { reduce { state.copy(authCode = it.authCode, isSendAuthCode = true) } } + updateAccessTokenUseCase(it.accessToken) + }.onFailure { + intent { postSideEffect(EmailAuthForPasswordResetSideEffect.NavigateToFail) } + } + } + + private fun getIntermediatorEmailAuthCode() = viewModelScope.launch { + emailAuthForIntermediatorPasswordResetUseCase(state.email).onSuccess { + intent { reduce { state.copy(authCode = it.authCode, isSendAuthCode = true) } } + updateAccessTokenUseCase(it.accessToken) + }.onFailure { + intent { postSideEffect(EmailAuthForPasswordResetSideEffect.NavigateToFail) } + } + } + + private fun enableNextButton() = intent { + if (!state.isSendAuthCode && state.isValidEmail) { + reduce { state.copy(enableNext = true) } + } else if(state.isSendAuthCode && state.inputAuthCode.length == 8) { + reduce { state.copy(enableNext = true) } + } else { + reduce { state.copy(enableNext = false) } + } + } + + private fun checkValidEmail() = intent { + reduce { state.copy(isValidEmail = Patterns.EMAIL_ADDRESS.matcher(state.email).matches()) } + } +} diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailSearchViewModel.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailSearchViewModel.kt new file mode 100644 index 000000000..697c547e3 --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailSearchViewModel.kt @@ -0,0 +1,91 @@ +package com.kusitms.connectdog.feature.login.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.auth.SearchIntermediatorEmailUseCase +import com.kusitms.connectdog.domain.usecase.auth.SearchVolunteerEmailUseCase +import com.kusitms.connectdog.feature.login.state.EmailSearchSideEffect +import com.kusitms.connectdog.feature.login.state.EmailSearchUiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.postSideEffect +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container +import javax.inject.Inject + +@HiltViewModel +class EmailSearchViewModel @Inject constructor( + private val searchVolunteerEmailUseCase: SearchVolunteerEmailUseCase, + private val searchIntermediatorEmailUseCase: SearchIntermediatorEmailUseCase +): ContainerHost, ViewModel() { + override val container: Container = container(EmailSearchUiState.empty()) + private val state: EmailSearchUiState + get() = container.stateFlow.value + + fun onPhoneNumberChanged(phoneNumber: String) = intent { + if (phoneNumber.length <= 11) reduce { state.copy(phoneNumber = phoneNumber) } + enableNextButton() + } + + fun onAuthCodeChanged(authCode: String) = intent { + if (authCode.length <= 6) reduce { state.copy(authCode = authCode) } + enableNextButton() + } + + private fun enableNextButton() = intent { + if(!state.isSendAuthCode && state.phoneNumber.length == 11) { + reduce { state.copy(enableNext = true) } + } else if(state.isSendAuthCode && state.authCode.length == 6) { + reduce { state.copy(enableNext = true) } + } else { + reduce { state.copy(enableNext = false) } + } + } + + fun onNextClick( + userType: UserType, + onSendMessageClick: (String) -> Unit, + onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, + ) { + if(!state.isSendAuthCode) { + updateBottomButtonText() + onSendMessageClick(state.phoneNumber) + disableNextButton() + intent { reduce { state.copy(isSendAuthCode = true) } } + } else { + onVerifyCodeClick(state.authCode) { + if(it) intent { + when(userType) { + UserType.INTERMEDIATOR -> searchIntermediatorEmail() + else -> searchVolunteerEmail() + } + postSideEffect(EmailSearchSideEffect.NavigateToEmailSearchResult) + } + else intent { reduce { state.copy(isAuthCodeError = true) } } + } + } + } + + private fun updateBottomButtonText() = intent { reduce { state.copy(bottomButtonText = "인증 확인" ) } } + private fun disableNextButton() = intent { reduce { state.copy(enableNext = false) } } + + private fun searchIntermediatorEmail() = viewModelScope.launch { + searchIntermediatorEmailUseCase(state.phoneNumber).onSuccess { + intent { reduce { state.copy(email = it.email) } } + }.onFailure { + + } + } + + private fun searchVolunteerEmail() = viewModelScope.launch { + searchVolunteerEmailUseCase(state.phoneNumber).onSuccess { + intent { reduce { state.copy(email = it.email) } } + }.onFailure { + + } + } +} diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/LoginViewModel.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/LoginViewModel.kt index 78fe65816..f779fb737 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/LoginViewModel.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/LoginViewModel.kt @@ -1,207 +1,144 @@ package com.kusitms.connectdog.feature.login.viewmodel import android.content.Context -import android.util.Log -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.kakao.sdk.auth.model.OAuthToken import com.kakao.sdk.common.model.ClientError import com.kakao.sdk.common.model.ClientErrorCause import com.kakao.sdk.user.UserApiClient -import com.kusitms.connectdog.core.data.api.model.NormalLoginBody -import com.kusitms.connectdog.core.data.api.model.SocialLoginBody -import com.kusitms.connectdog.core.data.repository.DataStoreRepository -import com.kusitms.connectdog.core.data.repository.LoginRepository -import com.kusitms.connectdog.core.util.AppMode -import com.kusitms.connectdog.core.util.SocialType +import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.login.AppMode +import com.kusitms.connectdog.domain.usecase.login.IntermediatorLoginUseCase +import com.kusitms.connectdog.domain.usecase.login.SocialLoginProvider +import com.kusitms.connectdog.domain.usecase.login.SocialLoginUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateAccessTokenUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateAppModeUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateRefreshTokenUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateSocialProviderUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateSocialTokenUseCase +import com.kusitms.connectdog.domain.usecase.login.VolunteerLoginUseCase +import com.kusitms.connectdog.feature.login.BuildConfig +import com.kusitms.connectdog.feature.login.state.LoginSideEffect +import com.kusitms.connectdog.feature.login.state.LoginUiState import com.navercorp.nid.NaverIdLoginSDK import com.navercorp.nid.oauth.NidOAuthLogin import com.navercorp.nid.oauth.OAuthLoginCallback import com.navercorp.nid.profile.NidProfileCallback import com.navercorp.nid.profile.data.NidProfileResponse import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.postSideEffect +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container import javax.inject.Inject -enum class Provider { - KAKAO, NAVER -} - -private const val TAG = "LoginViewModel" - @HiltViewModel class LoginViewModel @Inject constructor( - private val loginRepository: LoginRepository, - private val dataStoreRepository: DataStoreRepository -) : ViewModel() { - private val _isLoginSuccessful: MutableStateFlow = MutableStateFlow(null) - val isLoginSuccessful: StateFlow - get() = _isLoginSuccessful - - private val _socialType: MutableStateFlow = MutableStateFlow(null) - val socialType: StateFlow - get() = _socialType - - private val _email: MutableState = mutableStateOf("") - val email: String - get() = _email.value - - private val _password: MutableState = mutableStateOf("") - val password: String - get() = _password.value - - private val _accessToken: MutableStateFlow = MutableStateFlow(null) - - fun updateEmail(email: String) { - _email.value = email - } - - fun updatePassword(password: String) { - _password.value = password - } - - fun initVolunteerLogin() { - val body = NormalLoginBody(_email.value, _password.value) - viewModelScope.launch { - try { - val response = loginRepository.postLoginData(body) - dataStoreRepository.saveAccessToken(response.accessToken) - dataStoreRepository.saveRefreshToken(response.refreshToken) - dataStoreRepository.saveAppMode(AppMode.VOLUNTEER) - _isLoginSuccessful.value = true - Log.d(TAG, isLoginSuccessful.toString()) - Log.d(TAG, dataStoreRepository.accessTokenFlow.first().toString()) - } catch (e: Exception) { - _isLoginSuccessful.value = false - Log.d(TAG, e.message.toString()) + private val volunteerLoginUseCase: VolunteerLoginUseCase, + private val intermediatorLoginUseCase: IntermediatorLoginUseCase, + private val socialLoginUseCase: SocialLoginUseCase, + private val updateAccessTokenUseCase: UpdateAccessTokenUseCase, + private val updateRefreshTokenUseCase: UpdateRefreshTokenUseCase, + private val updateAppModeUseCase: UpdateAppModeUseCase, + private val updateSocialTokenUseCase: UpdateSocialTokenUseCase, + private val updateSocialProviderUseCase: UpdateSocialProviderUseCase, +) : ContainerHost, ViewModel() { + override val container: Container = container(LoginUiState.empty()) + private val state: LoginUiState + get() = container.stateFlow.value + + fun onEmailChanged(email: String) = intent { reduce { state.copy(email = email) } } + fun onPasswordChanged(password: String) = intent { reduce { state.copy(password = password) } } + + fun initVolunteerLogin() = viewModelScope.launch { + volunteerLoginUseCase( + email = state.email, + password = state.password + ).onSuccess { + updateAccessTokenUseCase(it.accessToken) + updateRefreshTokenUseCase(it.refreshToken) + updateAppModeUseCase(AppMode.VOLUNTEER) + intent { + reduce { state.copy(isLoginSuccessful = true) } + postSideEffect(LoginSideEffect.NavigateToHome) } + }.onFailure { + intent { reduce { state.copy(isLoginSuccessful = false) } } } } - fun initIntermediatorLogin() { - val body = NormalLoginBody(_email.value, _password.value) - viewModelScope.launch { - try { - val response = loginRepository.postIntermediatorLoginData(body) - _isLoginSuccessful.value = true - dataStoreRepository.saveAccessToken(response.accessToken) - dataStoreRepository.saveRefreshToken(response.refreshToken) - dataStoreRepository.saveAppMode(AppMode.INTERMEDIATOR) - } catch (e: Exception) { - _isLoginSuccessful.value = false - Log.d(TAG, e.message.toString()) + fun initIntermediatorLogin() = viewModelScope.launch { + intermediatorLoginUseCase( + email = state.email, + password = state.password + ).onSuccess { + intent { + reduce { state.copy(isLoginSuccessful = true) } + postSideEffect(LoginSideEffect.NavigateToHome) } + updateAccessTokenUseCase(it.accessToken) + updateRefreshTokenUseCase(it.refreshToken) + updateAppModeUseCase(AppMode.INTERMEDIATOR) + }.onFailure { + intent { reduce { state.copy(isLoginSuccessful = false) } } } } - fun initSocialLogin(provider: Provider, context: Context) { - when (provider) { - Provider.NAVER -> initNaverLogin(context) - Provider.KAKAO -> initKakaoLogin(context) - } - - viewModelScope.launch { - try { - _accessToken.collect { - if (it == null) return@collect - val body = SocialLoginBody(accessToken = it, provider = provider.toString()) - val response = loginRepository.postSocialLoginData(body) - dataStoreRepository.saveAccessToken(response.accessToken) - dataStoreRepository.saveRefreshToken(response.refreshToken) - dataStoreRepository.saveSocialToken(it) - dataStoreRepository.saveSocialProvider(provider.toString()) - when (response.roleName) { - "GUEST" -> _socialType.emit(SocialType.GUEST) - "AUTH_VOLUNTEER" -> { - _socialType.emit(SocialType.VOLUNTEER) - dataStoreRepository.saveAppMode(AppMode.VOLUNTEER) - } - } - Log.d(TAG, response.toString()) + private fun initSocialLogin(provider: SocialLoginProvider, token: String) = viewModelScope.launch { + socialLoginUseCase( + accessToken = token, + provider = provider.toString() + ).onSuccess { + updateAccessTokenUseCase(it.accessToken) + updateRefreshTokenUseCase(it.refreshToken) + when(it.roleName) { + "GUEST" -> intent { postSideEffect(LoginSideEffect.NavigateToSignUp(UserType.SOCIAL_VOLUNTEER)) } + "AUTH_VOLUNTEER" -> { + intent { postSideEffect(LoginSideEffect.NavigateToHome) } + updateAppModeUseCase(AppMode.VOLUNTEER) } - } catch (e: Exception) { - Log.d(TAG, e.message.toString()) } } } - private fun initNaverLogin(context: Context) { - NaverIdLoginSDK.initialize(context, "rWBuAHxm0vihdivNGAZI", "8Sfw75g883", "connectdog") - NaverIdLoginSDK.authenticate(context, naverLoginCallback) - } - private val naverLoginCallback = object : OAuthLoginCallback { override fun onSuccess() { NidOAuthLogin().callProfileApi(object : NidProfileCallback { override fun onSuccess(result: NidProfileResponse) { - Log.d("tszq", "succesa") - _accessToken.value = NaverIdLoginSDK.getAccessToken().toString() - } - - override fun onError(errorCode: Int, message: String) { - Log.e("login", message) + initSocialLogin(SocialLoginProvider.NAVER, NaverIdLoginSDK.getAccessToken().toString()) } - override fun onFailure(httpStatus: Int, message: String) { - Log.e("login", message) - } + override fun onError(errorCode: Int, message: String) {} + override fun onFailure(httpStatus: Int, message: String) {} }) } + override fun onError(errorCode: Int, message: String) {} + override fun onFailure(httpStatus: Int, message: String) {} + } - override fun onError(errorCode: Int, message: String) { - Log.e("login", message) - } - - override fun onFailure(httpStatus: Int, message: String) { - Log.e("login", message) + private val kakaoLoginCallback: (OAuthToken?, Throwable?) -> Unit = { token, error -> + if (token != null && error != null) { + initSocialLogin(SocialLoginProvider.KAKAO, token.accessToken) } } - private fun initKakaoLogin(context: Context) { - val kakaoLoginCallback: (OAuthToken?, Throwable?) -> Unit = { token, error -> - if (error != null) { - Log.e("Kakao Login", "카카오계정으로 로그인 실패", error) - } else if (token != null) { - Log.i("Kakao Login", "카카오계정으로 로그인 성공 ${token.accessToken}") - _accessToken.value = token.accessToken - - UserApiClient.instance.me { user, error -> - if (error != null) { - Log.e("Kakao Login", "사용자 정보 요청 실패", error) - } else if (user != null) { - } - } - } - } + fun initNaverLogin(context: Context) { + NaverIdLoginSDK.initialize(context, BuildConfig.NAVER_CLIENT_ID, BuildConfig.NAVER_CLIENT_SECRET, "connectdog") + NaverIdLoginSDK.authenticate(context, naverLoginCallback) + } + fun initKakaoLogin(context: Context) { if (UserApiClient.instance.isKakaoTalkLoginAvailable(context)) { UserApiClient.instance.loginWithKakaoTalk(context) { token, error -> - if (error != null) { - Log.e("Kakao Login", "카카오톡으로 로그인 실패", error) - - if (error is ClientError && error.reason == ClientErrorCause.Cancelled) { - return@loginWithKakaoTalk - } - - UserApiClient.instance.loginWithKakaoAccount( - context, - callback = kakaoLoginCallback - ) - } else if (token != null) { - Log.i("Kakao Login", "카카오 로그인 성공 ${token.accessToken}") - _accessToken.value = token.accessToken - - UserApiClient.instance.me { user, error -> - if (error != null) { - Log.e("Kakao Login", "사용자 정보 요청 실패", error) - } else if (user != null) { - } - } + if (error != null && token != null) { + initSocialLogin(SocialLoginProvider.KAKAO, token.accessToken) + } else if (error is ClientError && error.reason == ClientErrorCause.Cancelled) { + UserApiClient.instance.loginWithKakaoAccount(context, callback = kakaoLoginCallback) + return@loginWithKakaoTalk } } } else { diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordSearchViewModel.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordResetViewModel.kt similarity index 77% rename from feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordSearchViewModel.kt rename to feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordResetViewModel.kt index 844d9cd9b..8576e5690 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordSearchViewModel.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordResetViewModel.kt @@ -5,16 +5,25 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.kusitms.connectdog.core.data.repository.SignUpRepository import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.feature.login.state.PasswordResetSideEffect +import com.kusitms.connectdog.feature.login.state.PasswordResetUiState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.viewmodel.container import javax.inject.Inject @HiltViewModel -class PasswordSearchViewModel @Inject constructor( +class PasswordResetViewModel @Inject constructor( private val repository: SignUpRepository -) : ViewModel() { +): ContainerHost, ViewModel() { + override val container: Container = container(PasswordResetUiState.empty()) + private val state: PasswordResetUiState + get() = container.stateFlow.value + private var _password = mutableStateOf("") val password: String get() = _password.value diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordSearchAuthViewModel.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordSearchAuthViewModel.kt deleted file mode 100644 index 2fa5528b9..000000000 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordSearchAuthViewModel.kt +++ /dev/null @@ -1,105 +0,0 @@ -package com.kusitms.connectdog.feature.login.viewmodel - -import android.content.Context -import android.widget.Toast -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.repository.DataStoreRepository -import com.kusitms.connectdog.core.data.repository.LoginRepository -import com.kusitms.connectdog.core.util.UserType -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import javax.inject.Inject - -@HiltViewModel -class PasswordSearchAuthViewModel @Inject constructor( - private val repository: LoginRepository, - private val dataStoreRepository: DataStoreRepository -) : ViewModel() { - private var postNumber: String = "" - - private val _isEmailVerified: MutableStateFlow = MutableStateFlow(null) - val isEmailVerified: StateFlow - get() = _isEmailVerified - - private val _isEmailError: MutableStateFlow = MutableStateFlow(null) - val isEmailError: StateFlow - get() = _isEmailError - - private val _isValidEmail: MutableStateFlow = MutableStateFlow(null) - val isValidEmail: StateFlow - get() = _isValidEmail - - private val _email: MutableState = mutableStateOf("") - val email: String - get() = _email.value - - private val _certificationNumber: MutableState = mutableStateOf("") - val certificationNumber: String - get() = _certificationNumber.value - - private val accessToken = MutableStateFlow(null) - - fun updateEmail(email: String) { - _email.value = email - } - - fun updateCertificationNumber(certificationNumber: String) { - _certificationNumber.value = certificationNumber - } - - fun updateEmailValidity() { - _isValidEmail.value = !android.util.Patterns.EMAIL_ADDRESS.matcher(_email.value).matches() - } - - fun updateEmailVerify(value: Boolean) { - _isEmailVerified.value = value - } - - fun postEmail(context: Context, userType: UserType) = viewModelScope.launch { - if (_email.value.isEmpty()) { - Toast.makeText(context, "이메일을 입력해주세요", Toast.LENGTH_SHORT).show() - return@launch - } - if (isValidEmail.value == true) { - Toast.makeText(context, "유효한 이메일을 입력해주세요", Toast.LENGTH_SHORT).show() - return@launch - } - - try { - val response = when (userType) { - UserType.INTERMEDIATOR -> repository.interPasswordSearchAuth(_email.value) - else -> repository.volunteerPasswordSearchAuth(_email.value) - } - Toast.makeText(context, "이메일을 전송했습니다", Toast.LENGTH_SHORT).show() - _isEmailError.value = false - postNumber = response.authCode - accessToken.value = response.accessToken - } catch (e: Exception) { - val text = when (userType) { - UserType.INTERMEDIATOR -> "해당 이동봉사 모집자를 찾을 수 없습니다." - else -> "해당 봉사자를 찾을 수 없습니다." - } - _isEmailError.value = true - Toast.makeText(context, text, Toast.LENGTH_SHORT).show() - } - } - - fun checkCertificationNumber(context: Context) = viewModelScope.launch { - if (_certificationNumber.value.isEmpty()) { - Toast.makeText(context, "인증번호를 입력해주세요", Toast.LENGTH_SHORT).show() - } else { - _isEmailVerified.value = _certificationNumber.value == postNumber - if (_isEmailVerified.value == true) { - accessToken.value?.let { dataStoreRepository.saveAccessToken(it) } - Toast.makeText(context, "인증이 완료되었습니다", Toast.LENGTH_SHORT).show() - } else if (_isEmailVerified.value == false) { - Toast.makeText(context, "인증에 실패하였습니다", Toast.LENGTH_SHORT).show() - } - } - } -} diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/SearchViewModel.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/SearchViewModel.kt deleted file mode 100644 index 10fef30ae..000000000 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/SearchViewModel.kt +++ /dev/null @@ -1,77 +0,0 @@ -package com.kusitms.connectdog.feature.login.viewmodel - -import android.content.Context -import android.widget.Toast -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.repository.LoginRepository -import com.kusitms.connectdog.core.util.UserType -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import javax.inject.Inject - -@HiltViewModel -class SearchViewModel @Inject constructor( - private val repository: LoginRepository -) : ViewModel() { - private val _phoneNumber: MutableState = mutableStateOf("") - val phoneNumber: String - get() = _phoneNumber.value - - private val _certificationNumber: MutableState = mutableStateOf("") - val certificationNumber: String - get() = _certificationNumber.value - - private val _isSendNumber: MutableStateFlow = MutableStateFlow(false) - val isSendNumber: StateFlow = _isSendNumber - - private val _isCertified: MutableStateFlow = MutableStateFlow(false) - val isCertified: StateFlow = _isCertified - - private val _findEmail = MutableStateFlow(null) - val findEmail: StateFlow - get() = _findEmail - - fun updateCertificationNumber(value: String) { - _certificationNumber.value = value - } - - fun updatePhoneNumber(value: String) { - _phoneNumber.value = value - } - - fun updateIsSendNumber(value: Boolean) { - _isSendNumber.value = value - } - - fun updateIsCertified(isCertified: Boolean) { - _isCertified.value = isCertified - } - - fun test(userType: UserType, context: Context) = viewModelScope.launch { - try { - when (userType) { - UserType.INTERMEDIATOR -> { - val response = repository.interEmailSearch(_phoneNumber.value) - _findEmail.value = response.email - } - - UserType.NORMAL_VOLUNTEER -> { - val response = repository.volunteerEmailSearch(_phoneNumber.value) - _findEmail.value = response.email - } - - else -> {} - } - } catch (e: Exception) { - when (userType) { - UserType.INTERMEDIATOR -> Toast.makeText(context, "해당 해당 이동봉사 모집자를 찾을 수 없습니다.", Toast.LENGTH_SHORT).show() - else -> Toast.makeText(context, "해당 이동봉사자를 찾을 수 없습니다.", Toast.LENGTH_SHORT).show() - } - } - } -} diff --git a/feature/login/src/main/res/values/strings.xml b/feature/login/src/main/res/values/strings.xml index f3431d9a3..ee1f3361c 100644 --- a/feature/login/src/main/res/values/strings.xml +++ b/feature/login/src/main/res/values/strings.xml @@ -1,5 +1,14 @@ + 이메일 + 비밀번호 + + 이메일 입력 + 비밀번호 입력 + + 이메일로 회원가입 + 이메일 로그인\ + 네이버로 3초 만에 시작하기 카카오로 3초 만에 시작하기 코넥독 계정으로 회원가입하기 @@ -10,4 +19,13 @@ 비밀번호 찾기 로그인에 사용할\n비밀번호를 입력해 주세요 + + + 이메일 인증을\n진행해주세요 + 휴대폰 번호 + + + + 입력하신 번호로 가입한 계정이\n존재하지 않습니다 + 정보가 일치하는 계정이 존재하지 않습니다. \ No newline at end of file diff --git a/feature/main/build.gradle.kts b/feature/main/build.gradle.kts index d46d2787b..85412dd83 100644 --- a/feature/main/build.gradle.kts +++ b/feature/main/build.gradle.kts @@ -37,7 +37,6 @@ android { kotlinOptions { jvmTarget = "17" } - buildFeatures { compose = true } @@ -47,7 +46,7 @@ android { } dependencies { - + implementation(projects.domain) // Navigation을 위해 모든 feature 의존성 추가 필요 implementation(project(":feature:login")) implementation(project(":feature:signup")) @@ -90,9 +89,9 @@ dependencies { implementation(libs.androidx.compose.material3) implementation(libs.kotlinx.collection.imuutable) - - // test - implementation(libs.androidx.junit.ktx) + implementation(libs.orbit.core) + implementation(libs.orbit.compose) + implementation(libs.orbit.viewmodel) } kapt { diff --git a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainActivity.kt b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainActivity.kt index 5521e4aeb..713cccabb 100644 --- a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainActivity.kt +++ b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainActivity.kt @@ -31,20 +31,14 @@ import com.google.firebase.auth.PhoneAuthCredential import com.google.firebase.auth.PhoneAuthOptions import com.google.firebase.auth.PhoneAuthProvider import com.google.firebase.messaging.FirebaseMessaging -import com.kusitms.connectdog.core.data.repository.DataStoreRepository import com.kusitms.connectdog.core.designsystem.theme.ConnectDogTheme +import com.kusitms.connectdog.domain.usecase.login.AppMode import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import org.orbitmvi.orbit.compose.collectAsState import java.util.concurrent.TimeUnit -import javax.inject.Inject @AndroidEntryPoint class MainActivity : ComponentActivity() { - @Inject - lateinit var dataStore: DataStoreRepository private lateinit var auth: FirebaseAuth private lateinit var verificationId: String private var imeHeight by mutableIntStateOf(0) @@ -60,11 +54,10 @@ class MainActivity : ComponentActivity() { installSplashScreen() imeListener() - lifecycleScope.launch { - val appMode = withContext(Dispatchers.IO) { - dataStore.appModeFlow.first() - } - setContent { + + setContent { + val uiState by viewModel.collectAsState() + uiState.appMode?.let { appMode -> val navigator: MainNavigator = rememberMainNavigator(mode = appMode) ConnectDogTheme { MainScreen( @@ -137,7 +130,6 @@ class MainActivity : ComponentActivity() { val updatedHeight = if (imeHeight - sysBarInsets.bottom < 0) 0 else imeHeight - sysBarInsets.bottom - Log.d("saqa", updatedHeight.toString()) return insets } } diff --git a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainNavigator.kt b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainNavigator.kt index 7552e6709..049b5de21 100644 --- a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainNavigator.kt +++ b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainNavigator.kt @@ -8,8 +8,9 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navOptions -import com.kusitms.connectdog.core.util.AppMode +import com.kusitms.connectdog.core.util.AccountType import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.login.AppMode import com.kusitms.connectdog.feature.home.model.Filter import com.kusitms.connectdog.feature.home.navigation.HomeRoute import com.kusitms.connectdog.feature.home.navigation.navigateApply @@ -32,13 +33,14 @@ import com.kusitms.connectdog.feature.intermediator.navigation.navigateToCreateA import com.kusitms.connectdog.feature.intermediator.navigation.navigateToCreateComplete import com.kusitms.connectdog.feature.intermediator.navigation.navigateToCreateDog import com.kusitms.connectdog.feature.intermediator.navigation.navigateToInterProfileEdit -import com.kusitms.connectdog.feature.login.LoginRoute -import com.kusitms.connectdog.feature.login.navigateEmailSearch -import com.kusitms.connectdog.feature.login.navigateEmailSearchComplete -import com.kusitms.connectdog.feature.login.navigateNormalLogin -import com.kusitms.connectdog.feature.login.navigatePasswordSearch -import com.kusitms.connectdog.feature.login.navigatePasswordSearchAuth -import com.kusitms.connectdog.feature.login.navigateToLoginRoute +import com.kusitms.connectdog.feature.login.navigation.LoginRoute +import com.kusitms.connectdog.feature.login.navigation.navigateEmailSearch +import com.kusitms.connectdog.feature.login.navigation.navigateEmailSearchComplete +import com.kusitms.connectdog.feature.login.navigation.navigateNormalLogin +import com.kusitms.connectdog.feature.login.navigation.navigatePasswordSearch +import com.kusitms.connectdog.feature.login.navigation.navigatePasswordSearchAuth +import com.kusitms.connectdog.feature.login.navigation.navigateToLoginRoute +import com.kusitms.connectdog.feature.login.navigation.navigateToNoAccount import com.kusitms.connectdog.feature.management.navigation.navigateCheckReview import com.kusitms.connectdog.feature.management.navigation.navigateCreateReview import com.kusitms.connectdog.feature.management.navigation.navigateManagement @@ -71,7 +73,7 @@ internal class MainNavigator( val startDestination = when (mode) { AppMode.VOLUNTEER -> MainTab.HOME.route AppMode.INTERMEDIATOR -> IntermediatorRoute.route - AppMode.LOGIN -> LoginRoute.route + AppMode.LOGIN -> LoginRoute.ROUTE } val currentTab: MainTab? @@ -106,16 +108,17 @@ internal class MainNavigator( fun navigatePasswordSearchAuth(userType: UserType) = navController.navigatePasswordSearchAuth(userType) fun onLogoutClick() = navController.navigateToLoginRoute() fun navigatePasswordSearch(userType: UserType) = navController.navigatePasswordSearch(userType) + fun navigateNoAccount(accountType: AccountType) = navController.navigateToNoAccount(accountType) // signup navigator - fun navigateVolunteerProfile(userType: UserType) = navController.navigateToVolunteerProfile(userType) + fun navigateVolunteerProfile() = navController.navigateToVolunteerProfile() fun navigateIntermediatorProfile() = navController.navigateToIntermediatorProfile() - fun navigateRegisterEmail(userType: UserType) = navController.navigateRegisterEmail(userType) - fun navigateRegisterPassword(userType: UserType) = navController.navigateRegisterPassword(userType) + fun navigateRegisterEmail() = navController.navigateRegisterEmail() + fun navigateRegisterPassword() = navController.navigateRegisterPassword() fun navigateSelectProfileImage() = navController.navigateSelectProfileImage() - fun navigateCompleteSignUp(userType: UserType) = navController.navigateCompleteSignUp(userType) + fun navigateCompleteSignUp() = navController.navigateCompleteSignUp() fun navigateIntermediatorInformation() = navController.navigateIntermediatorInformation() - fun navigateCertification(userType: UserType) = navController.navigateToCertification(userType) + fun navigateCertification() = navController.navigateToCertification() // volunteer navigator fun navigateHome() = navigate(MainTab.HOME) @@ -176,7 +179,4 @@ internal class MainNavigator( internal fun rememberMainNavigator( navController: NavHostController = rememberNavController(), mode: AppMode -): MainNavigator = - remember(navController) { - MainNavigator(navController, mode) - } +): MainNavigator = remember(navController) { MainNavigator(navController, mode) } diff --git a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainScreen.kt b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainScreen.kt index 214a250c5..5a821f94c 100644 --- a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainScreen.kt +++ b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainScreen.kt @@ -1,6 +1,8 @@ package com.kusitms.connectdog.feature.main import android.net.Uri +import android.os.Build +import androidx.annotation.RequiresApi import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut @@ -12,7 +14,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.size -import androidx.compose.material3.Divider +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar @@ -31,20 +33,19 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.compose.NavHost import com.google.gson.Gson import com.kusitms.connectdog.core.designsystem.theme.ConnectDogTheme -import com.kusitms.connectdog.core.util.AppMode import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.login.AppMode import com.kusitms.connectdog.feature.home.navigation.homeNavGraph import com.kusitms.connectdog.feature.intermediator.navigation.intermediatorNavGraph import com.kusitms.connectdog.feature.intermediator.viewmodel.CreateApplicationViewModel -import com.kusitms.connectdog.feature.login.loginNavGraph +import com.kusitms.connectdog.feature.login.navigation.loginNavGraph import com.kusitms.connectdog.feature.management.navigation.managementNavGraph import com.kusitms.connectdog.feature.mypage.navigation.mypageNavGraph import com.kusitms.connectdog.feature.mypage.viewmodel.EditProfileViewModel import com.kusitms.connectdog.signup.navigation.signUpGraph -import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel -import com.kusitms.connectdog.signup.viewmodel.VolunteerProfileViewModel import kotlinx.collections.immutable.toPersistentList +@RequiresApi(Build.VERSION_CODES.TIRAMISU) @Composable internal fun MainScreen( mode: AppMode, @@ -55,18 +56,18 @@ internal fun MainScreen( openWebBrowser: (String) -> Unit, imeHeight: Int ) { - val profileViewModel: VolunteerProfileViewModel = hiltViewModel() - val signUpViewModel: SignUpViewModel = hiltViewModel() val editProfileViewModel: EditProfileViewModel = hiltViewModel() val createApplicationViewModel: CreateApplicationViewModel = hiltViewModel() Scaffold( content = { Box( - modifier = - Modifier + modifier = Modifier .fillMaxSize() - .background(MaterialTheme.colorScheme.onPrimary, shape = RectangleShape) + .background( + color = MaterialTheme.colorScheme.onPrimary, + shape = RectangleShape + ) ) { NavHost( navController = navigator.navController, @@ -86,23 +87,23 @@ internal fun MainScreen( onNavigateToPasswordSearchAuth = navigator::navigatePasswordSearchAuth, onSendMessage = { sendVerificationCode(it) }, onVerifyCode = { code, callback -> verifyCode(code) { callback(it) } }, - onNavigateToLoginRoute = navigator::onLogoutClick + onNavigateToLoginRoute = navigator::onLogoutClick, + onNavigateToNoAccount = navigator::navigateNoAccount ) signUpGraph( + navController = navigator.navController, onBackClick = navigator::popBackStackIfNotHome, - navigateToVolunteerProfile = { navigator.navigateVolunteerProfile(it) }, - navigateToIntermediatorInformation = { navigator.navigateIntermediatorInformation() }, - navigateToIntermediatorProfile = { navigator.navigateIntermediatorProfile() }, - navigateToRegisterEmail = { navigator.navigateRegisterEmail(it) }, - navigateToRegisterPassword = { navigator.navigateRegisterPassword(it) }, + navigateToVolunteerProfile = navigator::navigateVolunteerProfile, + navigateToIntermediatorInformation = navigator::navigateIntermediatorInformation, + navigateToIntermediatorProfile = navigator::navigateIntermediatorProfile, + navigateToRegisterEmail = navigator::navigateRegisterEmail, + navigateToRegisterPassword = navigator::navigateRegisterPassword, navigateToSelectProfileImage = { navigator.navigateSelectProfileImage() }, - navigateToCompleteSignUp = { navigator.navigateCompleteSignUp(it) }, - navigateToVolunteer = { navigator.navigateHome() }, - navigateToIntermediator = { navigator.navigateIntermediatorHome() }, + navigateToCompleteSignUp = navigator::navigateCompleteSignUp, + navigateToVolunteerHome = navigator::navigateHome, + navigateToIntermediatorHome = navigator::navigateIntermediatorHome, imeHeight = imeHeight, - signUpViewModel = signUpViewModel, - profileViewModel = profileViewModel, - navigateToCertification = { navigator.navigateCertification(it) }, + navigateToCertification = navigator::navigateCertification, onSendMessage = { sendVerificationCode(it) }, onVerifyCode = { code, callback -> verifyCode(code) { callback(it) } }, navigateToLogin = { navigator.onLogoutClick() }, @@ -190,7 +191,7 @@ internal fun MainScreen( Column( modifier = Modifier.height(68.dp) ) { - Divider(thickness = 1.dp, color = MaterialTheme.colorScheme.outline) + HorizontalDivider(thickness = 1.dp, color = MaterialTheme.colorScheme.outline) NavigationBar( containerColor = Color.Transparent, modifier = Modifier.background(Color.White) @@ -226,15 +227,10 @@ private fun NavigationIcon( selected: Boolean ) { Icon( + modifier = Modifier.size(24.dp), painter = painterResource(id = tab.iconResId), contentDescription = tab.contentDescription, - tint = - if (selected) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.onSurface - }, - modifier = Modifier.size(24.dp) + tint = if (selected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface, ) } diff --git a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainUiState.kt b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainUiState.kt new file mode 100644 index 000000000..e679dc58d --- /dev/null +++ b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainUiState.kt @@ -0,0 +1,15 @@ +package com.kusitms.connectdog.feature.main + +import com.kusitms.connectdog.domain.usecase.login.AppMode + +data class MainUiState( + val appMode: AppMode? +) { + companion object { + fun empty() = MainUiState( + appMode = null + ) + } +} + +sealed class MainSideEffect \ No newline at end of file diff --git a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainViewModel.kt b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainViewModel.kt index d1e8351fa..e4d69f3bc 100644 --- a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainViewModel.kt +++ b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainViewModel.kt @@ -1,19 +1,42 @@ package com.kusitms.connectdog.feature.main +import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.repository.DataStoreRepository +import com.kusitms.connectdog.domain.usecase.GetAppModeUseCase +import com.kusitms.connectdog.domain.usecase.UpdateFcmTokenUseCase +import com.kusitms.connectdog.feature.login.state.LoginSideEffect +import com.kusitms.connectdog.feature.login.state.LoginUiState import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container import javax.inject.Inject private const val TAG = "MAIN_VIEWMODEL" @HiltViewModel class MainViewModel @Inject constructor( - private val dataStoreRepository: DataStoreRepository -) : ViewModel() { + private val updateFcmTokenUseCase: UpdateFcmTokenUseCase, + private val getAppModeUseCase: GetAppModeUseCase +): ContainerHost, ViewModel() { + override val container: Container = container(MainUiState.empty()) + + init { + initAppMode() + } + + private fun initAppMode() = viewModelScope.launch { + getAppModeUseCase().collect { appMode -> + intent { reduce { state.copy(appMode = appMode) } } + } + } + fun updateFcmToken(token: String) = viewModelScope.launch { - dataStoreRepository.saveFcmToken(token) + updateFcmTokenUseCase(token) } } diff --git a/feature/mypage/build.gradle.kts b/feature/mypage/build.gradle.kts index 364c30bdf..c364cc3f6 100644 --- a/feature/mypage/build.gradle.kts +++ b/feature/mypage/build.gradle.kts @@ -46,7 +46,7 @@ android { } dependencies { - + implementation(projects.domain) implementation(project(":core:model")) implementation(project(":core:data")) implementation(project(":core:designsystem")) diff --git a/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/EditProfileViewModel.kt b/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/EditProfileViewModel.kt index 8418a79b3..9f7e1ee22 100644 --- a/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/EditProfileViewModel.kt +++ b/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/EditProfileViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody import com.kusitms.connectdog.core.data.api.model.volunteer.UserInfoResponse import com.kusitms.connectdog.core.data.repository.MyPageRepository +import com.kusitms.connectdog.core.model.signup.Nickname import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -42,7 +43,7 @@ class EditProfileViewModel @Inject constructor( } fun updateNicknameAvailability() { - val body = IsDuplicateNicknameBody(nickname = _nickname.value) + val body = Nickname(nickname = _nickname.value) viewModelScope.launch { try { val response = myPageRepository.postNickname(body) diff --git a/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/PasswordChangeViewModel.kt b/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/PasswordChangeViewModel.kt index c85727544..8ed0e7745 100644 --- a/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/PasswordChangeViewModel.kt +++ b/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/PasswordChangeViewModel.kt @@ -4,9 +4,9 @@ import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.repository.DataStoreRepository import com.kusitms.connectdog.core.data.repository.SignUpRepository import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.login.DeleteAccessTokenUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -16,7 +16,7 @@ import javax.inject.Inject @HiltViewModel class PasswordChangeViewModel @Inject constructor( private val repository: SignUpRepository, - private val dataStoreRepository: DataStoreRepository + private val deleteAccessTokenUseCase: DeleteAccessTokenUseCase ) : ViewModel() { private val _previousPassword: MutableState = mutableStateOf("") val previousPassword: String @@ -71,7 +71,7 @@ class PasswordChangeViewModel @Inject constructor( UserType.INTERMEDIATOR -> repository.changeInterPassword(_newPassword.value) else -> repository.changeVolunteerPassword(_newPassword.value) } - dataStoreRepository.deleteAccessToken() + deleteAccessTokenUseCase() } catch (e: Exception) { } } diff --git a/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/SettingViewModel.kt b/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/SettingViewModel.kt index 5d3e6ad9c..f0d938fdb 100644 --- a/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/SettingViewModel.kt +++ b/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/SettingViewModel.kt @@ -3,12 +3,13 @@ package com.kusitms.connectdog.feature.mypage.viewmodel import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.repository.DataStoreRepository import com.kusitms.connectdog.core.data.repository.InterManagementRepository -import com.kusitms.connectdog.core.data.repository.LoginRepository import com.kusitms.connectdog.core.data.repository.MyPageRepository -import com.kusitms.connectdog.core.util.AppMode import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.login.AppMode +import com.kusitms.connectdog.domain.usecase.login.DeleteAccessTokenUseCase +import com.kusitms.connectdog.domain.usecase.login.LogoutUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateAppModeUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow @@ -19,33 +20,30 @@ private const val TAG = "MyPageViewModel" @HiltViewModel class SettingViewModel @Inject constructor( - private val dataStoreRepository: DataStoreRepository, private val myPageRepository: MyPageRepository, - private val loginRepository: LoginRepository, - private val interRepository: InterManagementRepository + private val interRepository: InterManagementRepository, + private val updateAppModeUseCase: UpdateAppModeUseCase, + private val deleteAccessTokenUseCase: DeleteAccessTokenUseCase, + private val logoutUseCase: LogoutUseCase ) : ViewModel() { private val _isAbleWithdraw = MutableSharedFlow() val isAbleWithdraw: SharedFlow get() = _isAbleWithdraw fun initLogout() = viewModelScope.launch { - try { - dataStoreRepository.saveAppMode(AppMode.LOGIN) - loginRepository.logout() - dataStoreRepository.deleteAccessToken() - } catch (e: Exception) { - Log.d(TAG, e.message.toString()) - } + updateAppModeUseCase(AppMode.LOGIN) + deleteAccessTokenUseCase() + logoutUseCase() } fun deleteAccount(userType: UserType) = viewModelScope.launch { try { - dataStoreRepository.saveAppMode(AppMode.LOGIN) + updateAppModeUseCase(AppMode.LOGIN) when (userType) { UserType.INTERMEDIATOR -> myPageRepository.interWithdraw() else -> myPageRepository.volunteerWithdraw() } - dataStoreRepository.deleteAccessToken() + deleteAccessTokenUseCase() } catch (e: Exception) { Log.d(TAG, e.message.toString()) } diff --git a/feature/signup/build.gradle.kts b/feature/signup/build.gradle.kts index 29400106b..19fc48186 100644 --- a/feature/signup/build.gradle.kts +++ b/feature/signup/build.gradle.kts @@ -45,11 +45,17 @@ android { dependencies { - implementation(project(":core:designsystem")) - implementation(project(":core:util")) + implementation(projects.domain) + implementation(projects.core.designsystem) + implementation(projects.core.util) + implementation(projects.core.data) + implementation(projects.core.model) implementation(libs.androidx.core.splashscreen) - implementation(project(mapOf("path" to ":core:data"))) + + implementation(libs.orbit.core) + implementation(libs.orbit.compose) + implementation(libs.orbit.viewmodel) kapt(libs.hilt.compiler) implementation(libs.hilt.android) diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/navigation/SignUpNavigation.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/navigation/SignUpNavigation.kt index 7c1b822fe..56c91b56b 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/navigation/SignUpNavigation.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/navigation/SignUpNavigation.kt @@ -1,7 +1,12 @@ package com.kusitms.connectdog.signup.navigation +import android.annotation.SuppressLint +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController import androidx.navigation.NavOptions import androidx.navigation.NavType import androidx.navigation.compose.composable @@ -16,189 +21,147 @@ import com.kusitms.connectdog.signup.screen.intermediator.IntermediatorInformati import com.kusitms.connectdog.signup.screen.intermediator.IntermediatorProfileScreen import com.kusitms.connectdog.signup.screen.volunteer.SelectProfileImageScreen import com.kusitms.connectdog.signup.screen.volunteer.VolunteerProfileScreen -import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel -import com.kusitms.connectdog.signup.viewmodel.VolunteerProfileViewModel -fun NavController.navigateSignup(userType: UserType) { - navigate("${SignUpRoute.route}/$userType") -} - -fun NavController.navigateToIntermediatorProfile() { - navigate(SignUpRoute.intermediator_profile) -} - -fun NavController.navigateToCertification(userType: UserType) { - navigate("${SignUpRoute.certification}/$userType") -} - -fun NavController.navigateToVolunteerProfile(userType: UserType) { - navigate("${SignUpRoute.volunteer_profile}/$userType") -} - -fun NavController.navigateRegisterEmail(userType: UserType) { - navigate("${SignUpRoute.register_email}/$userType") -} - -fun NavController.navigateRegisterPassword(userType: UserType) { - navigate("${SignUpRoute.register_password}/$userType") -} - -fun NavController.navigateSelectProfileImage() { - navigate(SignUpRoute.profile_image) -} - -fun NavController.navigateCompleteSignUp(userType: UserType) { - val navOption = NavOptions.Builder() - .setPopUpTo(SignUpRoute.route, false) +fun NavController.navigateSignup(userType: UserType) = navigate("${SignUpRoute.ROUTE}/$userType") +fun NavController.navigateToIntermediatorProfile() = navigate(SignUpRoute.INTERMEDIATOR_PROFILE) +fun NavController.navigateToCertification() = navigate(SignUpRoute.CERTIFICATION) +fun NavController.navigateToVolunteerProfile() = navigate(SignUpRoute.VOLUNTEER_PROFILE) +fun NavController.navigateRegisterEmail() = navigate(SignUpRoute.REGISTER_EMAIL) +fun NavController.navigateRegisterPassword() = navigate(SignUpRoute.REGISTER_PASSWORD) +fun NavController.navigateSelectProfileImage() = navigate(SignUpRoute.SELECT_PROFILE_IMAGE) +fun NavController.navigateIntermediatorInformation() = navigate(SignUpRoute.INTERMEDIATOR_INFORMATION) +fun NavController.navigateCompleteSignUp() = navigate( + route = SignUpRoute.COMPLETE_SIGNUP, + navOptions = NavOptions.Builder() + .setPopUpTo(SignUpRoute.ROUTE, false) .build() - navigate("${SignUpRoute.complete_signup}/$userType", navOption) -} - -fun NavController.navigateIntermediatorInformation() { - navigate(SignUpRoute.intermediator_information) -} +) +@SuppressLint("UnrememberedGetBackStackEntry") +@RequiresApi(Build.VERSION_CODES.TIRAMISU) fun NavGraphBuilder.signUpGraph( + navController: NavHostController, onBackClick: () -> Unit, - navigateToVolunteerProfile: (UserType) -> Unit, + navigateToVolunteerProfile: () -> Unit, navigateToIntermediatorProfile: () -> Unit, navigateToIntermediatorInformation: () -> Unit, - navigateToRegisterEmail: (UserType) -> Unit, - navigateToRegisterPassword: (UserType) -> Unit, + navigateToRegisterEmail: () -> Unit, + navigateToRegisterPassword: () -> Unit, navigateToSelectProfileImage: () -> Unit, - navigateToCompleteSignUp: (UserType) -> Unit, - navigateToVolunteer: () -> Unit, - navigateToIntermediator: () -> Unit, - navigateToCertification: (UserType) -> Unit, + navigateToCompleteSignUp: () -> Unit, + navigateToVolunteerHome: () -> Unit, + navigateToIntermediatorHome: () -> Unit, + navigateToCertification: () -> Unit, navigateToLogin: () -> Unit, onSendMessage: (String) -> Unit, onVerifyCode: (String, (Boolean) -> Unit) -> Unit, openWebBrowser: (String) -> Unit, imeHeight: Int, - signUpViewModel: SignUpViewModel, - profileViewModel: VolunteerProfileViewModel ) { - val userTypeArgument = listOf( - navArgument("type") { - type = NavType.EnumType(UserType::class.java) - } - ) + val signUpRoute = "${SignUpRoute.ROUTE}/{userType}" composable( - route = "${SignUpRoute.route}/{type}", - arguments = userTypeArgument + route = signUpRoute, + arguments = listOf( + navArgument("userType") { + type = NavType.EnumType(UserType::class.java) + } + ) ) { SignUpRoute( onBackClick = navigateToLogin, - userType = it.arguments!!.getSerializable("type") as UserType, + userType = it.arguments?.getSerializable("userType", UserType::class.java) ?: UserType.NORMAL_VOLUNTEER, navigateToCertification = navigateToCertification, - openWebBrowser = openWebBrowser + openWebBrowser = openWebBrowser, + signUpViewModel = hiltViewModel(it) ) } - composable( - route = "${SignUpRoute.register_email}/{type}", - arguments = userTypeArgument - ) { + composable(route = SignUpRoute.CERTIFICATION) { + CertificationScreen( + onBackClick = onBackClick, + onNavigateToRegisterEmail = navigateToRegisterEmail, + onNavigateToVolunteerProfile = navigateToVolunteerProfile, + onSendMessageClick = onSendMessage, + onVerifyCodeClick = onVerifyCode, + imeHeight = imeHeight, + viewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) + ) + } + + composable(route = SignUpRoute.REGISTER_EMAIL) { RegisterEmailScreen( onBackClick = onBackClick, - userType = it.arguments!!.getSerializable("type") as UserType, onNavigateToRegisterPassword = navigateToRegisterPassword, - signUpViewModel = signUpViewModel, - imeHeight = imeHeight + imeHeight = imeHeight, + viewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) ) } - composable( - route = "${SignUpRoute.register_password}/{type}", - arguments = userTypeArgument - ) { + composable(route = SignUpRoute.REGISTER_PASSWORD) { RegisterPasswordScreen( onBackClick = onBackClick, onNavigateToIntermediatorProfile = navigateToIntermediatorProfile, onNavigateToVolunteerProfile = navigateToVolunteerProfile, - userType = it.arguments!!.getSerializable("type") as UserType, - signUpViewModel = signUpViewModel, - imeHeight = imeHeight + imeHeight = imeHeight, + viewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) ) } - composable( - route = "${SignUpRoute.volunteer_profile}/{type}", - arguments = userTypeArgument - ) { + composable(route = SignUpRoute.VOLUNTEER_PROFILE) { VolunteerProfileScreen( onBackClick = onBackClick, onNavigateToSelectProfileImage = navigateToSelectProfileImage, onNavigateToCompleteSignUp = navigateToCompleteSignUp, imeHeight = imeHeight, - signUpViewModel = signUpViewModel, - viewModel = profileViewModel, - userType = it.arguments!!.getSerializable("type") as UserType + viewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) ) } - composable(route = SignUpRoute.intermediator_profile) { + composable(route = SignUpRoute.INTERMEDIATOR_PROFILE) { IntermediatorProfileScreen( onBackClick = onBackClick, imeHeight = imeHeight, navigateToIntermediatorInfo = navigateToIntermediatorInformation, - signUpViewModel = signUpViewModel + viewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) ) } - composable(route = SignUpRoute.intermediator_information) { + composable(route = SignUpRoute.INTERMEDIATOR_INFORMATION) { IntermediatorInformationScreen( onBackClick = onBackClick, imeHeight = imeHeight, onNavigateToCompleteSignUp = navigateToCompleteSignUp, - signUpViewModel = signUpViewModel + signUpViewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) ) } - composable(route = SignUpRoute.profile_image) { + composable(route = SignUpRoute.SELECT_PROFILE_IMAGE) { SelectProfileImageScreen( onBackClick = onBackClick, - viewModel = profileViewModel + signUpViewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) ) } composable( - route = "${SignUpRoute.complete_signup}/{type}", - arguments = userTypeArgument + route = SignUpRoute.COMPLETE_SIGNUP, ) { CompleteSignUpScreen( - navigateToLoginRoute = navigateToLogin - ) - } - - composable( - route = "${SignUpRoute.certification}/{type}", - arguments = userTypeArgument - ) { - CertificationScreen( - onBackClick = onBackClick, - onNavigateToRegisterEmail = navigateToRegisterEmail, - onNavigateToVolunteerProfile = navigateToVolunteerProfile, - onSendMessageClick = onSendMessage, - onVerifyCodeClick = onVerifyCode, - imeHeight = imeHeight, - userType = it.arguments!!.getSerializable("type") as UserType, - signUpViewModel = signUpViewModel + viewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)), + navigateToVolunteerHome = navigateToVolunteerHome, + navigateToIntermediatorHome = navigateToIntermediatorHome ) } } object SignUpRoute { - const val route = "sign_up" - const val volunteer_profile = "volunteer_profile" - const val intermediator_profile = "intermediator_profile" - const val intermediator_information = "intermediator_information" - const val register_email = "register_email" - const val register_password = "register_password" - const val profile_image = "profile_image" - const val complete_signup = "complete_signup" - const val volunteer = "volunteer" - const val certification = "certification" - const val intermediator = "intermediator" + const val ROUTE = "sign_up" + const val VOLUNTEER_PROFILE = "volunteer_profile" + const val INTERMEDIATOR_PROFILE = "intermediator_profile" + const val INTERMEDIATOR_INFORMATION = "intermediator_information" + const val REGISTER_EMAIL = "register_email" + const val REGISTER_PASSWORD = "register_password" + const val SELECT_PROFILE_IMAGE = "profile_image" + const val COMPLETE_SIGNUP = "complete_signup" + const val CERTIFICATION = "certification" } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CeritificationScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CeritificationScreen.kt index 74828f3e8..c49dca9ce 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CeritificationScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CeritificationScreen.kt @@ -1,7 +1,7 @@ package com.kusitms.connectdog.signup.screen.common import android.annotation.SuppressLint -import android.widget.Toast +import android.util.Log import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement @@ -22,7 +22,6 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -30,41 +29,52 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavBackStackEntry import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextFieldWithTimer import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.Gray6 -import com.kusitms.connectdog.core.designsystem.theme.Gray8 +import com.kusitms.connectdog.core.designsystem.theme.Gray100 +import com.kusitms.connectdog.core.designsystem.theme.Gray60 +import com.kusitms.connectdog.core.designsystem.theme.Red1 import com.kusitms.connectdog.core.util.UserType import com.kusitms.connectdog.feature.signup.R -import com.kusitms.connectdog.signup.state.CertificationSideEffect -import com.kusitms.connectdog.signup.viewmodel.CertificationViewModel +import com.kusitms.connectdog.signup.state.SignUpSideEffect import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel import org.orbitmvi.orbit.compose.collectAsState import org.orbitmvi.orbit.compose.collectSideEffect -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "ResourceType") @Composable fun CertificationScreen( onBackClick: () -> Unit, - onNavigateToRegisterEmail: (UserType) -> Unit, - onNavigateToVolunteerProfile: (UserType) -> Unit, + onNavigateToRegisterEmail: () -> Unit, + onNavigateToVolunteerProfile: () -> Unit, onSendMessageClick: (String) -> Unit, onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, imeHeight: Int, - userType: UserType, - signUpViewModel: SignUpViewModel, - viewModel: CertificationViewModel = hiltViewModel() + viewModel: SignUpViewModel, ) { + val uiState by viewModel.collectAsState() + + viewModel.collectSideEffect { sideEffect -> + when (sideEffect) { + is SignUpSideEffect.NavigateToProfile -> onNavigateToVolunteerProfile() + is SignUpSideEffect.NavigateToEmailRegister -> onNavigateToRegisterEmail() + else -> Unit + } + } + + LaunchedEffect(Unit) { + Log.d("aswwwwaa", uiState.userType.toString()) + } + Scaffold( topBar = { ConnectDogTopAppBar( - titleRes = when (userType) { - UserType.INTERMEDIATOR -> R.string.intermediator_signup - else -> R.string.volunteer_signup - }, + titleRes = uiState.userType.topBarTitleRes, navigationType = TopAppBarNavigationType.BACK, navigationIconContentDescription = "Navigation icon", onNavigationClick = onBackClick @@ -72,14 +82,10 @@ fun CertificationScreen( } ) { Content( - onNavigateToRegisterEmail = { onNavigateToRegisterEmail(userType) }, - onNavigateToVolunteerProfile = { onNavigateToVolunteerProfile(userType) }, onSendMessageClick = onSendMessageClick, onVerifyCodeClick = onVerifyCodeClick, imeHeight = imeHeight, - userType = userType, viewModel = viewModel, - signUpViewModel = signUpViewModel ) } } @@ -87,48 +93,20 @@ fun CertificationScreen( @Composable private fun Content( imeHeight: Int, - userType: UserType, - onNavigateToRegisterEmail: (UserType) -> Unit, - onNavigateToVolunteerProfile: (UserType) -> Unit, onSendMessageClick: (String) -> Unit, onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, - signUpViewModel: SignUpViewModel, - viewModel: CertificationViewModel + viewModel: SignUpViewModel, ) { val focusManager = LocalFocusManager.current val interactionSource = remember { MutableInteractionSource() } - val context = LocalContext.current val scrollState = rememberScrollState() - val uiState by viewModel.collectAsState() - LaunchedEffect(key1 = signUpViewModel) { - signUpViewModel.isDuplicatePhoneNumber.collect { - if (it) { - Toast.makeText(context, "중복된 휴대폰 번호입니다.", Toast.LENGTH_SHORT).show() - } else { - Toast.makeText(context, "인증번호를 전송하였습니다.", Toast.LENGTH_SHORT).show() - } - } - } - - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - is CertificationSideEffect.NavigateToProfile -> { - signUpViewModel.updateName(uiState.name) - signUpViewModel.updatePhoneNumber(uiState.phoneNumber) - when (userType) { - UserType.SOCIAL_VOLUNTEER -> onNavigateToVolunteerProfile(userType) - else -> onNavigateToRegisterEmail(userType) - } - } - } - } - Column( modifier = Modifier .fillMaxSize() - .padding(start = 20.dp, end = 20.dp, top = 32.dp) + .padding(vertical = 32.dp) + .padding(horizontal = 20.dp) .clickable( onClick = { focusManager.clearFocus() }, indication = null, @@ -145,8 +123,8 @@ private fun Content( Spacer(modifier = Modifier.height(40.dp)) ConnectDogTextField( text = uiState.name, - label = "이름", - placeholder = "이름 입력", + label = stringResource(id = R.string.name), + placeholder = stringResource(id = R.string.input_name), keyboardType = KeyboardType.Text, onTextChanged = viewModel::onNameChanged ) @@ -155,48 +133,61 @@ private fun Content( text = uiState.phoneNumber, onTextChanged = viewModel::onPhoneNumberChanged, label = stringResource(id = R.string.phone_number), - placeholder = "'-'빼고 입력", + placeholder = stringResource(id = R.string.phone_number_requirement), keyboardType = KeyboardType.Number ) - - if (uiState.isSendCertificationNumber) { + if (uiState.isSendPhoneAuthCode) { Spacer(modifier = Modifier.height(12.dp)) ConnectDogTextFieldWithTimer( - text = uiState.certificationNumber, - textFieldLabel = "인증번호", - placeholder = "숫자 6자리", + text = uiState.phoneAuthCode, + textFieldLabel = stringResource(id = R.string.auth_code), + placeholder = stringResource(id = R.string.auth_code_requirement), keyboardType = KeyboardType.Number, - onTextChanged = viewModel::onChangeCertificationNumber + onTextChanged = viewModel::onPhoneAuthCodeChanged, + isError = (uiState.isPhoneNumberCertified == false) ) + if(uiState.isPhoneNumberCertified == false) { + Text( + modifier = Modifier.padding(top = 4.dp), + text = stringResource(id = R.string.auth_code_incorrect), + color = Red1, + fontSize = 10.sp + ) + } Spacer(modifier = Modifier.height(28.dp)) Row( modifier = Modifier.fillMaxSize(), horizontalArrangement = Arrangement.Center ) { Text( - text = "인증번호가 오지 않는다면?", - color = Gray6, + text = stringResource(id = R.string.resend_title), + color = Gray60, fontSize = 12.sp ) Spacer(modifier = Modifier.width(8.dp)) Text( modifier = Modifier.clickable { }, - text = "재발송", + text = stringResource(id = R.string.resend), fontSize = 12.sp, - color = Gray8, + color = Gray100, fontWeight = FontWeight.SemiBold ) } } Spacer(modifier = Modifier.weight(1f)) ConnectDogNormalButton( - content = uiState.bottomButtonText, - enabled = if (!uiState.isSendCertificationNumber) uiState.enableNext else uiState.enableCertification, modifier = Modifier .fillMaxWidth() .height(56.dp), - onClick = { viewModel.onNextClick(onSendMessageClick, onVerifyCodeClick) } + content = uiState.phoneCertificationButtonText, + enabled = uiState.enablePhoneCertification, + onClick = { + viewModel.onPhoneCertificationButtonClick( + onSendMessageClick = onSendMessageClick, + onVerifyCodeClick = onVerifyCodeClick, + ) + } ) - Spacer(modifier = Modifier.height((imeHeight + 32).dp)) + Spacer(modifier = Modifier.height((imeHeight).dp)) } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CompleteSignUpScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CompleteSignUpScreen.kt index f7a523a16..9651ffa40 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CompleteSignUpScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CompleteSignUpScreen.kt @@ -2,8 +2,6 @@ package com.kusitms.connectdog.signup.screen.common import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -14,12 +12,10 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.layout -import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign @@ -27,24 +23,28 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.kusitms.connectdog.core.designsystem.R import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton +import com.kusitms.connectdog.signup.state.SignUpSideEffect +import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel +import org.orbitmvi.orbit.compose.collectSideEffect @Composable fun CompleteSignUpScreen( - navigateToLoginRoute: () -> Unit + viewModel: SignUpViewModel, + navigateToVolunteerHome: () -> Unit, + navigateToIntermediatorHome: () -> Unit, ) { - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } + viewModel.collectSideEffect { + when(it) { + is SignUpSideEffect.NavigateToVolunteerHome -> navigateToVolunteerHome() + is SignUpSideEffect.NavigateToIntermediatorHome -> navigateToIntermediatorHome() + else -> Unit + } + } Box( - modifier = - Modifier + modifier = Modifier .fillMaxSize() .background(Color.White) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) ) { Image( painter = painterResource(id = R.drawable.background), @@ -75,8 +75,7 @@ fun CompleteSignUpScreen( } ConnectDogNormalButton( content = "확인", - modifier = - Modifier + modifier = Modifier .fillMaxWidth() .height(56.dp) .align(Alignment.BottomCenter) @@ -87,7 +86,7 @@ fun CompleteSignUpScreen( placeable.place(0, 0) } }, - onClick = navigateToLoginRoute + onClick = viewModel::onStartClick ) } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterEmailScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterEmailScreen.kt index d3c209f8b..aec0bea17 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterEmailScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterEmailScreen.kt @@ -1,6 +1,7 @@ package com.kusitms.connectdog.signup.screen.common import android.annotation.SuppressLint +import android.util.Log import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Column @@ -11,136 +12,130 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel -import com.kusitms.connectdog.core.designsystem.R +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavBackStackEntry import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton -import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextFieldWithButton +import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.ConnectDogTheme -import com.kusitms.connectdog.core.designsystem.theme.Gray5 -import com.kusitms.connectdog.core.designsystem.theme.PetOrange import com.kusitms.connectdog.core.designsystem.theme.Red1 import com.kusitms.connectdog.core.util.UserType -import com.kusitms.connectdog.signup.viewmodel.RegisterEmailViewModel +import com.kusitms.connectdog.feature.signup.R +import com.kusitms.connectdog.signup.state.SignUpSideEffect +import com.kusitms.connectdog.signup.state.SignUpUiState import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "ResourceType") @Composable fun RegisterEmailScreen( onBackClick: () -> Unit, - userType: UserType, - onNavigateToRegisterPassword: (UserType) -> Unit, - signUpViewModel: SignUpViewModel, - viewModel: RegisterEmailViewModel = hiltViewModel(), - imeHeight: Int + onNavigateToRegisterPassword: () -> Unit, + viewModel: SignUpViewModel, + imeHeight: Int, ) { - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } - val context = LocalContext.current - val isValidEmail by viewModel.isValidEmail.collectAsState() - val isEmailVerified by viewModel.isEmailVerified.collectAsState() - val isEmailDuplicated by viewModel.isEmailDuplicated.collectAsState() + val uiState by viewModel.collectAsState() + + LaunchedEffect(key1 = Unit) { + Log.d("aswwwwaa", uiState.userType.toString()) + } + + viewModel.collectSideEffect { + when(it) { + SignUpSideEffect.NavigateToPasswordRegister -> onNavigateToRegisterPassword() + else -> Unit + } + } Scaffold( topBar = { ConnectDogTopAppBar( - titleRes = when (userType) { - UserType.SOCIAL_VOLUNTEER -> R.string.volunteer_signup - UserType.NORMAL_VOLUNTEER -> R.string.volunteer_signup - UserType.INTERMEDIATOR -> R.string.intermediator_signup - }, + titleRes = uiState.userType.topBarTitleRes, navigationType = TopAppBarNavigationType.BACK, - navigationIconContentDescription = "Navigation icon", onNavigationClick = onBackClick ) } ) { - Column( - modifier = Modifier - .padding(horizontal = 20.dp) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) - ) { - Spacer(modifier = Modifier.height(80.dp)) - Text( - text = "로그인에 사용할\n이메일을 입력해주세요", - fontSize = 20.sp, - fontWeight = FontWeight.Bold - ) - Spacer(modifier = Modifier.height(40.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.email, - width = 62, - height = 27, - textFieldLabel = "이메일", - placeholder = "이메일 입력", - buttonLabel = "인증 요청", - isError = (isValidEmail ?: false) || (isEmailDuplicated ?: false), - onTextChanged = { - viewModel.updateEmail(it) - viewModel.updateEmailValidity() - }, - borderColor = if (isValidEmail == false && isEmailDuplicated == false) PetOrange else Gray5, - onClick = { viewModel.postEmail(context) }, - padding = 5 - ) - Spacer(modifier = Modifier.height(12.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.certificationNumber, - width = 62, - height = 27, - textFieldLabel = "인증 번호", - placeholder = "숫자 6자리", - buttonLabel = "인증 확인", - keyboardType = KeyboardType.Text, - onTextChanged = { viewModel.updateCertificationNumber(it) }, - borderColor = if (viewModel.isEmailVerified.value == true) PetOrange else if (viewModel.isEmailVerified.value == false) Red1 else Gray5, - onClick = { viewModel.checkCertificationNumber(context) }, - padding = 5, - isError = isEmailVerified == false - ) - Spacer(modifier = Modifier.weight(1f)) - ConnectDogBottomButton( - content = "다음", - enabled = isEmailVerified == true, - onClick = { - signUpViewModel.updateEmail(viewModel.email) - onNavigateToRegisterPassword(userType) - }, - modifier = Modifier - .fillMaxWidth() - .height(56.dp) - ) - Spacer(modifier = Modifier.height((imeHeight + 32).dp)) - } + Content( + viewModel = viewModel, + imeHeight = imeHeight, + uiState = uiState + ) } } -@Preview @Composable -private fun test() { - ConnectDogTheme { - RegisterEmailScreen( - onBackClick = {}, - userType = UserType.NORMAL_VOLUNTEER, - onNavigateToRegisterPassword = {}, - hiltViewModel(), - imeHeight = 10 +private fun Content( + viewModel: SignUpViewModel, + uiState: SignUpUiState, + imeHeight: Int +) { + val focusManager = LocalFocusManager.current + val interactionSource = remember { MutableInteractionSource() } + + Column( + modifier = Modifier + .padding(horizontal = 20.dp) + .clickable( + onClick = { focusManager.clearFocus() }, + indication = null, + interactionSource = interactionSource + ) + ) { + Spacer(modifier = Modifier.height(80.dp)) + Text( + text = stringResource(id = R.string.email_auth_title), + fontSize = 20.sp, + fontWeight = FontWeight.Bold ) + Spacer(modifier = Modifier.height(40.dp)) + ConnectDogTextField( + text = uiState.email, + label = stringResource(id = R.string.email), + placeholder = stringResource(id = R.string.input_email), + isError = uiState.isValidEmail == false, + onTextChanged = viewModel::onEmailChanged, + ) + Spacer(modifier = Modifier.height(12.dp)) + if (uiState.isSendEmailAuthCode) { + ConnectDogTextField( + text = uiState.inputEmailAuthCode, + label = stringResource(id = R.string.auth_code), + placeholder = stringResource(id = R.string.input_auth_code), + keyboardType = KeyboardType.Text, + onTextChanged = viewModel::onEmailAuthCodeChanged, + isError = uiState.isEmailAuthCodeError == true + ) + if(uiState.isEmailAuthCodeError == true) { + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = "올바른 인증번호를 입력해주세요", + fontSize = 10.sp, + color = Red1 + ) + } + } + Spacer(modifier = Modifier.weight(1f)) + ConnectDogBottomButton( + modifier = Modifier + .fillMaxWidth() + .height(56.dp), + content = uiState.emailCertificationButtonText, + enabled = uiState.enableEmailCertification, + onClick = viewModel::onEmailCertificationButtonClick, + ) + Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } -} +} \ No newline at end of file diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterPasswordScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterPasswordScreen.kt index a89ab5eb4..ab065ae89 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterPasswordScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterPasswordScreen.kt @@ -1,6 +1,7 @@ package com.kusitms.connectdog.signup.screen.common import android.annotation.SuppressLint +import android.util.Log import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource @@ -13,139 +14,122 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.hilt.navigation.compose.hiltViewModel -import com.kusitms.connectdog.core.designsystem.R +import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.ConnectDogTheme import com.kusitms.connectdog.core.designsystem.theme.Gray3 -import com.kusitms.connectdog.core.designsystem.theme.Orange_40 -import com.kusitms.connectdog.core.designsystem.theme.PetOrange -import com.kusitms.connectdog.core.util.UserType -import com.kusitms.connectdog.signup.viewmodel.RegisterPasswordViewModel +import com.kusitms.connectdog.feature.signup.R +import com.kusitms.connectdog.signup.state.SignUpSideEffect +import com.kusitms.connectdog.signup.state.SignUpUiState import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "ResourceType") @Composable fun RegisterPasswordScreen( onBackClick: () -> Unit, - onNavigateToVolunteerProfile: (UserType) -> Unit, + onNavigateToVolunteerProfile: () -> Unit, onNavigateToIntermediatorProfile: () -> Unit, - userType: UserType, imeHeight: Int, - signUpViewModel: SignUpViewModel, - viewModel: RegisterPasswordViewModel = hiltViewModel() + viewModel: SignUpViewModel ) { - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } - val isValidPassword by viewModel.isValidPassword.collectAsState() - val isValidConfirmPassword by viewModel.isValidConfirmPassword.collectAsState() + val uiState by viewModel.collectAsState() + viewModel.collectSideEffect { + when(it) { + is SignUpSideEffect.NavigateToProfile -> onNavigateToVolunteerProfile() + else -> Unit + } + } Scaffold( topBar = { ConnectDogTopAppBar( - titleRes = when (userType) { - UserType.INTERMEDIATOR -> R.string.intermediator_signup - else -> R.string.volunteer_signup - }, + titleRes = uiState.userType.topBarTitleRes, navigationType = TopAppBarNavigationType.BACK, navigationIconContentDescription = "Navigation icon", onNavigationClick = onBackClick ) } ) { - Column( - modifier = Modifier - .fillMaxSize() - .background(Color.White) - .padding(horizontal = 20.dp) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) - ) { - Spacer(modifier = Modifier.height(80.dp)) - Text( - text = "로그인에 사용할\n비밀번호를 입력해주세요", - fontSize = 20.sp, - fontWeight = FontWeight.Bold - ) - Spacer(modifier = Modifier.height(40.dp)) - ConnectDogTextField( - text = viewModel.password, - label = "비밀번호", - placeholder = "비밀번호 입력", - keyboardType = KeyboardType.Password, - isError = isValidPassword ?: false, - onTextChanged = { - viewModel.updatePassword(it) - viewModel.checkPasswordValidity(it) - } - ) - Spacer(modifier = Modifier.height(12.dp)) - ConnectDogTextField( - text = viewModel.confirmPassword, - label = "비밀번호 확인", - placeholder = "비밀번호 확인", - keyboardType = KeyboardType.Password, - isError = isValidConfirmPassword ?: false, - onTextChanged = { - viewModel.updateConfirmPassword(it) - viewModel.checkConfirmPasswordValidity(it) - } - ) - Spacer(modifier = Modifier.height(4.dp)) - Text( - text = "영문+숫자 10자 이상", - modifier = Modifier.padding(start = 8.dp), - fontSize = 11.sp, - color = Gray3 - ) - Spacer(modifier = Modifier.weight(1f)) - ConnectDogNormalButton( - content = "다음", - modifier = - Modifier - .fillMaxWidth() - .height(56.dp), - color = if (isValidPassword == false && isValidConfirmPassword == false) { - PetOrange - } else { - Orange_40 - }, - onClick = { - if (isValidPassword == false && isValidConfirmPassword == false) { - signUpViewModel.updatePassword(viewModel.password) - when (userType) { - UserType.INTERMEDIATOR -> onNavigateToIntermediatorProfile() - else -> onNavigateToVolunteerProfile(userType) - } - } - } - ) - Spacer(modifier = Modifier.height((imeHeight + 32).dp)) - } + Content( + viewModel = viewModel, + imeHeight = imeHeight, + uiState = uiState + ) } } -@Preview + @Composable -private fun Preview() { - ConnectDogTheme { - RegisterPasswordScreen({}, {}, {}, UserType.INTERMEDIATOR, 10, hiltViewModel()) +private fun Content( + viewModel: SignUpViewModel, + imeHeight: Int, + uiState: SignUpUiState, +) { + val focusManager = LocalFocusManager.current + val interactionSource = remember { MutableInteractionSource() } + + Column( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + .padding(horizontal = 20.dp) + .clickable( + onClick = { focusManager.clearFocus() }, + indication = null, + interactionSource = interactionSource + ) + ) { + Spacer(modifier = Modifier.height(80.dp)) + Text( + text = stringResource(id = R.string.register_password_title), + fontSize = 20.sp, + fontWeight = FontWeight.Bold + ) + Spacer(modifier = Modifier.height(40.dp)) + ConnectDogTextField( + text = uiState.password, + label = stringResource(id = R.string.password), + placeholder = stringResource(id = R.string.input_passwrod), + keyboardType = KeyboardType.Password, + isError = (uiState.isValidPassword == false), + onTextChanged = viewModel::onPasswordChanged + ) + Spacer(modifier = Modifier.height(12.dp)) + ConnectDogTextField( + text = uiState.confirmPassword, + label = stringResource(id = R.string.confirm_password), + placeholder = stringResource(id = R.string.confirm_password), + keyboardType = KeyboardType.Password, + isError = uiState.isValidConfirmPassword == false, + onTextChanged = viewModel::onConfirmPasswordChanged + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = stringResource(id = R.string.password_requirement), + modifier = Modifier.padding(start = 8.dp), + fontSize = 11.sp, + color = Gray3 + ) + Spacer(modifier = Modifier.weight(1f)) + ConnectDogBottomButton( + content = stringResource(id = R.string.next), + enabled = uiState.enablePasswordRegister, + onClick = viewModel::onPasswordRegisterNextButtonClick + ) + Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/TermScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/TermScreen.kt index 5150ea00e..32b00c309 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/TermScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/TermScreen.kt @@ -1,64 +1,49 @@ package com.kusitms.connectdog.signup.screen.common -import android.view.Gravity -import android.widget.Toast +import android.annotation.SuppressLint import androidx.activity.compose.BackHandler -import androidx.compose.foundation.Canvas import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue -import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel -import com.kusitms.connectdog.core.designsystem.R -import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton +import com.kusitms.connectdog.core.designsystem.component.CheckBox +import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar +import com.kusitms.connectdog.core.designsystem.component.HorizontalLine import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.Gray1 -import com.kusitms.connectdog.core.designsystem.theme.Gray2 import com.kusitms.connectdog.core.designsystem.theme.Gray3 -import com.kusitms.connectdog.core.designsystem.theme.Gray4 -import com.kusitms.connectdog.core.designsystem.theme.Orange_40 -import com.kusitms.connectdog.core.designsystem.theme.PetOrange import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.feature.signup.R +import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel import com.kusitms.connectdog.signup.viewmodel.TermsViewModel +import org.orbitmvi.orbit.compose.collectAsState @Composable internal fun SignUpRoute( onBackClick: () -> Unit, - navigateToCertification: (UserType) -> Unit, + navigateToCertification: () -> Unit, openWebBrowser: (String) -> Unit, - userType: UserType + userType: UserType, + signUpViewModel: SignUpViewModel ) { + LaunchedEffect(key1 = Unit) { + signUpViewModel.updateUserType(userType) + } + TermScreen( onBackClick = onBackClick, userType = userType, @@ -67,195 +52,97 @@ internal fun SignUpRoute( ) } +@SuppressLint("ResourceType", "UnusedMaterial3ScaffoldPaddingParameter") @Composable private fun TermScreen( userType: UserType, onBackClick: () -> Unit, - navigateToCertification: (UserType) -> Unit, + navigateToCertification: () -> Unit, openWebBrowser: (String) -> Unit, - viewModel: TermsViewModel = hiltViewModel() + viewModel: TermsViewModel = hiltViewModel(), ) { - val allChecked by viewModel.allChecked.observeAsState(initial = false) - val privacyChecked by viewModel.privacyChecked.observeAsState(initial = false) - val advertisementChecked by viewModel.advertisementChecked.observeAsState(initial = false) - val termsChecked by viewModel.termsChecked.observeAsState(initial = false) - val isAvailableNext by viewModel.isAvailableNext.observeAsState(initial = false) - - val context = LocalContext.current - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } - BackHandler { onBackClick() } - - Box( - modifier = - Modifier - .fillMaxSize() - .background(Color.White) - .padding(bottom = 32.dp) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) - ) { - Column( - modifier = Modifier - .fillMaxSize() - .background(Color.White) - ) { + Scaffold( + topBar = { ConnectDogTopAppBar( - titleRes = when (userType) { - UserType.SOCIAL_VOLUNTEER -> R.string.volunteer_signup - UserType.NORMAL_VOLUNTEER -> R.string.volunteer_signup - UserType.INTERMEDIATOR -> R.string.intermediator_signup - }, + titleRes = userType.topBarTitleRes, navigationType = TopAppBarNavigationType.BACK, navigationIconContentDescription = "Navigation icon", onNavigationClick = onBackClick ) - Spacer(modifier = Modifier.height(32.dp)) - Text( - text = "코넥독 서비스 이용약관에\n동의해주세요", - fontSize = 20.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(start = 20.dp) - ) - Spacer(modifier = Modifier.height(40.dp)) - - CustomCheckbox( - text = "모두 동의", - checked = allChecked, - hasDetail = false, - onCheckedChange = { - viewModel.updateAllChecked() - viewModel.updateTermsChecked() - viewModel.updatePrivacyChecked() - viewModel.updateAdvertisementChecked() - } - ) - - Spacer(modifier = Modifier.height(16.dp)) - HorizontalLine() - Spacer(modifier = Modifier.height(16.dp)) - CustomCheckbox( - text = "[필수] 이용약관 동의", - checked = termsChecked, - hasDetail = true, - onDetailClick = { openWebBrowser("https://docs.google.com/document/d/1Rr2sqZVGLVIqNyqI_YoaBazTZ2tqapRlX2zdqtM1ICs/edit?usp=sharing") }, - onCheckedChange = { viewModel.updateTermsChecked() } - ) - Spacer(modifier = Modifier.height(16.dp)) - CustomCheckbox( - text = "[필수] 개인정보 수집 및 이용 동의", - checked = privacyChecked, - onCheckedChange = { viewModel.updatePrivacyChecked() }, - hasDetail = true, - onDetailClick = { openWebBrowser("https://docs.google.com/document/d/14nF3hzCFfTVGSecKDddO4FJYy27v_c8BUkAU2w_m1O4/edit?usp=sharing") } - ) - Spacer(modifier = Modifier.height(16.dp)) - CustomCheckbox( - text = "[선택] 광고성 정보 수신 동의", - checked = advertisementChecked, - onCheckedChange = { viewModel.updateAdvertisementChecked() }, - hasDetail = true, - onDetailClick = { openWebBrowser("https://docs.google.com/document/d/14nF3hzCFfTVGSecKDddO4FJYy27v_c8BUkAU2w_m1O4/edit?usp=sharing") } - ) } - ConnectDogNormalButton( - content = "다음", - color = if (isAvailableNext) { - PetOrange - } else { - Orange_40 - }, - modifier = - Modifier - .fillMaxWidth() - .height(56.dp) - .align(Alignment.BottomCenter) - .padding(horizontal = 20.dp), - onClick = { - if (isAvailableNext) { - navigateToCertification(userType) - } else { - val toast = Toast.makeText(context, "모든 약관에 동의해주세요", Toast.LENGTH_SHORT) - toast.setGravity(Gravity.BOTTOM, 10, 1000) - toast.show() - } - } - ) - } -} - -@Composable -fun HorizontalLine() { - Canvas( - modifier = Modifier - .fillMaxWidth() - .height(1.dp) - .padding(horizontal = 20.dp) ) { - drawLine( - color = Gray3, - start = Offset(0f, 0f), - end = Offset(size.width, 0f), - strokeWidth = 1f + Content( + viewModel = viewModel, + navigateToCertification = navigateToCertification, + openWebBrowser = openWebBrowser ) } } @Composable -fun CustomCheckbox( - text: String, - checked: Boolean, - onCheckedChange: (Boolean) -> Unit, - hasDetail: Boolean, - onDetailClick: () -> Unit = {} +private fun Content( + viewModel: TermsViewModel, + navigateToCertification: () -> Unit, + openWebBrowser: (String) -> Unit, ) { - var isChecked by remember { mutableStateOf(checked) } - - if (checked != isChecked) { - isChecked = checked - } + val uiState by viewModel.collectAsState() - Row( - modifier = Modifier.padding(horizontal = 20.dp), - verticalAlignment = Alignment.CenterVertically + Column( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + .padding(top = 48.dp, bottom = 32.dp) ) { - Row( - modifier = Modifier.clickable { - isChecked = !isChecked - onCheckedChange(isChecked) - }, - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - painter = painterResource( - id = R.drawable.ic_checked - ), - contentDescription = "Custom Checkbox", - tint = if (isChecked) MaterialTheme.colorScheme.primary else Gray4, - modifier = Modifier.size(24.dp) - ) - Spacer(modifier = Modifier.width(12.dp)) - Text( - text = text, - fontSize = 14.sp, - fontWeight = FontWeight.Medium, - color = if (isChecked) Color.Black else Gray2 - ) - } + Spacer(modifier = Modifier.height(32.dp)) + Text( + text = "코넥독 서비스 이용약관에\n동의해주세요", + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(start = 20.dp) + ) + Spacer(modifier = Modifier.height(40.dp)) + CheckBox( + text = uiState.agreeAll.title, + checked = uiState.agreeAll.isChecked, + hasDetail = uiState.agreeAll.hasDetail, + onClick = viewModel::onAgreeAllClick + ) + Spacer(modifier = Modifier.height(16.dp)) + HorizontalLine( + height = 1, + color = Gray3 + ) + Spacer(modifier = Modifier.height(16.dp)) + CheckBox( + text = uiState.termsOfService.title, + checked = uiState.termsOfService.isChecked, + hasDetail = uiState.termsOfService.hasDetail, + onDetailClick = { openWebBrowser(uiState.termsOfService.url!!) }, + onClick = viewModel::onTermsOfServiceClick + ) + Spacer(modifier = Modifier.height(16.dp)) + CheckBox( + text = uiState.privacy.title, + checked = uiState.privacy.isChecked, + onClick = viewModel::onPrivacyClick, + hasDetail = uiState.privacy.hasDetail, + onDetailClick = { openWebBrowser(uiState.privacy.url!!) } + ) + Spacer(modifier = Modifier.height(16.dp)) + CheckBox( + text = uiState.advertisement.title, + checked = uiState.advertisement.isChecked, + onClick = viewModel::onAdvertisementClick, + hasDetail = uiState.advertisement.hasDetail, + onDetailClick = { openWebBrowser(uiState.advertisement.url!!) } + ) Spacer(modifier = Modifier.weight(1f)) - if (hasDetail) { - Text( - text = "보기", - style = TextStyle(textDecoration = TextDecoration.Underline), - fontSize = 14.sp, - fontWeight = FontWeight.Medium, - color = if (isChecked) Gray1 else Gray2, - modifier = Modifier.clickable { onDetailClick() } - ) - } + ConnectDogBottomButton( + modifier = Modifier.padding(horizontal = 20.dp), + content = stringResource(id = R.string.next), + enabled = uiState.enableNext, + onClick = navigateToCertification + ) } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorInformationScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorInformationScreen.kt index 33d657781..943e9c1d8 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorInformationScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorInformationScreen.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavBackStackEntry import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar @@ -35,7 +36,7 @@ import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel @Composable fun IntermediatorInformationScreen( onBackClick: () -> Unit, - onNavigateToCompleteSignUp: (UserType) -> Unit, + onNavigateToCompleteSignUp: () -> Unit, imeHeight: Int, viewModel: IntermediatorInformationViewModel = hiltViewModel(), signUpViewModel: SignUpViewModel @@ -91,10 +92,10 @@ fun IntermediatorInformationScreen( ConnectDogNormalButton( content = "다음", onClick = { - onNavigateToCompleteSignUp(UserType.INTERMEDIATOR) - signUpViewModel.updateUrl(viewModel.url) - signUpViewModel.updateContact(viewModel.contact) - signUpViewModel.postIntermediatorSignUp(context) + onNavigateToCompleteSignUp() +// signUpViewModel.updateUrl(viewModel.url) +// signUpViewModel.updateContact(viewModel.contact) +// signUpViewModel.postIntermediatorSignUp(context) }, modifier = Modifier .fillMaxWidth() diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorProfileScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorProfileScreen.kt index 08aa12052..9c4a438fb 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorProfileScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorProfileScreen.kt @@ -44,6 +44,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavBackStackEntry import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogOutlinedButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField @@ -56,6 +57,7 @@ import com.kusitms.connectdog.core.designsystem.theme.Red1 import com.kusitms.connectdog.feature.signup.R import com.kusitms.connectdog.signup.viewmodel.IntermediatorProfileViewModel import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel +import org.orbitmvi.orbit.compose.collectAsState @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable @@ -63,10 +65,34 @@ fun IntermediatorProfileScreen( onBackClick: () -> Unit, navigateToIntermediatorInfo: () -> Unit, imeHeight: Int, - viewModel: IntermediatorProfileViewModel = hiltViewModel(), - signUpViewModel: SignUpViewModel + viewModel: SignUpViewModel +) { + Scaffold( + topBar = { + ConnectDogTopAppBar( + titleRes = R.string.intermediator_signup, + navigationType = TopAppBarNavigationType.BACK, + onNavigationClick = onBackClick + ) + } + ) { + Content( + viewModel = viewModel, + imeHeight = imeHeight + ) + } +} + +@Composable +private fun Content( + viewModel: SignUpViewModel, + imeHeight: Int ) { val context = LocalContext.current + val focusManager = LocalFocusManager.current + val interactionSource = remember { MutableInteractionSource() } + val scrollState = rememberScrollState() + val uiState by viewModel.collectAsState() fun convertToBitmap(uri: Uri): Bitmap = ImageDecoder .decodeBitmap( @@ -78,124 +104,108 @@ fun IntermediatorProfileScreen( onResult = { imageUri = it } ) - Scaffold( - topBar = { - ConnectDogTopAppBar( - titleRes = R.string.intermediator_signup, - navigationType = TopAppBarNavigationType.BACK, - onNavigationClick = onBackClick + Column( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + .padding(horizontal = 20.dp) + .clickable( + onClick = { focusManager.clearFocus() }, + indication = null, + interactionSource = interactionSource ) - } + .verticalScroll(scrollState) ) { - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } - val scrollState = rememberScrollState() - - val isDuplicatedName by viewModel.isDuplicateName.collectAsState() - - Column( + LaunchedEffect(imeHeight) { + scrollState.animateScrollTo(scrollState.maxValue) + } + Spacer(modifier = Modifier.height(80.dp)) + Text( + text = "모집자 프로필에 사용할\n정보를 입력해주세요", + fontSize = 20.sp, + fontWeight = FontWeight.Bold + ) + Spacer(modifier = Modifier.height(40.dp)) + Row( modifier = Modifier - .fillMaxSize() - .background(Color.White) - .padding(horizontal = 20.dp) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) - .verticalScroll(scrollState) + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center ) { - LaunchedEffect(imeHeight) { - scrollState.animateScrollTo(scrollState.maxValue) - } - Spacer(modifier = Modifier.height(80.dp)) - Text( - text = "모집자 프로필에 사용할\n정보를 입력해주세요", - fontSize = 20.sp, - fontWeight = FontWeight.Bold - ) - Spacer(modifier = Modifier.height(40.dp)) - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - imageUri?.let { - Image( - bitmap = convertToBitmap(it).asImageBitmap(), - modifier = Modifier - .size(100.dp) - .clip(CircleShape), - contentDescription = "" - ) - viewModel.updateUri(it) - } ?: run { - Image( - painter = painterResource(id = com.kusitms.connectdog.core.util.R.drawable.ic_profile_1), - contentDescription = "" - ) - } - } - Spacer(modifier = Modifier.height(12.dp)) - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - ConnectDogOutlinedButton( - width = 105, - height = 27, - text = "프로필 사진 선택", - padding = 5, - onClick = { - photoPicker.launch( - PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly) - ) - } + imageUri?.let { + Image( + bitmap = convertToBitmap(it).asImageBitmap(), + modifier = Modifier + .size(100.dp) + .clip(CircleShape), + contentDescription = "" + ) +// viewModel.updateUri(it) + } ?: run { + Image( + painter = painterResource(id = com.kusitms.connectdog.core.util.R.drawable.ic_profile_1), + contentDescription = "" ) } - Spacer(modifier = Modifier.height(40.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.name, - width = 62, + } + Spacer(modifier = Modifier.height(12.dp)) + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + ConnectDogOutlinedButton( + width = 105, height = 27, - textFieldLabel = stringResource(id = R.string.intermediator_name), - placeholder = stringResource(id = R.string.intermediator_name_input), + text = "프로필 사진 선택", padding = 5, - onTextChanged = viewModel::updateName, - isError = isDuplicatedName == true, - onClick = { viewModel.checkNickNameDuplicate() } - ) - Spacer(modifier = Modifier.height(4.dp)) - Text( - text = if (isDuplicatedName == true) "이미 사용중인 모집자명입니다." else if (isDuplicatedName == false) "사용 가능한 모집자명 입니다." else "", - fontSize = 10.sp, - color = if (isDuplicatedName == true) Red1 else if (isDuplicatedName == false) PetOrange else Gray1, - fontWeight = FontWeight.Normal - ) - Spacer(modifier = Modifier.height(6.dp)) - ConnectDogTextField( - text = viewModel.introduce, - onTextChanged = viewModel::updateIntroduce, - placeholder = stringResource(id = R.string.introduce_placeholder), - height = 130 - ) - Spacer(modifier = Modifier.height(20.dp)) - Spacer(modifier = Modifier.weight(1f)) - ConnectDogBottomButton( - content = "다음", - modifier = Modifier - .fillMaxWidth() - .height(56.dp), - enabled = viewModel.name != "" && viewModel.introduce != "" && viewModel.uri != null, onClick = { - navigateToIntermediatorInfo() - signUpViewModel.updateIntro(viewModel.introduce) - signUpViewModel.updateNickname(viewModel.name) - signUpViewModel.updateInterProfileImage(viewModel.uri!!) + photoPicker.launch( + PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly) + ) } ) - Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } + Spacer(modifier = Modifier.height(40.dp)) + ConnectDogTextFieldWithButton( + text = uiState.name, + width = 62, + height = 27, + textFieldLabel = stringResource(id = R.string.intermediator_name), + placeholder = stringResource(id = R.string.intermediator_name_input), + padding = 5, + onTextChanged = {}, + isError = false, + onClick = { } + ) + Spacer(modifier = Modifier.height(4.dp)) +// Text( +// text = if (isDuplicatedName == true) "이미 사용중인 모집자명입니다." else if (isDuplicatedName == false) "사용 가능한 모집자명 입니다." else "", +// fontSize = 10.sp, +// color = if (isDuplicatedName == true) Red1 else if (isDuplicatedName == false) PetOrange else Gray1, +// fontWeight = FontWeight.Normal +// ) +// Spacer(modifier = Modifier.height(6.dp)) +// ConnectDogTextField( +// text = viewModel.introduce, +// onTextChanged = viewModel::updateIntroduce, +// placeholder = stringResource(id = R.string.introduce_placeholder), +// height = 130 +// ) +// Spacer(modifier = Modifier.height(20.dp)) +// Spacer(modifier = Modifier.weight(1f)) +// ConnectDogBottomButton( +// content = "다음", +// modifier = Modifier +// .fillMaxWidth() +// .height(56.dp), +// enabled = viewModel.name != "" && viewModel.introduce != "" && viewModel.uri != null, +// onClick = { +// navigateToIntermediatorInfo() +// signUpViewModel.updateIntro(viewModel.introduce) +// signUpViewModel.updateNickname(viewModel.name) +// signUpViewModel.updateInterProfileImage(viewModel.uri!!) +// } +// ) + Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/SelectProfileImageScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/SelectProfileImageScreen.kt index b529efb04..fef8fcf95 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/SelectProfileImageScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/SelectProfileImageScreen.kt @@ -1,11 +1,11 @@ package com.kusitms.connectdog.signup.screen.volunteer +import android.annotation.SuppressLint import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -15,85 +15,96 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.kusitms.connectdog.core.designsystem.R +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavBackStackEntry +import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType import com.kusitms.connectdog.core.designsystem.theme.Orange_40 import com.kusitms.connectdog.core.designsystem.theme.PetOrange import com.kusitms.connectdog.core.util.getProfileImageId -import com.kusitms.connectdog.signup.viewmodel.VolunteerProfileViewModel +import com.kusitms.connectdog.feature.signup.R +import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel +import com.kusitms.connectdog.signup.viewmodel.SelectProfileImageViewModel +import org.orbitmvi.orbit.compose.collectAsState +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "ResourceType") @Composable fun SelectProfileImageScreen( onBackClick: () -> Unit, - viewModel: VolunteerProfileViewModel + viewModel: SelectProfileImageViewModel = hiltViewModel(), + signUpViewModel: SignUpViewModel ) { - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } - val selectedImageIndex by viewModel.selectedImageIndex.collectAsState() + val uiState by signUpViewModel.collectAsState() - Box( - modifier = Modifier - .fillMaxSize() - .background(Color.White) - .padding(bottom = 32.dp) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) - ) { - Column( - modifier = Modifier - .fillMaxSize() - .background(Color.White) - ) { + LaunchedEffect(key1 = Unit) { + viewModel.updateProfileImageIndex(uiState.profileImageId) + } + + Scaffold( + topBar = { ConnectDogTopAppBar( - titleRes = R.string.volunteer_signup, + titleRes = uiState.userType.topBarTitleRes, navigationType = TopAppBarNavigationType.BACK, - navigationIconContentDescription = "Navigation icon", onNavigationClick = onBackClick ) - Spacer(modifier = Modifier.height(32.dp)) - Text( - text = "프로필 이미지를\n선택해주세요", - fontSize = 20.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(horizontal = 20.dp) - ) - Spacer(modifier = Modifier.height(40.dp)) - ProfileImageGrid(selectedImageIndex, viewModel) } + ) { + Content( + onBackClick = onBackClick, + viewModel = viewModel, + updateProfileImageIndex = signUpViewModel::updateProfileImageIndex + ) + } +} - ConnectDogNormalButton( - content = "선택", - color = if (selectedImageIndex != -1) { - PetOrange - } else { - Orange_40 - }, - modifier = Modifier - .fillMaxWidth() - .height(56.dp) - .align(Alignment.BottomCenter) - .padding(horizontal = 20.dp), +@Composable +private fun Content( + onBackClick: () -> Unit, + viewModel: SelectProfileImageViewModel, + updateProfileImageIndex: (Int) -> Unit +) { + val uiState by viewModel.collectAsState() + + Column( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + .padding(top = 48.dp, bottom = 32.dp) + .padding(horizontal = 20.dp) + ) { + Spacer(modifier = Modifier.height(32.dp)) + Text( + text = stringResource(id = R.string.select_profile_image_title), + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + ) + Spacer(modifier = Modifier.height(40.dp)) + ProfileImageGrid( + selectedImageIndex = uiState.selectedImageId, + updateProfileImageIndex = viewModel::updateProfileImageIndex + ) + Spacer(modifier = Modifier.weight(1f)) + ConnectDogBottomButton( + content = stringResource(id = R.string.select), onClick = { - viewModel.updateProfileImageIndex(selectedImageIndex) + updateProfileImageIndex(uiState.selectedImageId) onBackClick() } ) @@ -103,7 +114,7 @@ fun SelectProfileImageScreen( @Composable fun ProfileImageGrid( selectedImageIndex: Int, - viewModel: VolunteerProfileViewModel + updateProfileImageIndex: (Int) -> Unit ) { val modifier = Modifier .padding(15.dp) @@ -124,16 +135,11 @@ fun ProfileImageGrid( .weight(1f) .clickable( indication = null, - interactionSource = remember { MutableInteractionSource() } - ) { - viewModel.updateProfileImageIndex(index) - } - .then( - if (selectedImageIndex == index) { - modifier.border(4.dp, PetOrange, CircleShape) - } else { - modifier - } + interactionSource = remember { MutableInteractionSource() }, + onClick = { updateProfileImageIndex(index) } + ).then( + if (selectedImageIndex != index) modifier + else modifier.border(4.dp, PetOrange, CircleShape) ) ) } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/VolunteerProfileScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/VolunteerProfileScreen.kt index c68834f62..038be72ee 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/VolunteerProfileScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/VolunteerProfileScreen.kt @@ -16,7 +16,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier @@ -26,36 +25,39 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavBackStackEntry +import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogOutlinedButton -import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextFieldWithButton +import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.Gray5 -import com.kusitms.connectdog.core.designsystem.theme.Orange_40 -import com.kusitms.connectdog.core.designsystem.theme.PetOrange import com.kusitms.connectdog.core.designsystem.theme.Red1 import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.core.util.getProfileImageId import com.kusitms.connectdog.feature.signup.R +import com.kusitms.connectdog.signup.state.SignUpSideEffect import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel -import com.kusitms.connectdog.signup.viewmodel.VolunteerProfileViewModel +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable fun VolunteerProfileScreen( onBackClick: () -> Unit, onNavigateToSelectProfileImage: () -> Unit, - onNavigateToCompleteSignUp: (UserType) -> Unit, - userType: UserType, + onNavigateToCompleteSignUp: () -> Unit, imeHeight: Int, - signUpViewModel: SignUpViewModel, - viewModel: VolunteerProfileViewModel + viewModel: SignUpViewModel ) { - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } - val isDuplicatedNickname by viewModel.isDuplicatedNickname.collectAsState() - val selectedImageIndex by viewModel.selectedImageIndex.collectAsState() - val isAvailableNickname by viewModel.isAvailableNickname.collectAsState() + viewModel.collectSideEffect { + when(it) { + is SignUpSideEffect.NavigateToSignUpComplete -> onNavigateToCompleteSignUp() + else -> Unit + } + } Scaffold( topBar = { @@ -67,102 +69,87 @@ fun VolunteerProfileScreen( ) } ) { - Column( - modifier = Modifier - .fillMaxSize() - .background(Color.White) - .padding(horizontal = 20.dp) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) + Content( + viewModel = viewModel, + onNavigateToSelectProfileImage = onNavigateToSelectProfileImage, + imeHeight = imeHeight + ) + } +} + +@Composable +private fun Content( + viewModel: SignUpViewModel, + onNavigateToSelectProfileImage: () -> Unit, + imeHeight: Int, +) { + val focusManager = LocalFocusManager.current + val interactionSource = remember { MutableInteractionSource() } + val uiState by viewModel.collectAsState() + + Column( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + .padding(horizontal = 20.dp) + .clickable( + onClick = { focusManager.clearFocus() }, + indication = null, + interactionSource = interactionSource + ) + ) { + Spacer(modifier = Modifier.height(80.dp)) + Text( + text = "프로필 정보를\n입력해주세요", + fontSize = 20.sp, + fontWeight = FontWeight.Bold + ) + Spacer(modifier = Modifier.height(40.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center ) { - Spacer(modifier = Modifier.height(80.dp)) - Text( - text = "프로필 정보를\n입력해주세요", - fontSize = 20.sp, - fontWeight = FontWeight.Bold + Image( + painter = painterResource(id = getProfileImageId(uiState.profileImageId)), + contentDescription = "volunteer profile image" ) - Spacer(modifier = Modifier.height(40.dp)) - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - Image( - painter = painterResource(id = viewModel.getProfileImageId()), - contentDescription = "volunteer profile image" - ) - } - Spacer(modifier = Modifier.height(12.dp)) - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - ConnectDogOutlinedButton( - width = 105, - height = 27, - text = "프로필 사진 선택", - padding = 5, - onClick = onNavigateToSelectProfileImage - ) - } - Spacer(modifier = Modifier.height(40.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.nickname, - width = 62, + } + Spacer(modifier = Modifier.height(12.dp)) + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + ConnectDogOutlinedButton( + width = 105, height = 27, - textFieldLabel = "닉네임", - placeholder = "닉네임 입력", - buttonLabel = "중복 확인", - onClick = { - viewModel.updateNicknameAvailability(it) - }, - onTextChanged = { - viewModel.updateNickname(it) - viewModel.isAvailableNickname() - }, - borderColor = if (isDuplicatedNickname == false) Red1 else if (isDuplicatedNickname == true) PetOrange else Gray5, + text = "프로필 사진 선택", padding = 5, - isError = (isDuplicatedNickname == false) || (isAvailableNickname ?: false) + onClick = onNavigateToSelectProfileImage ) + } + Spacer(modifier = Modifier.height(40.dp)) + ConnectDogTextField( + text = uiState.nickname, + label = "닉네임", + placeholder = "닉네임 입력", + onTextChanged = viewModel::onNickNameChanged, + isError = uiState.isDuplicatedNickname == true + ) + if(uiState.isDuplicatedNickname == true) { Text( - text = isDuplicatedNickname?.let { - if (!it) { "이미 사용중인 닉네임 입니다." } else { "사용할 수 있는 닉네임 입니다." } - } ?: run { "" }, - color = when (isDuplicatedNickname?.not()) { - false -> PetOrange - else -> Red1 - }, + modifier = Modifier.padding(top = 4.dp, start = 8.dp), + text = uiState.nickNameErrorMessage, + color = Red1, fontSize = 11.sp, - modifier = Modifier.padding(top = 4.dp, start = 8.dp) - ) - Spacer(modifier = Modifier.weight(1f)) - ConnectDogNormalButton( - content = "다음", - modifier = - Modifier - .fillMaxWidth() - .height(56.dp), - color = if (selectedImageIndex != -1 && isDuplicatedNickname == true) { PetOrange } else { Orange_40 }, - onClick = { - if (selectedImageIndex != -1 && isDuplicatedNickname == true) { - signUpViewModel.apply { - this.updateNickname(viewModel.nickname) - this.updateProfileImageId(viewModel.selectedImageIndex.value) - when (userType) { - UserType.SOCIAL_VOLUNTEER -> this.postSocialVolunteerSignUp() - UserType.NORMAL_VOLUNTEER -> this.postNormalVolunteerSignUp() - UserType.INTERMEDIATOR -> {} - } - } - onNavigateToCompleteSignUp(userType) - } - } ) - Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } + Spacer(modifier = Modifier.weight(1f)) + ConnectDogBottomButton( + content = "중복 확인", + onClick = viewModel::onCheckNicknameDuplicationButtonClick, + enabled = uiState.enableNicknameDuplication + ) + Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SelectProfileImageUiState.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SelectProfileImageUiState.kt new file mode 100644 index 000000000..62eaa71ed --- /dev/null +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SelectProfileImageUiState.kt @@ -0,0 +1,13 @@ +package com.kusitms.connectdog.signup.state + +data class SelectProfileImageUiState( + val selectedImageId: Int +) { + companion object { + fun empty() = SelectProfileImageUiState( + selectedImageId = 1 + ) + } +} + +sealed class SelectProfileImageSideEffect diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SignUpUiState.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SignUpUiState.kt new file mode 100644 index 000000000..e143e33c6 --- /dev/null +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SignUpUiState.kt @@ -0,0 +1,95 @@ +package com.kusitms.connectdog.signup.state + +import android.net.Uri +import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.core.util.emptyString + +data class SignUpUiState( + val userType: UserType, + val email: String, + val password: String, + val confirmPassword: String, + val isValidPassword: Boolean?, + val isValidConfirmPassword: Boolean?, + val nickname: String, + val nicknameRegex: Regex, + val nickNameErrorMessage: String, + val profileImageId: Int, + val phoneNumber: String, + val phoneAuthCode: String, + val isSendPhoneAuthCode: Boolean, + val isDuplicatedPhoneNumber: Boolean, + val contact: String, + val intro: String, + val url: String, + val name: String, + val intermediatorProfileImage: Uri?, + val phoneCertificationButtonText: String, + val emailCertificationButtonText: String, + val enablePhoneCertification: Boolean, + val enableEmailCertification: Boolean, + val enablePasswordRegister: Boolean, + val enableNicknameDuplication: Boolean, + val isPhoneNumberCertified: Boolean?, + val isSendEmailAuthCode: Boolean, + val inputEmailAuthCode: String, + val emailAuthCode: String, + val isEmailAuthCodeError: Boolean?, + val isValidEmail: Boolean?, + val isAvailableNickName: Boolean, + val isDuplicatedNickname: Boolean?, + val isDuplicatedEmail: Boolean, + val englishAndNumberRegex: Regex, + val englishNumberSpecialRegex: Regex +) { + companion object { + fun empty() = SignUpUiState( + userType = UserType.INTERMEDIATOR, + email = emptyString(), + password = emptyString(), + confirmPassword = emptyString(), + isValidPassword = null, + isValidConfirmPassword = null, + nickname = emptyString(), + nicknameRegex = "^[ㄱ-ㅎ]+$".toRegex(), + nickNameErrorMessage = emptyString(), + profileImageId = 0, + phoneNumber = emptyString(), + phoneAuthCode = emptyString(), + isSendPhoneAuthCode = false, + contact = emptyString(), + intro = emptyString(), + url = emptyString(), + name = emptyString(), + intermediatorProfileImage = null, + phoneCertificationButtonText = "인증 요청", + emailCertificationButtonText = "인증 요청", + enablePhoneCertification = false, + enableEmailCertification = false, + enablePasswordRegister = false, + enableNicknameDuplication = false, + isPhoneNumberCertified = null, + isSendEmailAuthCode = false, + inputEmailAuthCode = emptyString(), + emailAuthCode = emptyString(), + isEmailAuthCodeError = null, + isValidEmail = null, + isAvailableNickName = false, + isDuplicatedNickname = null, + isDuplicatedEmail = false, + isDuplicatedPhoneNumber = false, + englishAndNumberRegex = Regex("^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{10,}$"), + englishNumberSpecialRegex = Regex("^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@#\$%^&+=!])[A-Za-z\\d@#\$%^&+=!]{8,}$") + ) + } +} + +sealed class SignUpSideEffect { + object NavigateToProfile : SignUpSideEffect() + object NavigateToEmailRegister: SignUpSideEffect() + object NavigateToPasswordRegister: SignUpSideEffect() + object NavigateToSignUpComplete: SignUpSideEffect() + object NavigateToVolunteerHome: SignUpSideEffect() + object NavigateToIntermediatorHome: SignUpSideEffect() + object NavigateTo: SignUpSideEffect() +} \ No newline at end of file diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/TermsUiState.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/TermsUiState.kt new file mode 100644 index 000000000..195950be6 --- /dev/null +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/TermsUiState.kt @@ -0,0 +1,48 @@ +package com.kusitms.connectdog.signup.state + +data class CheckBoxDetail( + val title: String, + val isChecked: Boolean, + val hasDetail: Boolean, + val url: String?, +) + +data class TermsUiState( + val agreeAll: CheckBoxDetail, + val termsOfService: CheckBoxDetail, + val privacy: CheckBoxDetail, + val advertisement: CheckBoxDetail, + val enableNext: Boolean, +) { + companion object { + fun empty() = TermsUiState( + agreeAll = CheckBoxDetail( + title = "모두 동의", + isChecked = false, + hasDetail = false, + url = null + ), + termsOfService = CheckBoxDetail( + title = "[필수] 이용약관 동의", + isChecked = false, + hasDetail = true, + url = "https://docs.google.com/document/d/14nF3hzCFfTVGSecKDddO4FJYy27v_c8BUkAU2w_m1O4/edit?usp=sharing" + ), + privacy = CheckBoxDetail( + title = "[필수] 개인정보 수집 및 이용 동의", + isChecked = false, + hasDetail = true, + url = "https://docs.google.com/document/d/14nF3hzCFfTVGSecKDddO4FJYy27v_c8BUkAU2w_m1O4/edit?usp=sharing" + ), + advertisement = CheckBoxDetail( + title = "[선택] 광고성 정보 수신 동의", + isChecked = false, + hasDetail = true, + url = "https://docs.google.com/document/d/14nF3hzCFfTVGSecKDddO4FJYy27v_c8BUkAU2w_m1O4/edit?usp=sharing" + ), + enableNext = false + ) + } +} + +sealed class TermsSideEffect diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/CertificationViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/CertificationViewModel.kt index fd256b665..b1aa56b8a 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/CertificationViewModel.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/CertificationViewModel.kt @@ -12,7 +12,9 @@ import org.orbitmvi.orbit.viewmodel.container import javax.inject.Inject @HiltViewModel -class CertificationViewModel @Inject constructor() : ContainerHost, ViewModel() { +class CertificationViewModel @Inject constructor( + +) : ContainerHost, ViewModel() { override val container = container(CertificationUiState.empty()) private val state: CertificationUiState get() = container.stateFlow.value diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/IntermediatorProfileViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/IntermediatorProfileViewModel.kt index 4a80f14ab..a8657f554 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/IntermediatorProfileViewModel.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/IntermediatorProfileViewModel.kt @@ -50,8 +50,8 @@ class IntermediatorProfileViewModel @Inject constructor( name = _name.value ) try { - val response = signUpRepository.isDuplicateInterNickName(body) - _isDuplicateName.value = response.isDuplicated +// val response = signUpRepository.isDuplicateInterNickName(body) +// _isDuplicateName.value = response.isDuplicated } catch (e: Exception) { } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/RegisterEmailViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/RegisterEmailViewModel.kt deleted file mode 100644 index 71de8c338..000000000 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/RegisterEmailViewModel.kt +++ /dev/null @@ -1,89 +0,0 @@ -package com.kusitms.connectdog.signup.viewmodel - -import android.content.Context -import android.widget.Toast -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailCertificationBody -import com.kusitms.connectdog.core.data.repository.SignUpRepository -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import javax.inject.Inject - -@HiltViewModel -class RegisterEmailViewModel @Inject constructor( - private val signUpRepository: SignUpRepository -) : ViewModel() { - private val _isEmailVerified: MutableStateFlow = MutableStateFlow(null) - val isEmailVerified: StateFlow - get() = _isEmailVerified - - private val _isEmailDuplicated: MutableStateFlow = MutableStateFlow(null) - val isEmailDuplicated: StateFlow - get() = _isEmailDuplicated - - private val _isValidEmail: MutableStateFlow = MutableStateFlow(null) - val isValidEmail: StateFlow - get() = _isValidEmail - - private val _email: MutableState = mutableStateOf("") - val email: String - get() = _email.value - - private var postNumber: String = "" - - private val _certificationNumber: MutableState = mutableStateOf("") - val certificationNumber: String - get() = _certificationNumber.value - - fun updateEmail(email: String) { - _email.value = email - } - - fun updateCertificationNumber(certificationNumber: String) { - _certificationNumber.value = certificationNumber - } - - fun updateEmailValidity() { - _isValidEmail.value = !android.util.Patterns.EMAIL_ADDRESS.matcher(_email.value).matches() - } - - fun updateEmailVerify(value: Boolean) { - _isEmailVerified.value = value - } - - fun postEmail(context: Context) = viewModelScope.launch { - if (isValidEmail.value == true) { - Toast.makeText(context, "유효한 이메일을 입력해주세요", Toast.LENGTH_SHORT).show() - return@launch - } - - val body = EmailCertificationBody(_email.value) - try { - val response = signUpRepository.postEmail(body) - Toast.makeText(context, "이메일을 전송했습니다", Toast.LENGTH_SHORT).show() - _isEmailDuplicated.value = false - postNumber = response.authCode - } catch (e: Exception) { - _isEmailDuplicated.value = true - Toast.makeText(context, "이미 가입된 이메일입니다.", Toast.LENGTH_SHORT).show() - } - } - - fun checkCertificationNumber(context: Context) { - if (_certificationNumber.value.isEmpty()) { - Toast.makeText(context, "인증번호를 입력해주세요", Toast.LENGTH_SHORT).show() - } else { - _isEmailVerified.value = _certificationNumber.value == postNumber - if (_isEmailVerified.value == true) { - Toast.makeText(context, "인증이 완료되었습니다", Toast.LENGTH_SHORT).show() - } else if (_isEmailVerified.value == true) { - Toast.makeText(context, "인증에 실패하였습니다", Toast.LENGTH_SHORT).show() - } - } - } -} diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SelectProfileImageViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SelectProfileImageViewModel.kt new file mode 100644 index 000000000..03e7ee887 --- /dev/null +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SelectProfileImageViewModel.kt @@ -0,0 +1,23 @@ +package com.kusitms.connectdog.signup.viewmodel + +import androidx.lifecycle.ViewModel +import com.kusitms.connectdog.signup.state.SelectProfileImageSideEffect +import com.kusitms.connectdog.signup.state.SelectProfileImageUiState +import dagger.hilt.android.lifecycle.HiltViewModel +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container +import javax.inject.Inject + +private const val TAG = "VolunteerProfileViewModel" + +@HiltViewModel +class SelectProfileImageViewModel @Inject constructor(): ContainerHost, ViewModel() { + override val container: Container = container(SelectProfileImageUiState.empty()) + private val state: SelectProfileImageUiState + get() = container.stateFlow.value + + fun updateProfileImageIndex(imageIndex: Int) = intent { reduce { state.copy(selectedImageId = imageIndex) } } +} diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SignUpViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SignUpViewModel.kt index a54722e02..e40bf338a 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SignUpViewModel.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SignUpViewModel.kt @@ -1,203 +1,347 @@ package com.kusitms.connectdog.signup.viewmodel -import android.content.Context -import android.net.Uri import android.util.Log +import android.util.Patterns import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberBody -import com.kusitms.connectdog.core.data.api.model.NormalLoginBody -import com.kusitms.connectdog.core.data.api.model.SocialLoginBody -import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorSignUpBody -import com.kusitms.connectdog.core.data.api.model.volunteer.NormalVolunteerSignUpBody -import com.kusitms.connectdog.core.data.api.model.volunteer.SocialVolunteerSignUpBody -import com.kusitms.connectdog.core.data.repository.DataStoreRepository -import com.kusitms.connectdog.core.data.repository.LoginRepository -import com.kusitms.connectdog.core.data.repository.SignUpRepository -import com.kusitms.connectdog.core.util.AppMode -import com.kusitms.connectdog.core.util.ImageConverter import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.auth.GetEmailAuthCodeUseCase +import com.kusitms.connectdog.domain.usecase.auth.GetIntermediatorPhoneNumberDuplicationUseCase +import com.kusitms.connectdog.domain.usecase.auth.GetVolunteerPhoneNumberDuplicationUseCase +import com.kusitms.connectdog.domain.usecase.login.AppMode +import com.kusitms.connectdog.domain.usecase.login.SocialLoginUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateAccessTokenUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateAppModeUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateRefreshTokenUseCase +import com.kusitms.connectdog.domain.usecase.login.VolunteerLoginUseCase +import com.kusitms.connectdog.domain.usecase.signup.GetIntermediatorNameDuplication +import com.kusitms.connectdog.domain.usecase.signup.GetSocialProviderUseCase +import com.kusitms.connectdog.domain.usecase.signup.GetSocialTokenUseCase +import com.kusitms.connectdog.domain.usecase.signup.GetVolunteerNicknameDuplication +import com.kusitms.connectdog.domain.usecase.signup.InitNormalVolunteerSignUpUseCase +import com.kusitms.connectdog.domain.usecase.signup.InitSocialVolunteerSignUpUseCase +import com.kusitms.connectdog.signup.state.SignUpSideEffect +import com.kusitms.connectdog.signup.state.SignUpUiState import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.postSideEffect +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container import javax.inject.Inject private const val TAG = "SignUpViewModel" @HiltViewModel class SignUpViewModel @Inject constructor( - private val signupRepository: SignUpRepository, - private val loginRepository: LoginRepository, - private val dataStoreRepository: DataStoreRepository -) : ViewModel() { - private val _email = MutableStateFlow("") - private val _password = MutableStateFlow("") - private val _nickname = MutableStateFlow("") - private val _profileImageId = MutableStateFlow(null) - private val _phoneNumber = MutableStateFlow("") - private val _contact = MutableStateFlow("") - private val _intro = MutableStateFlow("") - private val _url = MutableStateFlow("") - private val _name = MutableStateFlow("") - private val _interProfileImage = MutableStateFlow(null) + private val getVolunteerPhoneNumberDuplicationUseCase: GetVolunteerPhoneNumberDuplicationUseCase, + private val getIntermediatorPhoneNumberDuplicationUseCase: GetIntermediatorPhoneNumberDuplicationUseCase, + private val getEmailAuthCodeUseCase: GetEmailAuthCodeUseCase, + private val getNicknameDuplicationUseCase: GetVolunteerNicknameDuplication, + private val getIntermediatorNameDuplicationUseCase: GetIntermediatorNameDuplication, + private val initNormalVolunteerSignUpUseCase: InitNormalVolunteerSignUpUseCase, + private val initSocialVolunteerSignUpUseCase: InitSocialVolunteerSignUpUseCase, + private val volunteerLoginUseCase: VolunteerLoginUseCase, + private val socialLoginUseCase: SocialLoginUseCase, + private val updateAccessTokenUseCase: UpdateAccessTokenUseCase, + private val updateRefreshTokenUseCase: UpdateRefreshTokenUseCase, + private val updateAppModeUseCase: UpdateAppModeUseCase, + private val getSocialTokenUseCase: GetSocialTokenUseCase, + private val getSocialProviderUseCase: GetSocialProviderUseCase, +) : ContainerHost, ViewModel() { + override val container: Container = + container(SignUpUiState.empty()) + private val state: SignUpUiState + get() = container.stateFlow.value - val isDuplicatePhoneNumber = MutableSharedFlow() + fun updateUserType(userType: UserType) = intent { + reduce { state.copy(userType = userType) } + } + + /*이름, 휴대폰 번호 인증*/ + fun onNameChanged(name: String) = intent { + reduce { state.copy(name = name) } + enableSendPhoneAuthCodeButton() + } - fun updateEmail(email: String) { - _email.value = email + fun onPhoneNumberChanged(phoneNumber: String) = intent { + if (phoneNumber.length <= 11) reduce { state.copy(phoneNumber = phoneNumber) } + enableSendPhoneAuthCodeButton() } - fun updatePassword(password: String) { - _password.value = password + fun onPhoneAuthCodeChanged(authCode: String) { + if (authCode.length <= 6) intent { reduce { state.copy(phoneAuthCode = authCode) } } + enableSendPhoneAuthCodeButton() } - fun updateNickname(nickname: String) { - _nickname.value = nickname + fun onPhoneCertificationButtonClick( + onSendMessageClick: (String) -> Unit, + onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, + ) { + if (!state.isSendPhoneAuthCode) { + when (state.userType) { + UserType.INTERMEDIATOR -> getIntermediatorPhoneNumberDuplication() + else -> getVolunteerPhoneNumberDuplication() + } + if (!state.isDuplicatedPhoneNumber) sendPhoneAuthCode(onSendMessageClick) + else intent { postSideEffect(SignUpSideEffect.NavigateTo) } + } else checkPhoneAuthCode(onVerifyCodeClick, state.userType) } - fun updateProfileImageId(profileImageId: Int) { - _profileImageId.value = profileImageId + private fun getVolunteerPhoneNumberDuplication() = viewModelScope.launch { + getVolunteerPhoneNumberDuplicationUseCase( + phone = state.phoneNumber + ).onSuccess { + intent { reduce { state.copy(isDuplicatedPhoneNumber = it.isDuplicated) } } + }.onFailure { + + } } - fun updateName(name: String) { - _name.value = name + private fun getIntermediatorPhoneNumberDuplication() = viewModelScope.launch { + getIntermediatorPhoneNumberDuplicationUseCase( + phone = state.phoneNumber + ).onSuccess { + intent { reduce { state.copy(isDuplicatedPhoneNumber = it.isDuplicated) } } + }.onFailure { + + } } - fun updateIntro(intro: String) { - _intro.value = intro + private fun sendPhoneAuthCode(sendMessage: (String) -> Unit) { + sendMessage(state.phoneNumber) + intent { + reduce { + state.copy( + isSendPhoneAuthCode = true, + enablePhoneCertification = false + ) + } + } + updatePhoneCertificationButtonText() } - fun updateUrl(url: String) { - _url.value = url + private fun enableSendPhoneAuthCodeButton() = intent { + if (!state.isSendPhoneAuthCode && state.phoneNumber.length == 11 && state.name.isNotEmpty()) { + reduce { state.copy(enablePhoneCertification = true) } + } else if (state.isSendPhoneAuthCode && state.phoneAuthCode.length == 6) { + reduce { state.copy(enablePhoneCertification = true) } + } else { + reduce { state.copy(enablePhoneCertification = false) } + } } - fun updateContact(contact: String) { - _contact.value = contact + private fun checkPhoneAuthCode( + onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, + userType: UserType, + ) { +// onVerifyCodeClick(state.phoneAuthCode) { isCertified -> +// intent { reduce { state.copy(isPhoneNumberCertified = isCertified) } } +// if (isCertified) intent { +// when(userType) { +// UserType.SOCIAL_VOLUNTEER -> postSideEffect(SignUpSideEffect.NavigateToProfile) +// else -> postSideEffect(SignUpSideEffect.NavigateToEmailRegister) +// } +// } +// } + intent { + when (userType) { + UserType.SOCIAL_VOLUNTEER -> postSideEffect(SignUpSideEffect.NavigateToProfile) + else -> postSideEffect(SignUpSideEffect.NavigateToEmailRegister) + } + } } - fun updatePhoneNumber(phone: String) { - _phoneNumber.value = phone + private fun updatePhoneCertificationButtonText() = + intent { reduce { state.copy(phoneCertificationButtonText = "인증 확인") } } + + /*이메일 인증*/ + fun onEmailChanged(email: String) = intent { + reduce { state.copy(email = email) } + checkValidEmail() + enableEmailCertification() } - fun updateInterProfileImage(uri: Uri) { - _interProfileImage.value = uri + fun onEmailAuthCodeChanged(authCode: String) = intent { + if (authCode.length <= 8) reduce { state.copy(inputEmailAuthCode = authCode) } + enableEmailCertification() } - fun postNormalVolunteerSignUp() = viewModelScope.launch { - val body = NormalVolunteerSignUpBody( - name = _name.value, - phone = _phoneNumber.value, - email = _email.value, - nickname = _nickname.value, - password = _password.value, - profileImageNum = _profileImageId.value!! - ) - try { - signupRepository.postNormalVolunteerSignUp(body) - } catch (e: Exception) { - Log.d(TAG, e.message.toString()) + private fun enableEmailCertification() = intent { + if (!state.isSendEmailAuthCode && state.isValidEmail == true) reduce { + state.copy(enableEmailCertification = true) + } + else if (state.isSendEmailAuthCode && state.inputEmailAuthCode.length == 8) reduce { + state.copy(enableEmailCertification = true) } + else reduce { state.copy(enableEmailCertification = false) } } - fun setAutoLogin(appMode: AppMode, userType: UserType) = viewModelScope.launch { - val body = NormalLoginBody( - email = _email.value, - password = _password.value - ) - val socialBody = SocialLoginBody( - accessToken = dataStoreRepository.socialTokenFlow.first()!!, - provider = dataStoreRepository.socialProviderFlow.first()!! - ) - try { - when (userType) { - UserType.SOCIAL_VOLUNTEER -> { - val response = loginRepository.postSocialLoginData(socialBody) - dataStoreRepository.apply { - saveAppMode(appMode) - saveAccessToken(response.accessToken) - saveRefreshToken(response.refreshToken) - } - } + fun onEmailCertificationButtonClick() { + if (!state.isSendEmailAuthCode) getEmailAuthCode() + else checkEmailAuthCode() + } - UserType.NORMAL_VOLUNTEER -> { - val response = loginRepository.postLoginData(body) - dataStoreRepository.apply { - saveAppMode(appMode) - saveAccessToken(response.accessToken) - saveRefreshToken(response.refreshToken) - } - } + private fun checkEmailAuthCode() = intent { + reduce { state.copy(isEmailAuthCodeError = state.inputEmailAuthCode != state.emailAuthCode) } + if (state.isEmailAuthCodeError == false) postSideEffect(SignUpSideEffect.NavigateToPasswordRegister) + } + + private fun checkValidEmail() = intent { + reduce { state.copy(isValidEmail = Patterns.EMAIL_ADDRESS.matcher(state.email).matches()) } + } - UserType.INTERMEDIATOR -> { - val response = loginRepository.postIntermediatorLoginData(body) - dataStoreRepository.apply { - saveAppMode(appMode) - saveAccessToken(response.accessToken) - saveRefreshToken(response.refreshToken) - } + private fun getEmailAuthCode() = viewModelScope.launch { + getEmailAuthCodeUseCase( + email = state.email + ).onSuccess { + intent { + reduce { + state.copy( + emailAuthCode = it.authCode, + isSendEmailAuthCode = true, + enableEmailCertification = false + ) } } - } catch (e: Exception) { - Log.d("asdftt", e.toString()) + updateEmailCertificationButtonText() } } - fun postSocialVolunteerSignUp() { - val body = SocialVolunteerSignUpBody( - nickname = _nickname.value, - profileImageNum = _profileImageId.value!!, - name = _name.value, - phone = _phoneNumber.value - ) + private fun updateEmailCertificationButtonText() = + intent { reduce { state.copy(emailCertificationButtonText = "인증 확인") } } - viewModelScope.launch { - try { - signupRepository.postSocialVolunteerSignUp(body) - } catch (e: Exception) { - Log.d("tesqz", e.message.toString()) - } + /*비밀번호 등록*/ + fun onPasswordChanged(password: String) = intent { + reduce { state.copy(password = password) } + checkPasswordValidity() + enablePasswordRegisterButton() + } + + fun onConfirmPasswordChanged(password: String) = intent { + reduce { state.copy(confirmPassword = password) } + checkConfirmPasswordValidity() + enablePasswordRegisterButton() + } + + fun onPasswordRegisterNextButtonClick() = intent { + when (state.userType) { + UserType.INTERMEDIATOR -> Unit + else -> postSideEffect(SignUpSideEffect.NavigateToProfile) + } + } + + private fun enablePasswordRegisterButton() = intent { + reduce { state.copy(enablePasswordRegister = (state.isValidPassword == true && state.isValidConfirmPassword == true)) } + } + + private fun checkPasswordValidity() = intent { + reduce { + state.copy( + isValidPassword = state.englishAndNumberRegex.matches(state.password) + || state.englishNumberSpecialRegex.matches(state.password) + ) } } - fun postIntermediatorSignUp(context: Context) { - val body = IntermediatorSignUpBody( - email = _email.value, - password = _password.value, - realName = _name.value, - isOptionAgr = true, - intro = _intro.value, - url = _url.value, - contact = _contact.value, - phone = _phoneNumber.value, - name = _nickname.value - ) + private fun checkConfirmPasswordValidity() = intent { + reduce { state.copy(isValidConfirmPassword = state.password == state.confirmPassword) } + } + + /*닉네임*/ + fun onNickNameChanged(nickname: String) = intent { + if (nickname.length <= 12) reduce { state.copy(nickname = nickname) } + isAvailableNickname() + enableNicknameDuplicationButton() + } - val file = ImageConverter.uriToFile(context, _interProfileImage.value!!, 80) + private fun isAvailableNickname() { + intent { + reduce { state.copy(isAvailableNickName = !state.nicknameRegex.matches(state.nickname)) } + } + } - viewModelScope.launch { - try { - signupRepository.postIntermediatorSignUp(body, file!!) - } catch (e: Exception) { - Log.d("SignUpViewModel", e.message.toString()) + fun onCheckNicknameDuplicationButtonClick() = viewModelScope.launch { + getNicknameDuplicationUseCase(state.nickname).onSuccess { + intent { reduce { state.copy(isDuplicatedNickname = it.isDuplicated) } } + when (state.userType) { + UserType.NORMAL_VOLUNTEER -> initNormalVolunteerSignUp() + UserType.SOCIAL_VOLUNTEER -> initSocialVolunteerSignUp() + else -> Unit } } } - fun checkIsDuplicatePhoneNumber(userType: UserType, phoneNumber: String) = - viewModelScope.launch { - val body = IsDuplicatePhoneNumberBody(phone = phoneNumber) - when (userType) { - UserType.INTERMEDIATOR -> { - val response = signupRepository.getInterMediatorPhoneNumberDuplicated(body) - isDuplicatePhoneNumber.emit(response.isDuplicated) - } + fun updateProfileImageIndex(index: Int) = + intent { reduce { state.copy(profileImageId = index) } } - else -> { - val response = signupRepository.getVolunteerPhoneNumberDuplicated(body) - isDuplicatePhoneNumber.emit(response.isDuplicated) - } - } + private fun enableNicknameDuplicationButton() = intent { + if (state.nickname.length >= 2 && state.isAvailableNickName) reduce { + state.copy( + enableNicknameDuplication = true + ) + } + else reduce { state.copy(enableNicknameDuplication = false) } + } + + private fun getNameDuplication() = viewModelScope.launch { + getIntermediatorNameDuplicationUseCase(state.name).onSuccess { + + } + } + + private fun initNormalVolunteerSignUp() = viewModelScope.launch { + initNormalVolunteerSignUpUseCase( + email = state.email, + password = state.password, + nickname = state.nickname, + profileImageNum = state.profileImageId, + phone = state.phoneNumber, + name = state.name + ).onSuccess { + intent { postSideEffect(SignUpSideEffect.NavigateToSignUpComplete) } + }.onFailure { + Log.d("asdf", it.toString()) + } + } + + private fun initSocialVolunteerSignUp() = viewModelScope.launch { + initSocialVolunteerSignUpUseCase( + email = state.email, + password = state.password, + nickname = state.nickname, + profileImageNum = state.profileImageId, + phone = state.phoneNumber, + name = state.name + ).onSuccess { + setSocialVolunteerLogin() + }.onFailure { + + } + } + + fun initIntermediatorSignUp() = viewModelScope.launch { + + } + + fun onStartClick() = when (state.userType) { + UserType.NORMAL_VOLUNTEER -> setNormalVolunteerLogin() + UserType.SOCIAL_VOLUNTEER -> setSocialVolunteerLogin() + UserType.INTERMEDIATOR -> setSocialVolunteerLogin() + } + + private fun setNormalVolunteerLogin() = viewModelScope.launch { + volunteerLoginUseCase(state.email, state.password).onSuccess { + updateAccessTokenUseCase(it.accessToken) + updateRefreshTokenUseCase(it.refreshToken) + updateAppModeUseCase(AppMode.VOLUNTEER) + intent { postSideEffect(SignUpSideEffect.NavigateToSignUpComplete) } } + } + + private fun setSocialVolunteerLogin() = viewModelScope.launch { +// + } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/TermsViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/TermsViewModel.kt index 4636a83af..4b2fda225 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/TermsViewModel.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/TermsViewModel.kt @@ -1,64 +1,65 @@ package com.kusitms.connectdog.signup.viewmodel -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import com.kusitms.connectdog.signup.state.TermsSideEffect +import com.kusitms.connectdog.signup.state.TermsUiState import dagger.hilt.android.lifecycle.HiltViewModel +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container import javax.inject.Inject @HiltViewModel -class TermsViewModel @Inject constructor() : ViewModel() { - private val _allChecked = MutableLiveData(false) - val allChecked: LiveData = _allChecked +class TermsViewModel @Inject constructor() : ContainerHost, + ViewModel() { + override val container: Container = + container(TermsUiState.empty()) + private val state: TermsUiState + get() = container.stateFlow.value - private val _termsChecked = MutableLiveData(false) - val termsChecked: LiveData = _termsChecked - - private val _privacyChecked = MutableLiveData(false) - val privacyChecked: LiveData = _privacyChecked - - private val _advertisementChecked = MutableLiveData(false) - val advertisementChecked: LiveData = _advertisementChecked - - private val _isAvailableNext = MutableLiveData(false) - val isAvailableNext: LiveData - get() = _isAvailableNext - - fun updateAllChecked() { - _allChecked.value = !_allChecked.value!! - _termsChecked.value = !_allChecked.value!! - _privacyChecked.value = !_allChecked.value!! - _advertisementChecked.value = !_allChecked.value!! - } - - fun updateTermsChecked() { - _termsChecked.value = !_termsChecked.value!! - updateAllCheckedState() - isAvailableNext() + fun onAgreeAllClick() = intent { + reduce { + state.copy( + agreeAll = state.agreeAll.copy(isChecked = !state.agreeAll.isChecked), + termsOfService = state.termsOfService.copy(isChecked = !state.agreeAll.isChecked), + privacy = state.privacy.copy(isChecked = !state.agreeAll.isChecked), + advertisement = state.advertisement.copy(isChecked = !state.agreeAll.isChecked), + ) + } + enableNext() } - fun updatePrivacyChecked() { - _privacyChecked.value = !_privacyChecked.value!! - updateAllCheckedState() - isAvailableNext() + fun onTermsOfServiceClick() = intent { + reduce { state.copy(termsOfService = state.termsOfService.copy(isChecked = !state.termsOfService.isChecked)) } + updateAllAgree() + enableNext() } - fun updateAdvertisementChecked() { - _advertisementChecked.value = !_advertisementChecked.value!! - updateAllCheckedState() + fun onPrivacyClick() = intent { + reduce { state.copy(privacy = state.privacy.copy(isChecked = !state.privacy.isChecked)) } + updateAllAgree() + enableNext() } - private fun updateAllCheckedState() { - _allChecked.value = _termsChecked.value == true && _privacyChecked.value == true && _advertisementChecked.value == true + fun onAdvertisementClick() = intent { + reduce { state.copy(advertisement = state.advertisement.copy(isChecked = !state.advertisement.isChecked)) } + updateAllAgree() + enableNext() } - private fun isAvailableNext() { - _isAvailableNext.value = _termsChecked.value == true && _privacyChecked.value == true + private fun updateAllAgree() = intent { + reduce { + state.copy( + agreeAll = state.agreeAll.copy( + isChecked = state.termsOfService.isChecked && state.privacy.isChecked && state.advertisement.isChecked + ) + ) + } } - fun resetState() { - _allChecked.value = false - _privacyChecked.value = false - _termsChecked.value = false + private fun enableNext() = intent { + reduce { state.copy(enableNext = state.termsOfService.isChecked && state.privacy.isChecked) } } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/VolunteerProfileViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/VolunteerProfileViewModel.kt deleted file mode 100644 index 0e9ea6fe0..000000000 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/VolunteerProfileViewModel.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.kusitms.connectdog.signup.viewmodel - -import android.util.Log -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody -import com.kusitms.connectdog.core.data.repository.SignUpRepository -import com.kusitms.connectdog.core.util.getProfileImageId -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import javax.inject.Inject - -private const val TAG = "VolunteerProfileViewModel" - -@HiltViewModel -class VolunteerProfileViewModel @Inject constructor( - private val signupRepository: SignUpRepository -) : ViewModel() { - private val _selectedImageIndex = MutableStateFlow(-1) - val selectedImageIndex: StateFlow - get() = _selectedImageIndex - - private val _isDuplicatedNickname: MutableStateFlow = MutableStateFlow(null) - val isDuplicatedNickname: StateFlow - get() = _isDuplicatedNickname - - private val _isAvailableNickname: MutableStateFlow = MutableStateFlow(null) - val isAvailableNickname: StateFlow - get() = _isAvailableNickname - - private val _nickname: MutableState = mutableStateOf("") - val nickname: String - get() = _nickname.value - - fun isAvailableNickname() { - val regex = Regex("[가-힣0-9]+") - _isAvailableNickname.value = !regex.matches(_nickname.value) - Log.d("taswa", _isAvailableNickname.value.toString()) - } - - fun updateNicknameAvailability(nickname: String) { - val nicknameBody = IsDuplicateNicknameBody(nickname = nickname) - viewModelScope.launch { - try { - val response = signupRepository.postNickname(nicknameBody) - Log.d(TAG, response.toString()) - _isDuplicatedNickname.value = !response.isDuplicated - } catch (e: Exception) { - Log.d(TAG, e.message.toString()) - } - } - } - - fun updateProfileImageIndex(imageIndex: Int) { - _selectedImageIndex.value = imageIndex - } - - fun updateNickname(nickname: String) { - _nickname.value = nickname - } - - fun getProfileImageId(): Int { - return if (_selectedImageIndex.value == -1) { - com.kusitms.connectdog.core.designsystem.R.drawable.ic_circle - } else { - getProfileImageId(_selectedImageIndex.value) - } - } -} diff --git a/feature/signup/src/main/res/values/string.xml b/feature/signup/src/main/res/values/string.xml index 46fba4197..bea7f24b7 100644 --- a/feature/signup/src/main/res/values/string.xml +++ b/feature/signup/src/main/res/values/string.xml @@ -3,12 +3,40 @@ 이동봉사자 회원가입 이동봉사 모집자 회원가입 + + 다음 + + 이름 + 이름 입력 휴대폰 번호 인증을\n진행해 주세요 휴대폰 번호 + \'-\'빼고 입력 + 인증번호 + 숫자 6자리 + 인증번호 입력 + 인증번호가 일치하지 않습니다. + 인증번호가 오지 않는다면? + 재발송 + 한 줄 소개 한 줄 소개 입력 모집자명 모집자명 입력 + + + 이메일 + 이메일 입력 + 로그인에 사용할\n이메일 입력해주라 + + + 로그인에 사용할\n비밀번호를 입력해주세요 + 비밀번호 + 비밀번호 입력 + 비밀번호 확인 + 영문+숫자 10자 이상 또는 영문+숫자+특수기호 8자 이상 + + 프로필 이미지를\n선택해주세요 + 선택 \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 3c5031eb7..6920c05bd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,4 +20,5 @@ kotlin.code.style=official # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file +android.nonTransitiveRClass=true +android.defaults.buildfeatures.buildconfig=true \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ec44bbd4a..c54693be7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,6 +15,8 @@ androidxComposeMaterial = "1.5.4" androidxComposeFoundation = "1.5.4" androidxSplash = "1.0.0-beta02" androidxDataStore = "1.0.0" +kotlinxCoroutines = "1.7.2" + hilt = "2.46.1" hiltNavigationCompose = "1.0.0" accompanistPager = "0.20.1" @@ -63,6 +65,7 @@ androidx-lifecycle-viewModelKtx = { group = "androidx.lifecycle", name = "lifecy androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "androidxActivity" } androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "androidxSplash" } androidx-datastore = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "androidxDataStore" } +kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" } androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" } androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 69dbdd5b0..6312a2ea2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,16 +17,21 @@ dependencyResolutionManagement { } rootProject.name = "ConnectDog" +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + include(":app") + +include(":domain") + include(":core:data") include(":core:model") include(":core:designsystem") +include(":core:util") + +include(":feature:intermediator") +include(":feature:signup") include(":feature:main") include(":feature:home") include(":feature:login") include(":feature:management") include(":feature:mypage") -include(":core:util") -include(":feature:intermediator") -include(":feature:signup") -include(":domain")