diff --git a/app/src/main/java/com/terning/point/di/DataSourceModule.kt b/app/src/main/java/com/terning/point/di/DataSourceModule.kt index 1c395b630..6869e4768 100644 --- a/app/src/main/java/com/terning/point/di/DataSourceModule.kt +++ b/app/src/main/java/com/terning/point/di/DataSourceModule.kt @@ -1,11 +1,11 @@ package com.terning.point.di -import com.terning.data.datasource.MockDataSource -import com.terning.data.datasource.ScrapDataSource -import com.terning.data.datasourceimpl.MockDataSourceImpl -import com.terning.data.datasourceimpl.ScrapDataSourceImpl -import com.terning.data.repositoryimpl.ScrapRepositoryImpl -import com.terning.domain.repository.ScrapRepository +import com.terning.data.datasource.AuthDataSource +import com.terning.data.datasource.SearchDataSource +import com.terning.data.datasourceimpl.AuthDataSourceImpl +import com.terning.data.datasourceimpl.SearchDataSourceImpl +import com.terning.data.datasource.CalendarDataSource +import com.terning.data.datasourceimpl.CalendarDataSourceImpl import dagger.Binds import dagger.Module import dagger.hilt.InstallIn @@ -18,9 +18,14 @@ abstract class DataSourceModule { @Binds @Singleton - abstract fun bindScrapRepository(scrapDataSourceImpl: ScrapDataSourceImpl): ScrapDataSource + abstract fun bindCalendarRepository(calendarDataSourceImpl: CalendarDataSourceImpl): CalendarDataSource @Binds @Singleton - abstract fun bindMockDataSource(mockDataSourceImpl: MockDataSourceImpl): MockDataSource + abstract fun bindAuthDataSource(authDataSourceImpl: AuthDataSourceImpl): AuthDataSource + + @Binds + @Singleton + abstract fun bindSearchViewsDataSource(searchViewsDataSourceImpl: SearchDataSourceImpl): + SearchDataSource } \ No newline at end of file diff --git a/app/src/main/java/com/terning/point/di/DataStoreModule.kt b/app/src/main/java/com/terning/point/di/DataStoreModule.kt new file mode 100644 index 000000000..ca4b09d65 --- /dev/null +++ b/app/src/main/java/com/terning/point/di/DataStoreModule.kt @@ -0,0 +1,27 @@ +package com.terning.point.di + +import android.content.Context +import android.content.SharedPreferences +import com.terning.data.local.TerningDataStore +import com.terning.data.local.TerningDataStoreImpl +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 + +@Module +@InstallIn(SingletonComponent::class) +object DataStoreModule { + + @Provides + @Singleton + fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences = + context.getSharedPreferences(context.packageName, Context.MODE_PRIVATE) + + @Provides + @Singleton + fun provideTerningDataStore(dataStoreImpl: TerningDataStoreImpl): TerningDataStore = + dataStoreImpl +} \ No newline at end of file diff --git a/app/src/main/java/com/terning/point/di/RepositoryModule.kt b/app/src/main/java/com/terning/point/di/RepositoryModule.kt index 9aa69d3a6..bf31bd876 100644 --- a/app/src/main/java/com/terning/point/di/RepositoryModule.kt +++ b/app/src/main/java/com/terning/point/di/RepositoryModule.kt @@ -1,9 +1,13 @@ package com.terning.point.di -import com.terning.data.repositoryimpl.MockRepositoryImpl -import com.terning.data.repositoryimpl.ScrapRepositoryImpl -import com.terning.domain.repository.MockRepository -import com.terning.domain.repository.ScrapRepository +import com.terning.data.repositoryimpl.AuthRepositoryImpl +import com.terning.data.repositoryimpl.CalendarRepositoryImpl +import com.terning.data.repositoryimpl.SearchViewsRepositoryImpl +import com.terning.data.repositoryimpl.TokenRepositoryImpl +import com.terning.domain.repository.AuthRepository +import com.terning.domain.repository.CalendarRepository +import com.terning.domain.repository.SearchRepository +import com.terning.domain.repository.TokenRepository import dagger.Binds import dagger.Module import dagger.hilt.InstallIn @@ -16,9 +20,17 @@ abstract class RepositoryModule { @Binds @Singleton - abstract fun scrapRepository(scrapRepositoryImpl: ScrapRepositoryImpl): ScrapRepository + abstract fun calendarRepository(calendarRepositoryImpl: CalendarRepositoryImpl): CalendarRepository @Binds @Singleton - abstract fun bindMockRepository(mockRepositoryImpl: MockRepositoryImpl): MockRepository + abstract fun bindAuthRepository(authRepositoryImpl: AuthRepositoryImpl): AuthRepository + + @Binds + @Singleton + abstract fun bindTokenRepository(tokenRepositoryImpl: TokenRepositoryImpl): TokenRepository + + @Binds + @Singleton + abstract fun bindSearchViewsRepository(searchViewsRepositoryImpl: SearchViewsRepositoryImpl): SearchRepository } \ No newline at end of file diff --git a/app/src/main/java/com/terning/point/di/RetrofitModule.kt b/app/src/main/java/com/terning/point/di/RetrofitModule.kt index 961fa891b..c5840f081 100644 --- a/app/src/main/java/com/terning/point/di/RetrofitModule.kt +++ b/app/src/main/java/com/terning/point/di/RetrofitModule.kt @@ -2,8 +2,8 @@ package com.terning.point.di import com.terning.core.extension.isJsonArray import com.terning.core.extension.isJsonObject -import com.terning.point.BuildConfig -import com.terning.point.di.qualifier.OPEN +import com.terning.point.BuildConfig.BASE_URL +import com.terning.point.di.qualifier.JWT import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -65,12 +65,12 @@ object RetrofitModule { @Provides @Singleton - @OPEN - fun provideOpenRetrofit( + @JWT + fun provideJWTRetrofit( client: OkHttpClient, factory: Converter.Factory ): Retrofit = Retrofit.Builder() - .baseUrl(BuildConfig.BASE_URL) + .baseUrl(BASE_URL) .addConverterFactory(factory) .client(client) .build() diff --git a/app/src/main/java/com/terning/point/di/ServiceModule.kt b/app/src/main/java/com/terning/point/di/ServiceModule.kt index 317c02f92..fcb0ced95 100644 --- a/app/src/main/java/com/terning/point/di/ServiceModule.kt +++ b/app/src/main/java/com/terning/point/di/ServiceModule.kt @@ -1,7 +1,9 @@ package com.terning.point.di -import com.terning.data.service.MockService -import com.terning.point.di.qualifier.OPEN +import com.terning.data.service.AuthService +import com.terning.data.service.CalendarService +import com.terning.data.service.SearchService +import com.terning.point.di.qualifier.JWT import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -15,7 +17,17 @@ object ServiceModule { @Provides @Singleton - fun provideMockService(@OPEN retrofit: Retrofit): MockService = - retrofit.create(MockService::class.java) + fun provideAuthService(@JWT retrofit: Retrofit): AuthService = + retrofit.create(AuthService::class.java) + + @Provides + @Singleton + fun provideSearchService(@JWT retrofit: Retrofit): SearchService = + retrofit.create(SearchService::class.java) + + @Provides + @Singleton + fun provideCalendarService(@JWT retrofit: Retrofit): CalendarService = + retrofit.create(CalendarService::class.java) } \ No newline at end of file diff --git a/app/src/main/java/com/terning/point/di/qualifier/RetrofitQualifier.kt b/app/src/main/java/com/terning/point/di/qualifier/RetrofitQualifier.kt index fe7176d0b..11956ab89 100644 --- a/app/src/main/java/com/terning/point/di/qualifier/RetrofitQualifier.kt +++ b/app/src/main/java/com/terning/point/di/qualifier/RetrofitQualifier.kt @@ -5,4 +5,4 @@ import javax.inject.Qualifier @Qualifier @Retention(AnnotationRetention.BINARY) -annotation class OPEN \ No newline at end of file +annotation class JWT \ No newline at end of file diff --git a/core/src/main/java/com/terning/core/designsystem/component/textfield/TerningBasicTextField.kt b/core/src/main/java/com/terning/core/designsystem/component/textfield/TerningBasicTextField.kt index 5fcea5394..d30599864 100644 --- a/core/src/main/java/com/terning/core/designsystem/component/textfield/TerningBasicTextField.kt +++ b/core/src/main/java/com/terning/core/designsystem/component/textfield/TerningBasicTextField.kt @@ -68,9 +68,13 @@ fun TerningBasicTextField( keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), keyboardActions = KeyboardActions( onDone = { - keyboardController?.hide() - focusManager.clearFocus() - onDoneAction?.invoke() + if (value.isNotBlank()) { + keyboardController?.hide() + focusManager.clearFocus() + if (onDoneAction != null) { + onDoneAction() + } + } } ), diff --git a/core/src/main/java/com/terning/core/extension/LocalDateExt.kt b/core/src/main/java/com/terning/core/extension/LocalDateExt.kt index 702ea1182..1f8d4355f 100644 --- a/core/src/main/java/com/terning/core/extension/LocalDateExt.kt +++ b/core/src/main/java/com/terning/core/extension/LocalDateExt.kt @@ -1,6 +1,7 @@ package com.terning.core.extension import java.time.LocalDate +import java.time.format.DateTimeFormatter import java.time.format.TextStyle import java.util.Locale @@ -10,6 +11,11 @@ fun LocalDate.getStringAsTitle(): String = fun LocalDate.getDateStringInKorean(): String = "${monthValue}월 ${dayOfMonth}일 ${dayOfWeek.getDisplayName(TextStyle.FULL, Locale.KOREAN)}" +fun LocalDate.getDateAsMapString(): String { + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") + return format(formatter) +} + fun LocalDate.getWeekIndexContainingSelectedDate(inDays: Int): Int = (inDays + dayOfMonth - 1) / 7 fun LocalDate.isToday(): Boolean = this == LocalDate.now() \ No newline at end of file diff --git a/core/src/main/java/com/terning/core/extension/Map.kt b/core/src/main/java/com/terning/core/extension/Map.kt new file mode 100644 index 000000000..fab779e23 --- /dev/null +++ b/core/src/main/java/com/terning/core/extension/Map.kt @@ -0,0 +1,3 @@ +package com.terning.core.extension + +fun List?.isListNotEmpty():Boolean = this.orEmpty().isNotEmpty() diff --git a/data/src/main/java/com/terning/data/datasource/AuthDataSource.kt b/data/src/main/java/com/terning/data/datasource/AuthDataSource.kt new file mode 100644 index 000000000..362d71b23 --- /dev/null +++ b/data/src/main/java/com/terning/data/datasource/AuthDataSource.kt @@ -0,0 +1,12 @@ +package com.terning.data.datasource + +import com.terning.data.dto.BaseResponse +import com.terning.data.dto.request.SignInRequestDto +import com.terning.data.dto.response.SignInResponseDto + +interface AuthDataSource { + suspend fun postSignIn( + authorization: String, + platform: SignInRequestDto + ): BaseResponse +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/datasource/CalendarDataSource.kt b/data/src/main/java/com/terning/data/datasource/CalendarDataSource.kt new file mode 100644 index 000000000..609019fa8 --- /dev/null +++ b/data/src/main/java/com/terning/data/datasource/CalendarDataSource.kt @@ -0,0 +1,15 @@ +package com.terning.data.datasource + +import com.terning.data.dto.BaseResponse +import com.terning.data.dto.request.CalendarDayListRequestDto +import com.terning.data.dto.request.CalendarMonthListRequestDto +import com.terning.data.dto.request.CalendarMonthRequestDto +import com.terning.data.dto.response.CalendarDayListResponseDto +import com.terning.data.dto.response.CalendarMonthListResponseDto +import com.terning.data.dto.response.CalendarMonthResponseDto + +interface CalendarDataSource { + suspend fun getCalendarMonth(request: CalendarMonthRequestDto): BaseResponse> + suspend fun getCalendarMonthList(request: CalendarMonthListRequestDto): BaseResponse> + suspend fun getCalendarDayList(request: CalendarDayListRequestDto): BaseResponse> +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/datasource/MockDataSource.kt b/data/src/main/java/com/terning/data/datasource/MockDataSource.kt deleted file mode 100644 index 468b21bca..000000000 --- a/data/src/main/java/com/terning/data/datasource/MockDataSource.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.terning.data.datasource - -import com.terning.data.dto.response.MockResponseDto - -interface MockDataSource { - suspend fun getMock(page: Int): MockResponseDto -} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/datasource/ScrapDataSource.kt b/data/src/main/java/com/terning/data/datasource/ScrapDataSource.kt deleted file mode 100644 index 97e893cda..000000000 --- a/data/src/main/java/com/terning/data/datasource/ScrapDataSource.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.terning.data.datasource - -import com.terning.data.dto.BaseResponse -import com.terning.data.dto.request.ScrapRequestDto -import com.terning.data.dto.response.ScrapResponseDto - -interface ScrapDataSource { - suspend fun getScrapMonth(request: ScrapRequestDto): BaseResponse> -} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/datasource/SearchDataSource.kt b/data/src/main/java/com/terning/data/datasource/SearchDataSource.kt new file mode 100644 index 000000000..cc15b29b6 --- /dev/null +++ b/data/src/main/java/com/terning/data/datasource/SearchDataSource.kt @@ -0,0 +1,8 @@ +package com.terning.data.datasource + +import com.terning.data.dto.BaseResponse +import com.terning.data.dto.response.SearchViewsResponseDto + +interface SearchDataSource { + suspend fun getSearchViews(): BaseResponse +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/datasourceimpl/AuthDataSourceImpl.kt b/data/src/main/java/com/terning/data/datasourceimpl/AuthDataSourceImpl.kt new file mode 100644 index 000000000..cbb8ca54f --- /dev/null +++ b/data/src/main/java/com/terning/data/datasourceimpl/AuthDataSourceImpl.kt @@ -0,0 +1,17 @@ +package com.terning.data.datasourceimpl + +import com.terning.data.datasource.AuthDataSource +import com.terning.data.dto.BaseResponse +import com.terning.data.dto.request.SignInRequestDto +import com.terning.data.dto.response.SignInResponseDto +import com.terning.data.service.AuthService +import javax.inject.Inject + +class AuthDataSourceImpl @Inject constructor( + private val authService: AuthService +) : AuthDataSource { + override suspend fun postSignIn( + authorization: String, + platform: SignInRequestDto + ): BaseResponse = authService.postSignIn(authorization, platform) +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/datasourceimpl/CalendarDataSourceImpl.kt b/data/src/main/java/com/terning/data/datasourceimpl/CalendarDataSourceImpl.kt new file mode 100644 index 000000000..eddcecef0 --- /dev/null +++ b/data/src/main/java/com/terning/data/datasourceimpl/CalendarDataSourceImpl.kt @@ -0,0 +1,25 @@ +package com.terning.data.datasourceimpl + +import com.terning.data.datasource.CalendarDataSource +import com.terning.data.dto.BaseResponse +import com.terning.data.dto.request.CalendarDayListRequestDto +import com.terning.data.dto.request.CalendarMonthListRequestDto +import com.terning.data.dto.request.CalendarMonthRequestDto +import com.terning.data.dto.response.CalendarDayListResponseDto +import com.terning.data.dto.response.CalendarMonthListResponseDto +import com.terning.data.dto.response.CalendarMonthResponseDto +import com.terning.data.service.CalendarService +import javax.inject.Inject + +class CalendarDataSourceImpl @Inject constructor( + private val calendarService: CalendarService +) : CalendarDataSource { + override suspend fun getCalendarMonth(request: CalendarMonthRequestDto): BaseResponse> = + CalendarList.getCalendarScrapMonth(request) + + override suspend fun getCalendarMonthList(request: CalendarMonthListRequestDto): BaseResponse> = + CalendarList.getCalendarScrapMonthList(request) + + override suspend fun getCalendarDayList(request: CalendarDayListRequestDto): BaseResponse> = + CalendarList.getCalendarScrapDayList(request) +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/datasourceimpl/CalendarList.kt b/data/src/main/java/com/terning/data/datasourceimpl/CalendarList.kt new file mode 100644 index 000000000..74b1ff8e0 --- /dev/null +++ b/data/src/main/java/com/terning/data/datasourceimpl/CalendarList.kt @@ -0,0 +1,846 @@ +package com.terning.data.datasourceimpl + +import com.terning.data.dto.BaseResponse +import com.terning.data.dto.request.CalendarDayListRequestDto +import com.terning.data.dto.request.CalendarMonthListRequestDto +import com.terning.data.dto.request.CalendarMonthRequestDto +import com.terning.data.dto.response.CalendarDayListResponseDto +import com.terning.data.dto.response.CalendarMonthListResponseDto +import com.terning.data.dto.response.CalendarMonthResponseDto + +object CalendarList { + fun getCalendarScrapMonth(request: CalendarMonthRequestDto): BaseResponse> = + BaseResponse( + status = 200, + message = "캘린더 > (월간) 스크랩 된 공고 정보 불러오기를 성공했습니다", + result = getMockScrapList(request.year, request.month) + ) + + fun getCalendarScrapMonthList(request: CalendarMonthListRequestDto): BaseResponse> = + BaseResponse( + status = 200, + message = "캘린더 > (월간) 스크랩 된 공고 정보 불러오기를 성공했습니다", + result = getMockScrapDetailList(request.year, request.month) + ) + + fun getCalendarScrapDayList(requestDto: CalendarDayListRequestDto): BaseResponse> = + BaseResponse( + status = 200, + message = "캘린더 > (일간) 스크랩 된 공고 정보 불러오기를 성공했습니다", + result = getMockDayList(requestDto.date) + ) + + + + fun getMockScrapList(year: Int, month: Int): List { + val deadline = month.toString().padStart(2, '0') + return when (month % 4) { + 0 -> { + listOf( + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-13", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FFED4E54" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 2, + title = "제목2", + color = "#FFC4E953" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 3, + title = "제목3", + color = "#FF9B64E2" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 4, + title = "제목4", + color = "#FFF260AC" + ) + ) + ), + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-17", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FFC4E953" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 2, + title = "제목2", + color = "#FF45D0CC" + ), + ) + ), + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-23", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FF5397F3" + ) + ) + ), + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-30", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FF45D0CC" + ) + ) + ) + ) + } + + 1 -> { + listOf( + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-01", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FFED4E54" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 2, + title = "제목2", + color = "#FFC4E953" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 3, + title = "제목3", + color = "#FF9B64E2" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 4, + title = "제목4", + color = "#FFF260AC" + ) + ) + ), + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-02", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FFC4E953" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 2, + title = "제목2", + color = "#FF9B64E2" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 3, + title = "제목3", + color = "#FFED4E54" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 4, + title = "제목4", + color = "#FFF260AC" + ) + ) + ), + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-12", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FFC4E953" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 2, + title = "제목2", + color = "#FF45D0CC" + ), + ) + ), + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-27", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FF5397F3" + ) + ) + ), + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-29", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FF45D0CC" + ) + ) + ) + ) + } + + 2 -> { + listOf( + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-02", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FFED4E54" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 2, + title = "제목2", + color = "#FFC4E953" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 3, + title = "제목3", + color = "#FF9B64E2" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 4, + title = "제목4", + color = "#FFF260AC" + ) + ) + ), + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-18", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FFC4E953" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 2, + title = "제목2", + color = "#FF45D0CC" + ), + ) + ), + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-20", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FF5397F3" + ) + ) + ), + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-29", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FF45D0CC" + ) + ) + ) + ) + } + + 3 -> { + listOf( + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-05", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FFED4E54" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 2, + title = "제목2", + color = "#FFC4E953" + )/*, + ScrapResponsesDto.Scrap( + scrapId = 3, + title = "제목3", + color = "#FF9B64E2" + ), + ScrapResponsesDto.Scrap( + scrapId = 4, + title = "제목4", + color = "#FFF260AC" + )*/ + ) + ), + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-11", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FFC4E953" + ), + CalendarMonthResponseDto.Scrap( + scrapId = 2, + title = "제목2", + color = "#FF45D0CC" + ), + ) + ), + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-19", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FF5397F3" + ) + ) + ), + CalendarMonthResponseDto( + deadline = "${year}-${deadline}-28", + scraps = listOf( + CalendarMonthResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FF45D0CC" + ) + ) + ) + ) + } + + else -> { + listOf() + } + } + } +} + + +/*************************MockDataType***************************/ + +fun getMockScrapDetailList(year: Int, month: Int): List { + val deadline = month.toString().padStart(2, '0') + return when (month % 5) { + 0 -> { + listOf( + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-13", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 1, + title = "제목1", + color = "#FFED4E54", + internshipAnnouncementId = 1, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 2, + title = "제목2", + color = "#FFC4E953", + internshipAnnouncementId = 2, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 3, + title = "제목3", + color = "#FF9B64E2", + internshipAnnouncementId = 3, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 4, + title = "제목4", + color = "#FFF260AC", + internshipAnnouncementId = 3, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) + ) + ), + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-17", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 5, + title = "제목5", + color = "#FFC4E953", + internshipAnnouncementId = 5, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 6, + title = "제목6", + color = "#FF45D0CC", + internshipAnnouncementId = 6, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + ) + ), + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-23", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 7, + title = "제목7", + color = "#FF5397F3", + internshipAnnouncementId = 7, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) + ) + ), + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-30", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 8, + title = "제목8", + color = "#FF45D0CC", + internshipAnnouncementId = 8, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) + ) + ) + ) + } + + 1 -> { + listOf( + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-01", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 9, + title = "제목9", + color = "#FFED4E54", + internshipAnnouncementId = 9, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 10, + title = "제목10", + color = "#FFC4E953", + internshipAnnouncementId = 10, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 11, + title = "제목11", + color = "#FF9B64E2", + internshipAnnouncementId = 11, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 12, + title = "제목12", + color = "#FFF260AC", + internshipAnnouncementId = 12, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) + ) + ), + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-02", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 13, + title = "제목13", + color = "#FFC4E953", + internshipAnnouncementId = 13, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 14, + title = "제목14", + color = "#FF9B64E2", + internshipAnnouncementId = 14, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 15, + title = "제목15", + color = "#FFED4E54", + internshipAnnouncementId = 15, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 16, + title = "제목16", + color = "#FFF260AC", + internshipAnnouncementId = 16, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) + ) + ), + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-12", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 17, + title = "제목17", + color = "#FFC4E953", + internshipAnnouncementId = 17, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 18, + title = "제목18", + color = "#FF45D0CC", + internshipAnnouncementId = 18, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + ) + ), + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-27", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 19, + title = "제목19", + color = "#FF5397F3", + internshipAnnouncementId = 19, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) + ) + ), + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-29", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 20, + title = "제목20", + color = "#FF45D0CC", + internshipAnnouncementId = 20, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) + ) + ) + ) + } + + 2 -> { + listOf( + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-02", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 21, + title = "제목1", + color = "#FFED4E54", + internshipAnnouncementId = 21, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 22, + title = "제목22", + color = "#FFC4E953", + internshipAnnouncementId = 22, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 23, + title = "제목23", + color = "#FF9B64E2", + internshipAnnouncementId = 23, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 24, + title = "제목24", + color = "#FFF260AC", + internshipAnnouncementId = 24, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) + ) + ), + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-18", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 25, + title = "제목25", + color = "#FFC4E953", + internshipAnnouncementId =25, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 26, + title = "제목26", + color = "#FF45D0CC", + internshipAnnouncementId = 26, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + ) + ), + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-20", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 27, + title = "제목27", + color = "#FF5397F3", + internshipAnnouncementId = 27, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) + ) + ), + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-29", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 28, + title = "제목28", + color = "#FF45D0CC", + internshipAnnouncementId = 28, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) + ) + ) + ) + } + + 3 -> { + listOf( + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-05", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 29, + title = "제목29", + color = "#FFED4E54", + internshipAnnouncementId = 29, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 30, + title = "제목30", + color = "#FFC4E953", + internshipAnnouncementId = 30, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) + ) + ), + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-11", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 31, + title = "제목31", + color = "#FFC4E953", + internshipAnnouncementId = 31, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarMonthListResponseDto.Scrap( + scrapId = 32, + title = "제목32", + color = "#FF45D0CC", + internshipAnnouncementId = 32, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + ) + ), + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-19", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 33, + title = "제목33", + color = "#FF5397F3", + internshipAnnouncementId = 33, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) + ) + ), + CalendarMonthListResponseDto( + deadline = "${year}-${deadline}-28", + scraps = listOf( + CalendarMonthListResponseDto.Scrap( + scrapId = 34, + title = "제목34", + color = "#FF45D0CC", + internshipAnnouncementId = 34, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) + ) + ) + ) + } + + else -> { + listOf() + } + } +} + +/******************DayList******************/ + +fun getMockDayList(request: String): List = listOf( + CalendarDayListResponseDto( + scrapId = 34, + title = "제목34", + color = "#FF45D0CC", + internshipAnnouncementId = 34, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ), + CalendarDayListResponseDto( + scrapId = 34, + title = "제목34", + color = "#FF45D0CC", + internshipAnnouncementId = 34, + dDay = "10", + workingPeriod = "10", + companyImage = "", + startYear = 2024, + startMonth = 8 + ) +) diff --git a/data/src/main/java/com/terning/data/datasourceimpl/MockDataSourceImpl.kt b/data/src/main/java/com/terning/data/datasourceimpl/MockDataSourceImpl.kt deleted file mode 100644 index 12aa9731f..000000000 --- a/data/src/main/java/com/terning/data/datasourceimpl/MockDataSourceImpl.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.terning.data.datasourceimpl - -import com.terning.data.datasource.MockDataSource -import com.terning.data.dto.response.MockResponseDto -import com.terning.data.service.MockService -import javax.inject.Inject - -class MockDataSourceImpl @Inject constructor( - private val mockService: MockService -) : MockDataSource { - override suspend fun getMock(page: Int): MockResponseDto = - mockService.getMockListFromServer(page) -} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/datasourceimpl/ScrapDataSourceImpl.kt b/data/src/main/java/com/terning/data/datasourceimpl/ScrapDataSourceImpl.kt deleted file mode 100644 index 5b4afdf5e..000000000 --- a/data/src/main/java/com/terning/data/datasourceimpl/ScrapDataSourceImpl.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.terning.data.datasourceimpl - -import com.terning.data.datasource.ScrapDataSource -import com.terning.data.dto.BaseResponse -import com.terning.data.dto.request.ScrapRequestDto -import com.terning.data.dto.response.ScrapResponseDto -import com.terning.data.dto.response.getMockScrapList -import javax.inject.Inject - -class ScrapDataSourceImpl @Inject constructor( - -) : ScrapDataSource { - override suspend fun getScrapMonth(request: ScrapRequestDto): BaseResponse> = - BaseResponse( - status = 200, - message = "(월간) 스크랩된 공고 정보가 성공적으로 로드되었습니다.", - result = getMockScrapList(request.year, request.month) - ) - -} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/datasourceimpl/SearchDataSourceImpl.kt b/data/src/main/java/com/terning/data/datasourceimpl/SearchDataSourceImpl.kt new file mode 100644 index 000000000..7a5872e56 --- /dev/null +++ b/data/src/main/java/com/terning/data/datasourceimpl/SearchDataSourceImpl.kt @@ -0,0 +1,14 @@ +package com.terning.data.datasourceimpl + +import com.terning.data.datasource.SearchDataSource +import com.terning.data.dto.BaseResponse +import com.terning.data.dto.response.SearchViewsResponseDto +import com.terning.data.service.SearchService +import javax.inject.Inject + +class SearchDataSourceImpl @Inject constructor( + private val searchService: SearchService, +) : SearchDataSource { + override suspend fun getSearchViews(): BaseResponse = + searchService.getSearchViewsList() +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/dto/NonDataBaseResponse.kt b/data/src/main/java/com/terning/data/dto/NonDataBaseResponse.kt index 34db1f722..ddc6d1a70 100644 --- a/data/src/main/java/com/terning/data/dto/NonDataBaseResponse.kt +++ b/data/src/main/java/com/terning/data/dto/NonDataBaseResponse.kt @@ -7,8 +7,6 @@ import kotlinx.serialization.Serializable data class NonDataBaseResponse( @SerialName("status") val status: Int, - @SerialName("code") - val code: String, @SerialName("message") val message: String, ) diff --git a/data/src/main/java/com/terning/data/dto/request/CalendarDayListRequestDto.kt b/data/src/main/java/com/terning/data/dto/request/CalendarDayListRequestDto.kt new file mode 100644 index 000000000..857b75029 --- /dev/null +++ b/data/src/main/java/com/terning/data/dto/request/CalendarDayListRequestDto.kt @@ -0,0 +1,5 @@ +package com.terning.data.dto.request + +data class CalendarDayListRequestDto( + val date: String +) \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/dto/request/CalendarMonthListRequestDto.kt b/data/src/main/java/com/terning/data/dto/request/CalendarMonthListRequestDto.kt new file mode 100644 index 000000000..6a951d73d --- /dev/null +++ b/data/src/main/java/com/terning/data/dto/request/CalendarMonthListRequestDto.kt @@ -0,0 +1,13 @@ +package com.terning.data.dto.request + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class CalendarMonthListRequestDto( + @SerialName("deadline") + val year: Int, + @SerialName("scraps") + val month: Int +) + diff --git a/data/src/main/java/com/terning/data/dto/request/ScrapRequestDto.kt b/data/src/main/java/com/terning/data/dto/request/CalendarMonthRequestDto.kt similarity index 86% rename from data/src/main/java/com/terning/data/dto/request/ScrapRequestDto.kt rename to data/src/main/java/com/terning/data/dto/request/CalendarMonthRequestDto.kt index f93df1059..00eaf4696 100644 --- a/data/src/main/java/com/terning/data/dto/request/ScrapRequestDto.kt +++ b/data/src/main/java/com/terning/data/dto/request/CalendarMonthRequestDto.kt @@ -4,7 +4,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable -data class ScrapRequestDto( +data class CalendarMonthRequestDto( @SerialName("year") val year: Int, @SerialName("month") diff --git a/data/src/main/java/com/terning/data/dto/request/SignInRequestDto.kt b/data/src/main/java/com/terning/data/dto/request/SignInRequestDto.kt new file mode 100644 index 000000000..f87431913 --- /dev/null +++ b/data/src/main/java/com/terning/data/dto/request/SignInRequestDto.kt @@ -0,0 +1,14 @@ +package com.terning.data.dto.request + +import com.terning.domain.entity.request.SignInRequestModel +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class SignInRequestDto( + @SerialName("authType") + val authType: String +) + +fun SignInRequestModel.toSignInRequestDto(): SignInRequestDto = + SignInRequestDto(authType = authType) \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/dto/response/CalendarDayListResponseDto.kt b/data/src/main/java/com/terning/data/dto/response/CalendarDayListResponseDto.kt new file mode 100644 index 000000000..e2d23afb1 --- /dev/null +++ b/data/src/main/java/com/terning/data/dto/response/CalendarDayListResponseDto.kt @@ -0,0 +1,42 @@ +package com.terning.data.dto.response + +import com.terning.domain.entity.response.CalendarScrapDetailModel +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class CalendarDayListResponseDto( + @SerialName("scrapId") + val scrapId: Long, + @SerialName("internshipAnnouncementId") + val internshipAnnouncementId: Long, + @SerialName("title") + val title: String, + @SerialName("dDay") + val dDay: String, + @SerialName("workingPeriod") + val workingPeriod: String, + @SerialName("color") + val color: String, + @SerialName("companyImage") + val companyImage: String, + @SerialName("startYear") + val startYear: Int, + @SerialName("startMonth") + val startMonth: Int +){ + fun toScrapDetailModelList(): CalendarScrapDetailModel = + CalendarScrapDetailModel( + scrapId = scrapId, + internshipAnnouncementId = internshipAnnouncementId, + title = title, + dDay = dDay, + workingPeriod = workingPeriod, + color = color, + companyImage = companyImage, + startYear = startYear, + startMonth = startMonth, + deadLine = "" + ) + +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/dto/response/CalendarMonthListResponseDto.kt b/data/src/main/java/com/terning/data/dto/response/CalendarMonthListResponseDto.kt new file mode 100644 index 000000000..1aa7ac882 --- /dev/null +++ b/data/src/main/java/com/terning/data/dto/response/CalendarMonthListResponseDto.kt @@ -0,0 +1,50 @@ +package com.terning.data.dto.response + +import com.terning.domain.entity.response.CalendarScrapDetailModel +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class CalendarMonthListResponseDto( + @SerialName("deadline") + val deadline: String, + @SerialName("scraps") + val scraps: List +) { + @Serializable + data class Scrap( + @SerialName("scrapId") + val scrapId: Long, + @SerialName("internshipAnnouncementId") + val internshipAnnouncementId: Long, + @SerialName("title") + val title: String, + @SerialName("dDay") + val dDay: String, + @SerialName("workingPeriod") + val workingPeriod: String, + @SerialName("color") + val color: String, + @SerialName("companyImage") + val companyImage: String, + @SerialName("startYear") + val startYear: Int, + @SerialName("startMonth") + val startMonth: Int + ) + + fun toScrapDetailModelList(): List = scraps.map { scrap -> + CalendarScrapDetailModel( + scrapId = scrap.scrapId, + internshipAnnouncementId = scrap.internshipAnnouncementId, + title = scrap.title, + dDay = scrap.dDay, + workingPeriod = scrap.workingPeriod, + color = scrap.color, + companyImage = scrap.companyImage, + startYear = scrap.startYear, + startMonth = scrap.startMonth, + deadLine = deadline + ) + } +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/dto/response/CalendarMonthResponseDto.kt b/data/src/main/java/com/terning/data/dto/response/CalendarMonthResponseDto.kt new file mode 100644 index 000000000..2af310d95 --- /dev/null +++ b/data/src/main/java/com/terning/data/dto/response/CalendarMonthResponseDto.kt @@ -0,0 +1,33 @@ +package com.terning.data.dto.response + +import com.terning.domain.entity.response.CalendarScrapModel +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class CalendarMonthResponseDto( + @SerialName("deadline") + val deadline: String, + @SerialName("scraps") + val scraps: List +) { + @Serializable + data class Scrap( + @SerialName("scrapId") + val scrapId: Long, + @SerialName("title") + val title: String, + @SerialName("color") + val color: String + ) + + fun toScrapModelList(): List = scraps.map { scrap -> + CalendarScrapModel( + scrapId = scrap.scrapId, + title = scrap.title, + color = scrap.color, + deadLine = deadline, + isScrapped = true + ) + } +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/dto/response/MockResponseDto.kt b/data/src/main/java/com/terning/data/dto/response/MockResponseDto.kt deleted file mode 100644 index 6163bd8bd..000000000 --- a/data/src/main/java/com/terning/data/dto/response/MockResponseDto.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.terning.data.dto.response - -import com.terning.domain.entity.response.MockResponseModel -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class MockResponseDto( - @SerialName("page") - val page: Int, - @SerialName("per_page") - val per_page: Int, - @SerialName("total") - val total: Int, - @SerialName("total_pages") - val total_pages: Int, - @SerialName("data") - val data: List, - @SerialName("support") - val support: Support, -) { - @Serializable - data class MockData( - @SerialName("id") - val id: Int, - @SerialName("email") - val email: String, - @SerialName("first_name") - val first_name: String, - @SerialName("last_name") - val last_name: String, - @SerialName("avatar") - val avatar: String - ) - - @Serializable - data class Support( - @SerialName("url") - val url: String, - @SerialName("text") - val text: String, - ) - - fun toMockEntity(): List = data.map { - MockResponseModel( - avatar = it.avatar, - email = it.email, - firstName = it.first_name, - lastName = it.last_name - ) - } - -} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/dto/response/ScrapResponseDto.kt b/data/src/main/java/com/terning/data/dto/response/ScrapResponseDto.kt deleted file mode 100644 index 1a44012a9..000000000 --- a/data/src/main/java/com/terning/data/dto/response/ScrapResponseDto.kt +++ /dev/null @@ -1,328 +0,0 @@ -package com.terning.data.dto.response - -import com.terning.domain.entity.response.ScrapModel -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class ScrapResponseDto( - @SerialName("deadline") - val deadline: String, - @SerialName("scraps") - val scraps: List -) { - @Serializable - data class Scrap( - @SerialName("scrapId") - val scrapId: Long, - @SerialName("title") - val title: String, - @SerialName("color") - val color: String - ) - - fun toScrapModelList(): List = scraps.map { scrap -> - ScrapModel( - scrapId = scrap.scrapId, - title = scrap.title, - color = scrap.color, - deadLine = deadline, - isScrapped = true - ) - } -} - -fun getMockScrapList(year: Int, month: Int): List { - val deadline = month.toString().padStart(2, '0') - - return when (month % 4) { - 0 -> { - listOf( - ScrapResponseDto( - deadline = "${year}-${deadline}-13", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FFED4E54" - ), - ScrapResponseDto.Scrap( - scrapId = 2, - title = "제목2", - color = "#FFC4E953" - ), - ScrapResponseDto.Scrap( - scrapId = 3, - title = "제목3", - color = "#FF9B64E2" - ), - ScrapResponseDto.Scrap( - scrapId = 4, - title = "제목4", - color = "#FFF260AC" - ) - ) - ), - ScrapResponseDto( - deadline = "${year}-${deadline}-17", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FFC4E953" - ), - ScrapResponseDto.Scrap( - scrapId = 2, - title = "제목2", - color = "#FF45D0CC" - ), - ) - ), - ScrapResponseDto( - deadline = "${year}-${deadline}-23", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FF5397F3" - ) - ) - ), - ScrapResponseDto( - deadline = "${year}-${deadline}-30", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FF45D0CC" - ) - ) - ) - ) - } - - 1 -> { - listOf( - ScrapResponseDto( - deadline = "${year}-${deadline}-01", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FFED4E54" - ), - ScrapResponseDto.Scrap( - scrapId = 2, - title = "제목2", - color = "#FFC4E953" - ), - ScrapResponseDto.Scrap( - scrapId = 3, - title = "제목3", - color = "#FF9B64E2" - ), - ScrapResponseDto.Scrap( - scrapId = 4, - title = "제목4", - color = "#FFF260AC" - ) - ) - ), - ScrapResponseDto( - deadline = "${year}-${deadline}-02", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FFC4E953" - ), - ScrapResponseDto.Scrap( - scrapId = 2, - title = "제목2", - color = "#FF9B64E2" - ), - ScrapResponseDto.Scrap( - scrapId = 3, - title = "제목3", - color = "#FFED4E54" - ), - ScrapResponseDto.Scrap( - scrapId = 4, - title = "제목4", - color = "#FFF260AC" - ) - ) - ), - ScrapResponseDto( - deadline = "${year}-${deadline}-12", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FFC4E953" - ), - ScrapResponseDto.Scrap( - scrapId = 2, - title = "제목2", - color = "#FF45D0CC" - ), - ) - ), - ScrapResponseDto( - deadline = "${year}-${deadline}-27", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FF5397F3" - ) - ) - ), - ScrapResponseDto( - deadline = "${year}-${deadline}-29", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FF45D0CC" - ) - ) - ) - ) - } - - 2 -> { - listOf( - ScrapResponseDto( - deadline = "${year}-${deadline}-02", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FFED4E54" - ), - ScrapResponseDto.Scrap( - scrapId = 2, - title = "제목2", - color = "#FFC4E953" - ), - ScrapResponseDto.Scrap( - scrapId = 3, - title = "제목3", - color = "#FF9B64E2" - ), - ScrapResponseDto.Scrap( - scrapId = 4, - title = "제목4", - color = "#FFF260AC" - ) - ) - ), - ScrapResponseDto( - deadline = "${year}-${deadline}-18", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FFC4E953" - ), - ScrapResponseDto.Scrap( - scrapId = 2, - title = "제목2", - color = "#FF45D0CC" - ), - ) - ), - ScrapResponseDto( - deadline = "${year}-${deadline}-20", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FF5397F3" - ) - ) - ), - ScrapResponseDto( - deadline = "${year}-${deadline}-29", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FF45D0CC" - ) - ) - ) - ) - } - - 3 -> { - listOf( - ScrapResponseDto( - deadline = "${year}-${deadline}-05", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FFED4E54" - ), - ScrapResponseDto.Scrap( - scrapId = 2, - title = "제목2", - color = "#FFC4E953" - )/*, - ScrapResponsesDto.Scrap( - scrapId = 3, - title = "제목3", - color = "#FF9B64E2" - ), - ScrapResponsesDto.Scrap( - scrapId = 4, - title = "제목4", - color = "#FFF260AC" - )*/ - ) - ), - ScrapResponseDto( - deadline = "${year}-${deadline}-11", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FFC4E953" - ), - ScrapResponseDto.Scrap( - scrapId = 2, - title = "제목2", - color = "#FF45D0CC" - ), - ) - ), - ScrapResponseDto( - deadline = "${year}-${deadline}-19", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FF5397F3" - ) - ) - ), - ScrapResponseDto( - deadline = "${year}-${deadline}-28", - scraps = listOf( - ScrapResponseDto.Scrap( - scrapId = 1, - title = "제목1", - color = "#FF45D0CC" - ) - ) - ) - ) - } - - else -> { - listOf() - } - } -} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/dto/response/SearchViewsResponseDto.kt b/data/src/main/java/com/terning/data/dto/response/SearchViewsResponseDto.kt new file mode 100644 index 000000000..1f928b498 --- /dev/null +++ b/data/src/main/java/com/terning/data/dto/response/SearchViewsResponseDto.kt @@ -0,0 +1,27 @@ +package com.terning.data.dto.response + +import com.terning.domain.entity.response.InternshipAnnouncement +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class SearchViewsResponseDto( + @SerialName("internshipAnnouncementId") + val internshipAnnouncementId: Long, + @SerialName("companyImage") + val companyImage: String, + @SerialName("title") + val title: String, +) { + + + fun toSearchViewsEntity(): List { + return listOf( + InternshipAnnouncement( + announcementId = internshipAnnouncementId, + companyImage = companyImage, + title = title, + ) + ) + } +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/dto/response/SignInResponseDto.kt b/data/src/main/java/com/terning/data/dto/response/SignInResponseDto.kt new file mode 100644 index 000000000..eabc0ea67 --- /dev/null +++ b/data/src/main/java/com/terning/data/dto/response/SignInResponseDto.kt @@ -0,0 +1,24 @@ +package com.terning.data.dto.response + +import com.terning.domain.entity.response.SignInResponseModel +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class SignInResponseDto( + @SerialName("accessToken") + val accessToken: String, + @SerialName("refreshToken") + val refreshToken: String, + @SerialName("userId") + val userId: Long, + @SerialName("authType") + val authType: String, +) { + fun toSignInModel() = SignInResponseModel( + accessToken = accessToken, + refreshToken = refreshToken, + userId = userId, + authType = authType + ) +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/local/TerningDataStore.kt b/data/src/main/java/com/terning/data/local/TerningDataStore.kt new file mode 100644 index 000000000..23e6af70a --- /dev/null +++ b/data/src/main/java/com/terning/data/local/TerningDataStore.kt @@ -0,0 +1,8 @@ +package com.terning.data.local + +interface TerningDataStore { + var accessToken: String + var refreshToken: String + var userId: Long + fun clearInfo() +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/local/TerningDataStoreImpl.kt b/data/src/main/java/com/terning/data/local/TerningDataStoreImpl.kt new file mode 100644 index 000000000..573cc8f27 --- /dev/null +++ b/data/src/main/java/com/terning/data/local/TerningDataStoreImpl.kt @@ -0,0 +1,31 @@ +package com.terning.data.local + +import android.content.SharedPreferences +import androidx.core.content.edit +import javax.inject.Inject + +class TerningDataStoreImpl @Inject constructor( + private val dataStore: SharedPreferences, +) : TerningDataStore { + override var accessToken: String + get() = dataStore.getString(ACCESS_TOKEN, "") ?: "" + set(value) = dataStore.edit { putString(ACCESS_TOKEN, value) } + + override var refreshToken: String + get() = dataStore.getString(REFRESH_TOKEN, "") ?: "" + set(value) = dataStore.edit { putString(REFRESH_TOKEN, value) } + + override var userId: Long + get() = dataStore.getLong(USER_ID, 0L) + set(value) = dataStore.edit { putLong(USER_ID, value) } + + override fun clearInfo() { + dataStore.edit().clear().commit() + } + + companion object { + private const val ACCESS_TOKEN = "ACCESS_TOKEN" + private const val REFRESH_TOKEN = "REFRESH_TOKEN" + private const val USER_ID = "USER_ID" + } +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/repositoryimpl/AuthRepositoryImpl.kt b/data/src/main/java/com/terning/data/repositoryimpl/AuthRepositoryImpl.kt new file mode 100644 index 000000000..f5b5c1df7 --- /dev/null +++ b/data/src/main/java/com/terning/data/repositoryimpl/AuthRepositoryImpl.kt @@ -0,0 +1,22 @@ +package com.terning.data.repositoryimpl + +import com.terning.data.datasource.AuthDataSource +import com.terning.data.dto.request.toSignInRequestDto +import com.terning.domain.entity.request.SignInRequestModel +import com.terning.domain.entity.response.SignInResponseModel +import com.terning.domain.repository.AuthRepository +import javax.inject.Inject + +class AuthRepositoryImpl @Inject constructor( + private val authDataSource: AuthDataSource +) : AuthRepository { + override suspend fun postSignIn( + authorization: String, + request: SignInRequestModel + ): Result = kotlin.runCatching { + authDataSource.postSignIn( + authorization, + request.toSignInRequestDto() + ).result.toSignInModel() + } +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/repositoryimpl/CalendarRepositoryImpl.kt b/data/src/main/java/com/terning/data/repositoryimpl/CalendarRepositoryImpl.kt new file mode 100644 index 000000000..b9e0c308f --- /dev/null +++ b/data/src/main/java/com/terning/data/repositoryimpl/CalendarRepositoryImpl.kt @@ -0,0 +1,67 @@ +package com.terning.data.repositoryimpl + +import com.terning.data.datasource.CalendarDataSource +import com.terning.data.dto.request.CalendarDayListRequestDto +import com.terning.data.dto.request.CalendarMonthListRequestDto +import com.terning.data.dto.request.CalendarMonthRequestDto +import com.terning.domain.entity.response.CalendarScrapDetailModel +import com.terning.domain.entity.response.CalendarScrapModel +import com.terning.domain.repository.CalendarRepository +import java.time.LocalDate +import java.time.format.DateTimeFormatter +import javax.inject.Inject + +class CalendarRepositoryImpl @Inject constructor( + private val calendarDataSource: CalendarDataSource +) : CalendarRepository { + override suspend fun getScrapMonth( + year: Int, + month: Int + ): Result>> = + runCatching { + val result = calendarDataSource.getCalendarMonth( + request = CalendarMonthRequestDto( + year = year, + month = month + ) + ).result + + val scrapModelMapByDeadLine = result.flatMap { dto -> + dto.toScrapModelList() + }.groupBy { it.deadLine } + + scrapModelMapByDeadLine + } + + override suspend fun getScrapMonthList( + year: Int, + month: Int + ): Result>> = + runCatching { + val result = calendarDataSource.getCalendarMonthList( + request = CalendarMonthListRequestDto( + year = year, + month = month + ) + ).result + + val scrapModelMapByDeadLine = result.flatMap { dto -> + dto.toScrapDetailModelList() + }.groupBy { it.deadLine } + + scrapModelMapByDeadLine + } + + override suspend fun getScrapDayList( + currentDate: LocalDate + ): Result> = + runCatching { + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") + val request = CalendarDayListRequestDto(currentDate.format(formatter)) + val response = calendarDataSource.getCalendarDayList(request) + val scrapModelList = response.result.map { scrap -> + scrap.toScrapDetailModelList() + } + scrapModelList + } +} diff --git a/data/src/main/java/com/terning/data/repositoryimpl/MockRepositoryImpl.kt b/data/src/main/java/com/terning/data/repositoryimpl/MockRepositoryImpl.kt deleted file mode 100644 index d8cd7b4fa..000000000 --- a/data/src/main/java/com/terning/data/repositoryimpl/MockRepositoryImpl.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.terning.data.repositoryimpl - -import com.terning.data.datasource.MockDataSource -import com.terning.domain.entity.response.MockResponseModel -import com.terning.domain.repository.MockRepository -import javax.inject.Inject - -class MockRepositoryImpl @Inject constructor(private val mockDataSource: MockDataSource) : - MockRepository { - override suspend fun getMockList(page: Int): Result> = - runCatching { - mockDataSource.getMock(page).toMockEntity() - } -} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/repositoryimpl/ScrapRepositoryImpl.kt b/data/src/main/java/com/terning/data/repositoryimpl/ScrapRepositoryImpl.kt deleted file mode 100644 index 686cdf29a..000000000 --- a/data/src/main/java/com/terning/data/repositoryimpl/ScrapRepositoryImpl.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.terning.data.repositoryimpl - -import com.terning.data.datasource.ScrapDataSource -import com.terning.data.dto.request.ScrapRequestDto -import com.terning.domain.entity.response.ScrapModel -import com.terning.domain.repository.ScrapRepository -import javax.inject.Inject - -class ScrapRepositoryImpl @Inject constructor( - private val scrapDataSource: ScrapDataSource -): ScrapRepository { - override suspend fun getScrapMonth(year: Int, month: Int): Result>> = - runCatching { - val result = scrapDataSource.getScrapMonth( - request = ScrapRequestDto( - year = year, - month = month - ) - ).result - - val scrapModelMapByDeadLine = result.flatMap{ dto -> - dto.toScrapModelList() - }.groupBy { it.deadLine } - - scrapModelMapByDeadLine - } -} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/repositoryimpl/SearchViewsRepositoryImpl.kt b/data/src/main/java/com/terning/data/repositoryimpl/SearchViewsRepositoryImpl.kt new file mode 100644 index 000000000..3900c1f5e --- /dev/null +++ b/data/src/main/java/com/terning/data/repositoryimpl/SearchViewsRepositoryImpl.kt @@ -0,0 +1,15 @@ +package com.terning.data.repositoryimpl + +import com.terning.data.datasource.SearchDataSource +import com.terning.domain.entity.response.InternshipAnnouncement +import com.terning.domain.repository.SearchRepository +import javax.inject.Inject + +class SearchViewsRepositoryImpl @Inject constructor( + private val searchDataSource: SearchDataSource, +) : SearchRepository { + override suspend fun getSearchViewsList(): Result> = + runCatching { + searchDataSource.getSearchViews().result.toSearchViewsEntity() + } +} diff --git a/data/src/main/java/com/terning/data/repositoryimpl/TokenRepositoryImpl.kt b/data/src/main/java/com/terning/data/repositoryimpl/TokenRepositoryImpl.kt new file mode 100644 index 000000000..13b1a3031 --- /dev/null +++ b/data/src/main/java/com/terning/data/repositoryimpl/TokenRepositoryImpl.kt @@ -0,0 +1,27 @@ +package com.terning.data.repositoryimpl + +import com.terning.data.local.TerningDataStore +import com.terning.domain.repository.TokenRepository +import javax.inject.Inject + +class TokenRepositoryImpl @Inject constructor( + private val terningDataStore: TerningDataStore +) : TokenRepository { + override fun getAccessToken(): String = terningDataStore.accessToken + + override fun getRefreshToken(): String = terningDataStore.refreshToken + + override fun setTokens(accessToken: String, refreshToken: String) { + terningDataStore.accessToken = accessToken + terningDataStore.refreshToken = refreshToken + } + + override fun setUserId(userId: Long) { + terningDataStore.userId = userId + } + + override fun clearInfo() { + terningDataStore.clearInfo() + } + +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/service/AuthService.kt b/data/src/main/java/com/terning/data/service/AuthService.kt new file mode 100644 index 000000000..0e8aeba61 --- /dev/null +++ b/data/src/main/java/com/terning/data/service/AuthService.kt @@ -0,0 +1,16 @@ +package com.terning.data.service + +import com.terning.data.dto.BaseResponse +import com.terning.data.dto.request.SignInRequestDto +import com.terning.data.dto.response.SignInResponseDto +import retrofit2.http.Body +import retrofit2.http.Header +import retrofit2.http.POST + +interface AuthService { + @POST("api/v1/auth/sign-in") + suspend fun postSignIn( + @Header("Authorization") authorization: String, + @Body body: SignInRequestDto, + ): BaseResponse +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/service/CalendarService.kt b/data/src/main/java/com/terning/data/service/CalendarService.kt new file mode 100644 index 000000000..57a21408e --- /dev/null +++ b/data/src/main/java/com/terning/data/service/CalendarService.kt @@ -0,0 +1,28 @@ +package com.terning.data.service + +import com.terning.data.dto.BaseResponse +import com.terning.data.dto.response.CalendarMonthListResponseDto +import com.terning.data.dto.response.CalendarMonthResponseDto +import retrofit2.http.GET +import retrofit2.http.Query + +interface CalendarService{ + @GET("/api/v1/calendar/monthly-default") + suspend fun getCalendarScrapMonth( + @Query("year") year: Int, + @Query("month") month: Int + ): BaseResponse> + + @GET("/api/v1/calendar/monthly-list") + suspend fun getCalendarScrapMonthList( + @Query("year") year: Int, + @Query("month") month: Int + ): BaseResponse> + + @GET("/api/v1/calendar/daily") + suspend fun getCalendarScrapDayList( + @Query("year") year: Int, + @Query("month") month: Int, + @Query("day") day: Int + ): BaseResponse> +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/service/MockService.kt b/data/src/main/java/com/terning/data/service/MockService.kt deleted file mode 100644 index fddfe0b4b..000000000 --- a/data/src/main/java/com/terning/data/service/MockService.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.terning.data.service - -import com.terning.data.dto.response.MockResponseDto -import retrofit2.http.GET -import retrofit2.http.Query - -interface MockService { - @GET("api/users") - suspend fun getMockListFromServer( - @Query("page") page: Int, - ): MockResponseDto -} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/service/SearchService.kt b/data/src/main/java/com/terning/data/service/SearchService.kt new file mode 100644 index 000000000..e6f3e27d1 --- /dev/null +++ b/data/src/main/java/com/terning/data/service/SearchService.kt @@ -0,0 +1,10 @@ +package com.terning.data.service + +import com.terning.data.dto.BaseResponse +import com.terning.data.dto.response.SearchViewsResponseDto +import retrofit2.http.GET + +interface SearchService { + @GET("api/v1/search/views") + suspend fun getSearchViewsList(): BaseResponse +} \ No newline at end of file diff --git a/domain/src/main/java/com/terning/domain/entity/request/SignInRequestModel.kt b/domain/src/main/java/com/terning/domain/entity/request/SignInRequestModel.kt new file mode 100644 index 000000000..c51066a71 --- /dev/null +++ b/domain/src/main/java/com/terning/domain/entity/request/SignInRequestModel.kt @@ -0,0 +1,5 @@ +package com.terning.domain.entity.request + +data class SignInRequestModel( + val authType: String +) \ No newline at end of file diff --git a/domain/src/main/java/com/terning/domain/entity/response/CalendarScrapDetailModel.kt b/domain/src/main/java/com/terning/domain/entity/response/CalendarScrapDetailModel.kt new file mode 100644 index 000000000..881c4623b --- /dev/null +++ b/domain/src/main/java/com/terning/domain/entity/response/CalendarScrapDetailModel.kt @@ -0,0 +1,15 @@ +package com.terning.domain.entity.response + +data class CalendarScrapDetailModel( + val scrapId: Long, + val internshipAnnouncementId: Long, + val title: String, + val dDay: String, + val workingPeriod: String, + val color: String, + val companyImage: String, + val startYear: Int, + val startMonth: Int, + val deadLine: String, + val isScrapped: Boolean = true +) diff --git a/domain/src/main/java/com/terning/domain/entity/response/ScrapModel.kt b/domain/src/main/java/com/terning/domain/entity/response/CalendarScrapModel.kt similarity index 84% rename from domain/src/main/java/com/terning/domain/entity/response/ScrapModel.kt rename to domain/src/main/java/com/terning/domain/entity/response/CalendarScrapModel.kt index 8b68bbe35..162b4544d 100644 --- a/domain/src/main/java/com/terning/domain/entity/response/ScrapModel.kt +++ b/domain/src/main/java/com/terning/domain/entity/response/CalendarScrapModel.kt @@ -1,6 +1,6 @@ package com.terning.domain.entity.response -data class ScrapModel( +data class CalendarScrapModel( val scrapId: Long, val title: String, val deadLine: String, diff --git a/domain/src/main/java/com/terning/domain/entity/response/InternshipAnnouncement.kt b/domain/src/main/java/com/terning/domain/entity/response/InternshipAnnouncement.kt new file mode 100644 index 000000000..c090f25a9 --- /dev/null +++ b/domain/src/main/java/com/terning/domain/entity/response/InternshipAnnouncement.kt @@ -0,0 +1,7 @@ +package com.terning.domain.entity.response + +data class InternshipAnnouncement( + val title: String, + val companyImage: String, + val announcementId: Long, +) \ No newline at end of file diff --git a/domain/src/main/java/com/terning/domain/entity/response/MockResponseModel.kt b/domain/src/main/java/com/terning/domain/entity/response/MockResponseModel.kt deleted file mode 100644 index 5b272ff6b..000000000 --- a/domain/src/main/java/com/terning/domain/entity/response/MockResponseModel.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.terning.domain.entity.response - -data class MockResponseModel( - val avatar: String, - val email: String, - val firstName: String, - val lastName: String, -) \ No newline at end of file diff --git a/domain/src/main/java/com/terning/domain/entity/response/SignInResponseModel.kt b/domain/src/main/java/com/terning/domain/entity/response/SignInResponseModel.kt new file mode 100644 index 000000000..4ffe25fa8 --- /dev/null +++ b/domain/src/main/java/com/terning/domain/entity/response/SignInResponseModel.kt @@ -0,0 +1,8 @@ +package com.terning.domain.entity.response + +data class SignInResponseModel( + val accessToken : String? , + val refreshToken : String?, + val userId : Long, + val authType: String +) \ No newline at end of file diff --git a/domain/src/main/java/com/terning/domain/repository/AuthRepository.kt b/domain/src/main/java/com/terning/domain/repository/AuthRepository.kt new file mode 100644 index 000000000..7176db213 --- /dev/null +++ b/domain/src/main/java/com/terning/domain/repository/AuthRepository.kt @@ -0,0 +1,11 @@ +package com.terning.domain.repository + +import com.terning.domain.entity.request.SignInRequestModel +import com.terning.domain.entity.response.SignInResponseModel + +interface AuthRepository { + suspend fun postSignIn( + authorization: String, + request: SignInRequestModel + ): Result +} \ No newline at end of file diff --git a/domain/src/main/java/com/terning/domain/repository/CalendarRepository.kt b/domain/src/main/java/com/terning/domain/repository/CalendarRepository.kt new file mode 100644 index 000000000..2150e6864 --- /dev/null +++ b/domain/src/main/java/com/terning/domain/repository/CalendarRepository.kt @@ -0,0 +1,11 @@ +package com.terning.domain.repository + +import com.terning.domain.entity.response.CalendarScrapDetailModel +import com.terning.domain.entity.response.CalendarScrapModel +import java.time.LocalDate + +interface CalendarRepository{ + suspend fun getScrapMonth(year: Int, month: Int): Result>> + suspend fun getScrapMonthList(year: Int, month: Int): Result>> + suspend fun getScrapDayList(currentDate: LocalDate): Result> +} \ No newline at end of file diff --git a/domain/src/main/java/com/terning/domain/repository/MockRepository.kt b/domain/src/main/java/com/terning/domain/repository/MockRepository.kt deleted file mode 100644 index ca5e06da8..000000000 --- a/domain/src/main/java/com/terning/domain/repository/MockRepository.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.terning.domain.repository - -import com.terning.domain.entity.response.MockResponseModel - -interface MockRepository { - suspend fun getMockList(page: Int): Result> -} \ No newline at end of file diff --git a/domain/src/main/java/com/terning/domain/repository/ScrapRepository.kt b/domain/src/main/java/com/terning/domain/repository/ScrapRepository.kt deleted file mode 100644 index bc13c9639..000000000 --- a/domain/src/main/java/com/terning/domain/repository/ScrapRepository.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.terning.domain.repository - -import com.terning.domain.entity.response.ScrapModel - -interface ScrapRepository{ - suspend fun getScrapMonth(year: Int, month: Int): Result>> -} \ No newline at end of file diff --git a/domain/src/main/java/com/terning/domain/repository/SearchRepository.kt b/domain/src/main/java/com/terning/domain/repository/SearchRepository.kt new file mode 100644 index 000000000..c4b83bdb6 --- /dev/null +++ b/domain/src/main/java/com/terning/domain/repository/SearchRepository.kt @@ -0,0 +1,7 @@ +package com.terning.domain.repository + +import com.terning.domain.entity.response.InternshipAnnouncement + +interface SearchRepository { + suspend fun getSearchViewsList(): Result> +} \ No newline at end of file diff --git a/domain/src/main/java/com/terning/domain/repository/TokenRepository.kt b/domain/src/main/java/com/terning/domain/repository/TokenRepository.kt new file mode 100644 index 000000000..d55d469ef --- /dev/null +++ b/domain/src/main/java/com/terning/domain/repository/TokenRepository.kt @@ -0,0 +1,13 @@ +package com.terning.domain.repository + +interface TokenRepository { + fun getAccessToken(): String + + fun getRefreshToken(): String + + fun setTokens(accessToken: String, refreshToken: String) + + fun setUserId(userId: Long) + + fun clearInfo() +} diff --git a/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt b/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt index d6b1135c5..a64244d21 100644 --- a/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt +++ b/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt @@ -1,8 +1,6 @@ package com.terning.feature.calendar.calendar import androidx.activity.compose.BackHandler -import androidx.compose.animation.AnimatedContent -import androidx.compose.animation.SizeTransform import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutHorizontally @@ -11,7 +9,6 @@ import androidx.compose.animation.togetherWith import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Scaffold @@ -26,7 +23,6 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.LocalLifecycleOwner @@ -37,16 +33,14 @@ import androidx.navigation.compose.rememberNavController import com.terning.core.designsystem.component.topappbar.CalendarTopAppBar import com.terning.core.designsystem.theme.Grey200 import com.terning.core.extension.toast -import com.terning.feature.R import com.terning.feature.calendar.calendar.component.ScreenTransition import com.terning.feature.calendar.calendar.component.WeekDaysHeader import com.terning.feature.calendar.calendar.model.CalendarState import com.terning.feature.calendar.month.CalendarMonthScreen -import com.terning.feature.calendar.scrap.CalendarScrapList -import com.terning.feature.calendar.week.CalendarWeekWithScrap +import com.terning.feature.calendar.scrap.CalendarListScreen +import com.terning.feature.calendar.week.CalendarWeekScreen import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch -import java.time.LocalDate import java.time.YearMonth @Composable @@ -59,7 +53,7 @@ fun CalendarRoute( } @Composable -fun CalendarScreen( +private fun CalendarScreen( modifier: Modifier = Modifier, navController: NavController = rememberNavController(), viewModel: CalendarViewModel = hiltViewModel() @@ -168,24 +162,20 @@ fun CalendarScreen( ) }, contentTwo = { - CalendarWeekWithScrap( + CalendarWeekScreen( modifier = Modifier .fillMaxSize(), - selectedDate = calendarUiState, - scrapLists = viewModel.mockScrapList, - onDateSelected = { - viewModel.updateSelectedDate(it) - } + viewModel = viewModel ) } ) } }, contentTwo = { - CalendarScrapList( - scrapList = viewModel.mockScrapList, + CalendarListScreen( listState = listState, pages = state.getPageCount(), + viewModel = viewModel, modifier = Modifier .fillMaxSize() .padding(top = paddingValues.calculateTopPadding()) diff --git a/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt b/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt index 2f6d7ad04..0c11f4792 100644 --- a/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt +++ b/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt @@ -2,18 +2,12 @@ package com.terning.feature.calendar.calendar import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.terning.core.designsystem.theme.CalBlue1 -import com.terning.core.designsystem.theme.CalGreen1 -import com.terning.core.designsystem.theme.CalGreen2 -import com.terning.core.designsystem.theme.CalPink -import com.terning.core.designsystem.theme.CalPurple -import com.terning.core.designsystem.theme.CalRed -import com.terning.core.designsystem.theme.CalYellow import com.terning.core.state.UiState -import com.terning.domain.repository.ScrapRepository +import com.terning.domain.repository.CalendarRepository import com.terning.feature.R -import com.terning.feature.calendar.month.ScrapCalendarState -import com.terning.feature.calendar.scrap.model.Scrap +import com.terning.feature.calendar.month.CalendarMonthState +import com.terning.feature.calendar.scrap.CalendarListState +import com.terning.feature.calendar.week.CalendarWeekState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableSharedFlow @@ -28,10 +22,10 @@ import javax.inject.Inject @HiltViewModel class CalendarViewModel @Inject constructor( - private val scrapRepository: ScrapRepository + private val calendarRepository: CalendarRepository ) : ViewModel() { - private var _selectedDate:MutableStateFlow = MutableStateFlow( + private var _selectedDate: MutableStateFlow = MutableStateFlow( CalendarUiState( selectedDate = LocalDate.now(), isListEnabled = false @@ -40,10 +34,16 @@ class CalendarViewModel @Inject constructor( val selectedDate get() = _selectedDate.asStateFlow() - private val _scrapCalendarState = MutableStateFlow(ScrapCalendarState()) - val scrapCalendarState = _scrapCalendarState.asStateFlow() + private val _calendarMonthState = MutableStateFlow(CalendarMonthState()) + val calendarMonthState = _calendarMonthState.asStateFlow() - private val _calendarSideEffect:MutableSharedFlow = MutableSharedFlow() + private val _calendarListState = MutableStateFlow(CalendarListState()) + val calendarListState = _calendarListState.asStateFlow() + + private val _calendarWeekState = MutableStateFlow(CalendarWeekState()) + val calendarWeekState = _calendarWeekState.asStateFlow() + + private val _calendarSideEffect: MutableSharedFlow = MutableSharedFlow() val calendarSideEffect = _calendarSideEffect.asSharedFlow() fun updateSelectedDate(date: LocalDate) = viewModelScope.launch { @@ -54,6 +54,7 @@ class CalendarViewModel @Inject constructor( isWeekEnabled = true ) } + getScrapWeekList() } else { _selectedDate.update { currentState -> currentState.copy( @@ -83,15 +84,14 @@ class CalendarViewModel @Inject constructor( year: Int, month: Int ) = viewModelScope.launch { withContext(Dispatchers.IO) { - scrapRepository.getScrapMonth(year, month) + calendarRepository.getScrapMonth(year, month) }.fold( onSuccess = { - _scrapCalendarState.update { currentState -> + _calendarMonthState.update { currentState -> currentState.copy( loadState = UiState.Success(it) ) } - _calendarSideEffect.emit(CalendarSideEffect.ShowToast(R.string.server_success)) }, onFailure = { _calendarSideEffect.emit(CalendarSideEffect.ShowToast(R.string.server_failure)) @@ -99,122 +99,54 @@ class CalendarViewModel @Inject constructor( ) } + fun getScrapMonthList( + year: Int, month: Int + ) = viewModelScope.launch { + withContext(Dispatchers.IO) { + calendarRepository.getScrapMonthList(year, month) + }.fold( + onSuccess = { + _calendarListState.update { currentState -> + currentState.copy( + loadState = if (it.isNotEmpty()) UiState.Success(it) else UiState.Empty + //loadState = UiState.Success(it) + ) + } + }, + onFailure = { + _calendarListState.update { currentState -> + currentState.copy( + loadState = UiState.Failure(it.message.toString()) + ) - //To be erased in future - val mockScrapList: List> - get() { - val list: MutableList> = mutableListOf() - for (i in 0..30) { - when (i % 6) { - 0 -> { - list.add( - i, - listOf() - ) - } - - 1 -> { - list.add( - i, - listOf( - Scrap( - "Task1_1", - CalBlue1, - dDay = "1", - period = "3", - isScraped = true - ), - ) - ) - } - - 2 -> { - list.add( - i, - listOf( - Scrap( - "Task2_1", - CalPink, - dDay = "2", - period = "3", - isScraped = true - ), - Scrap( - "Task2_2", - CalGreen1, - dDay = "2", - period = "3", - isScraped = true - ) - ) - ) - } - - 3 -> { - list.add( - i, - listOf() - ) - } - - 4 -> { - list.add( - i, - listOf() - ) - } - - 5 -> { - list.add( - i, - listOf( - Scrap( - "Task3_1", - CalPink, - dDay = "5", - period = "3", - isScraped = true - ), - Scrap( - "Task3_2", - CalPurple, - dDay = "5", - period = "3", - isScraped = true - ), - Scrap( - "Task3_3", - CalRed, - dDay = "5", - period = "3", - isScraped = true - ), - Scrap( - "Task3_4", - CalBlue1, - dDay = "5", - period = "3", - isScraped = true - ), - Scrap( - "Task3_5", - CalGreen2, - dDay = "5", - period = "3", - isScraped = true - ), - Scrap( - "Task3_6", - CalYellow, - dDay = "5", - period = "3", - isScraped = true - ) - ) - ) - } } + _calendarSideEffect.emit(CalendarSideEffect.ShowToast(R.string.server_failure)) } - return list.toList() - } + ) + } + + fun getScrapWeekList() = viewModelScope.launch { + withContext(Dispatchers.IO) { + calendarRepository.getScrapDayList(_selectedDate.value.selectedDate) + }.fold( + onSuccess = { + _calendarWeekState.update { currentState -> + currentState.copy( + loadState = if (it.isNotEmpty()) UiState.Success(it) else UiState.Empty + //loadState = UiState.Success(it) + ) + } + _calendarSideEffect.emit(CalendarSideEffect.ShowToast(R.string.server_success)) + }, + onFailure = { + _calendarWeekState.update { currentState -> + currentState.copy( + loadState = UiState.Failure(it.message.toString()) + ) + + } + _calendarSideEffect.emit(CalendarSideEffect.ShowToast(R.string.server_failure)) + } + ) + } } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonth.kt b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonth.kt index dad61a86e..4fa0f6f50 100644 --- a/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonth.kt +++ b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonth.kt @@ -12,8 +12,9 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.terning.core.designsystem.theme.Grey150 import com.terning.core.designsystem.theme.TerningPointTheme +import com.terning.core.extension.getDateAsMapString import com.terning.core.extension.isToday -import com.terning.domain.entity.response.ScrapModel +import com.terning.domain.entity.response.CalendarScrapModel import com.terning.feature.calendar.calendar.CalendarUiState import com.terning.feature.calendar.month.component.CalendarDay import com.terning.feature.calendar.month.model.MonthData @@ -27,7 +28,7 @@ fun CalendarMonth( monthData: MonthData, onDateSelected: (LocalDate) -> Unit, calendarUiState: CalendarUiState, - scrapMap: Map> = mapOf() + scrapMap: Map> = mapOf() ) { Column( modifier = modifier @@ -53,7 +54,7 @@ fun CalendarMonth( onDateSelected = onDateSelected ) if(!day.isOutDate) { - val index = day.date.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd")) + val index = day.date.getDateAsMapString() CalendarScrapStrip( scrapLists = scrapMap[index].orEmpty() ) diff --git a/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt index 4e36aefca..06fb41092 100644 --- a/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt +++ b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt @@ -12,12 +12,12 @@ import androidx.compose.ui.Modifier import androidx.hilt.navigation.compose.hiltViewModel import com.terning.core.designsystem.theme.White import com.terning.core.state.UiState -import com.terning.domain.entity.response.ScrapModel +import com.terning.domain.entity.response.CalendarScrapModel +import com.terning.feature.calendar.calendar.CalendarUiState +import com.terning.feature.calendar.calendar.CalendarViewModel import com.terning.feature.calendar.calendar.model.CalendarDefaults.flingBehavior import com.terning.feature.calendar.calendar.model.CalendarState.Companion.getDateByPage -import com.terning.feature.calendar.calendar.CalendarViewModel import com.terning.feature.calendar.month.model.MonthData -import com.terning.feature.calendar.calendar.CalendarUiState import kotlinx.coroutines.flow.distinctUntilChanged import java.time.LocalDate import java.time.YearMonth @@ -31,7 +31,7 @@ fun CalendarMonthScreen( modifier: Modifier = Modifier, viewModel: CalendarViewModel = hiltViewModel() ) { - val scrapState by viewModel.scrapCalendarState.collectAsState() + val scrapState by viewModel.calendarMonthState.collectAsState() LaunchedEffect(key1 = listState) { snapshotFlow { listState.firstVisibleItemIndex } @@ -48,25 +48,25 @@ fun CalendarMonthScreen( UiState.Empty -> {} is UiState.Failure -> {} is UiState.Success -> { + val scrapMap = (scrapState.loadState as UiState.Success).data HorizontalCalendar( pages = pages, - modifier = modifier, + listState = listState, calendarUiState = calendarUiState, + scrapMap = scrapMap, onDateSelected = onDateSelected, - listState = listState, - scrapMap = (scrapState.loadState as UiState.Success).data + modifier = modifier ) } } } - @Composable fun HorizontalCalendar( pages: Int, listState: LazyListState, calendarUiState: CalendarUiState, - scrapMap: Map>, + scrapMap: Map>, onDateSelected: (LocalDate) -> Unit, modifier: Modifier = Modifier, ) { diff --git a/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthState.kt b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthState.kt new file mode 100644 index 000000000..acd6b1bde --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthState.kt @@ -0,0 +1,8 @@ +package com.terning.feature.calendar.month + +import com.terning.core.state.UiState +import com.terning.domain.entity.response.CalendarScrapModel + +data class CalendarMonthState ( + val loadState: UiState>> = UiState.Loading +) \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/month/ScrapCalendarState.kt b/feature/src/main/java/com/terning/feature/calendar/month/ScrapCalendarState.kt deleted file mode 100644 index c332a75a9..000000000 --- a/feature/src/main/java/com/terning/feature/calendar/month/ScrapCalendarState.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.terning.feature.calendar.month - -import com.terning.core.state.UiState -import com.terning.domain.entity.response.ScrapModel - -data class ScrapCalendarState ( - val loadState: UiState>> = UiState.Loading -) \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/scrap/CalendarListScreen.kt b/feature/src/main/java/com/terning/feature/calendar/scrap/CalendarListScreen.kt new file mode 100644 index 000000000..04bdf8532 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/scrap/CalendarListScreen.kt @@ -0,0 +1,124 @@ +package com.terning.feature.calendar.scrap + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.LocalLifecycleOwner +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.terning.core.designsystem.theme.Back +import com.terning.core.designsystem.theme.Grey400 +import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.designsystem.theme.White +import com.terning.core.extension.getDateAsMapString +import com.terning.core.extension.isListNotEmpty +import com.terning.core.state.UiState +import com.terning.feature.R +import com.terning.feature.calendar.calendar.CalendarViewModel +import com.terning.feature.calendar.calendar.model.CalendarDefaults.flingBehavior +import com.terning.feature.calendar.calendar.model.CalendarState.Companion.getDateByPage +import com.terning.feature.calendar.scrap.component.CalendarScrapList +import kotlinx.coroutines.flow.distinctUntilChanged +import java.time.LocalDate + +@Composable +fun CalendarListScreen( + pages: Int, + listState: LazyListState, + modifier: Modifier = Modifier, + viewModel: CalendarViewModel = hiltViewModel() +) { + val lifecycleOwner = LocalLifecycleOwner.current + val scrapState by viewModel.calendarListState.collectAsStateWithLifecycle(lifecycleOwner) + + LaunchedEffect(key1 = listState) { + snapshotFlow { listState.firstVisibleItemIndex } + .distinctUntilChanged() + .collect { + val page = listState.firstVisibleItemIndex + val date = getDateByPage(page) + viewModel.getScrapMonthList(date.year, date.monthValue) + } + } + + + LazyRow( + modifier = modifier + .background(White), + state = listState, + userScrollEnabled = true, + flingBehavior = flingBehavior( + state = listState + ) + ) { + items(pages) { page -> + val getDate = getDateByPage(page) + + LazyColumn( + modifier = Modifier + .fillParentMaxWidth() + .fillMaxHeight() + .background(Back) + ) { + when (scrapState.loadState) { + UiState.Loading -> {} + UiState.Empty -> { + item { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text( + modifier = Modifier + .padding(top = 42.dp) + .fillMaxWidth(), + text = stringResource(id = R.string.calendar_empty_scrap), + textAlign = TextAlign.Center, + style = TerningTheme.typography.body5, + color = Grey400 + ) + } + } + } + + is UiState.Failure -> {} + is UiState.Success -> { + items(getDate.lengthOfMonth()) { day -> + val scrapMap = (scrapState.loadState as UiState.Success).data + val currentDate = + LocalDate.of(getDate.year, getDate.monthValue, day + 1) + val dateIndex = currentDate.getDateAsMapString() + + if (scrapMap[dateIndex].isListNotEmpty()) { + CalendarScrapList( + selectedDate = currentDate, + scrapList = scrapMap[dateIndex].orEmpty(), + isFromList = true, + + noScrapScreen = {}) + } + } + } + } + } + } + } +} + + diff --git a/feature/src/main/java/com/terning/feature/calendar/scrap/CalendarListState.kt b/feature/src/main/java/com/terning/feature/calendar/scrap/CalendarListState.kt new file mode 100644 index 000000000..958a020e8 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/scrap/CalendarListState.kt @@ -0,0 +1,8 @@ +package com.terning.feature.calendar.scrap + +import com.terning.core.state.UiState +import com.terning.domain.entity.response.CalendarScrapDetailModel + +data class CalendarListState ( + val loadState: UiState>> = UiState.Loading +) \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/scrap/CalendarMonthScrap.kt b/feature/src/main/java/com/terning/feature/calendar/scrap/CalendarMonthScrap.kt index c07a9ea52..900bf6d5a 100644 --- a/feature/src/main/java/com/terning/feature/calendar/scrap/CalendarMonthScrap.kt +++ b/feature/src/main/java/com/terning/feature/calendar/scrap/CalendarMonthScrap.kt @@ -15,12 +15,12 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.designsystem.theme.White -import com.terning.domain.entity.response.ScrapModel +import com.terning.domain.entity.response.CalendarScrapModel @Composable fun CalendarScrapStrip( modifier: Modifier = Modifier, - scrapLists: List + scrapLists: List ) { LazyColumn( modifier = modifier.fillMaxWidth() diff --git a/feature/src/main/java/com/terning/feature/calendar/scrap/CalendarScrapList.kt b/feature/src/main/java/com/terning/feature/calendar/scrap/CalendarScrapList.kt deleted file mode 100644 index 099df3971..000000000 --- a/feature/src/main/java/com/terning/feature/calendar/scrap/CalendarScrapList.kt +++ /dev/null @@ -1,125 +0,0 @@ -package com.terning.feature.calendar.scrap - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.terning.core.designsystem.theme.Back -import com.terning.core.designsystem.theme.Black -import com.terning.core.designsystem.theme.Grey200 -import com.terning.core.designsystem.theme.TerningTheme -import com.terning.core.designsystem.theme.White -import com.terning.core.extension.getDateStringInKorean -import com.terning.feature.calendar.calendar.model.CalendarDefaults.flingBehavior -import com.terning.feature.calendar.calendar.model.CalendarState.Companion.getDateByPage -import com.terning.feature.calendar.scrap.component.CalendarScrap -import com.terning.feature.calendar.scrap.model.Scrap -import java.time.LocalDate - -@Composable -fun CalendarScrapList( - scrapList: List>, - pages: Int, - listState: LazyListState, - modifier: Modifier = Modifier -) { - LazyRow( - modifier = modifier - .background(White), - state = listState, - userScrollEnabled = true, - flingBehavior = flingBehavior( - state = listState - ) - ) { - items(pages) { page -> - val getDate = getDateByPage(page) - - LazyColumn( - modifier = Modifier - .fillParentMaxWidth() - .fillMaxHeight() - .background(Back) - ) { - items(scrapList.size) { day -> - runCatching { - LocalDate.of(getDate.year, getDate.monthValue, day + 1) - }.onSuccess { - CalendarScrapList( - selectedDate = it, - scrapLists = scrapList, - isFromList = true, - noScrapScreen = {}) - - - if (scrapList[day].isNotEmpty()) { - Spacer( - modifier = Modifier - .height(4.dp) - .fillMaxWidth() - .background(Grey200) - ) - } - } - } - } - } - } -} - -@Composable -fun CalendarScrapList( - selectedDate: LocalDate, - scrapLists: List>, - isFromList: Boolean = false, - noScrapScreen: @Composable () -> Unit -) { - val scrollState = rememberScrollState() - if (scrapLists[selectedDate.dayOfMonth - 1].isNotEmpty()) { - Text( - text = selectedDate.getDateStringInKorean(), - style = TerningTheme.typography.title5, - color = Black, - modifier = Modifier.padding(start = 24.dp, top = 16.dp, bottom = 15.dp) - ) - } - val topModifier = if (!isFromList) { - Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp) - .verticalScroll(scrollState) - } else { - Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp) - } - - if (scrapLists[selectedDate.dayOfMonth - 1].isEmpty()) { - noScrapScreen() - } else { - Column( - modifier = topModifier - ) { - for (scrap in scrapLists[selectedDate.dayOfMonth - 1]) { - CalendarScrap( - scrap = scrap - ) - Spacer( - modifier = Modifier.height(12.dp) - ) - } - } - } -} diff --git a/feature/src/main/java/com/terning/feature/calendar/scrap/component/CalendarScrap.kt b/feature/src/main/java/com/terning/feature/calendar/scrap/component/CalendarScrap.kt index 2989c59f7..239618a87 100644 --- a/feature/src/main/java/com/terning/feature/calendar/scrap/component/CalendarScrap.kt +++ b/feature/src/main/java/com/terning/feature/calendar/scrap/component/CalendarScrap.kt @@ -2,28 +2,29 @@ package com.terning.feature.calendar.scrap.component import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.terning.core.designsystem.component.item.InternItem import com.terning.core.designsystem.component.item.ScrapBox -import com.terning.feature.calendar.scrap.model.Scrap +import com.terning.domain.entity.response.CalendarScrapDetailModel @Composable fun CalendarScrap( - scrap: Scrap, + scrap: CalendarScrapDetailModel, modifier: Modifier = Modifier, ) { ScrapBox( modifier = modifier, cornerRadius = 10.dp, - scrapColor = scrap.backgroundColor, + scrapColor = Color(android.graphics.Color.parseColor(scrap.color)), elevation = 1.dp, ) { InternItem( - imageUrl = scrap.image.orEmpty(), - title = scrap.text, + imageUrl = scrap.companyImage.orEmpty(), + title = scrap.title, dateDeadline = scrap.dDay, - workingPeriod = scrap.period, - isScraped = scrap.isScraped + workingPeriod = scrap.workingPeriod, + isScraped = scrap.isScrapped ) } } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/scrap/component/CalendarScrapList.kt b/feature/src/main/java/com/terning/feature/calendar/scrap/component/CalendarScrapList.kt new file mode 100644 index 000000000..844e4e523 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/scrap/component/CalendarScrapList.kt @@ -0,0 +1,65 @@ +package com.terning.feature.calendar.scrap.component + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.terning.core.designsystem.theme.Black +import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.extension.getDateStringInKorean +import com.terning.core.extension.isListNotEmpty +import com.terning.domain.entity.response.CalendarScrapDetailModel +import java.time.LocalDate + +@Composable +fun CalendarScrapList( + selectedDate: LocalDate, + scrapList: List, + isFromList: Boolean = false, + noScrapScreen: @Composable () -> Unit +) { + val scrollState = rememberScrollState() + + if (scrapList.isListNotEmpty()) { + Text( + text = selectedDate.getDateStringInKorean(), + style = TerningTheme.typography.title5, + color = Black, + modifier = Modifier.padding(start = 24.dp, top = 16.dp, bottom = 15.dp) + ) + } + val topModifier = if (!isFromList) { + Modifier + .fillMaxWidth() + .padding(horizontal = 24.dp) + .verticalScroll(scrollState) + } else { + Modifier + .fillMaxWidth() + .padding(horizontal = 24.dp) + } + + if (!scrapList.isListNotEmpty()) { + noScrapScreen() + } else { + Column( + modifier = topModifier + ) { + for (scrap in scrapList) { + CalendarScrap( + scrap = scrap + ) + Spacer( + modifier = Modifier.height(12.dp) + ) + } + } + } +} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt b/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt new file mode 100644 index 000000000..b22a15f9a --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt @@ -0,0 +1,124 @@ +package com.terning.feature.calendar.week + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Card +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +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.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.LocalLifecycleOwner +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.terning.core.designsystem.theme.Back +import com.terning.core.designsystem.theme.Grey200 +import com.terning.core.designsystem.theme.Grey400 +import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.designsystem.theme.White +import com.terning.core.state.UiState +import com.terning.domain.entity.response.CalendarScrapDetailModel +import com.terning.feature.R +import com.terning.feature.calendar.calendar.CalendarViewModel +import com.terning.feature.calendar.scrap.component.CalendarScrapList +import java.time.LocalDate + +@Composable +fun CalendarWeekScreen( + modifier: Modifier = Modifier, + viewModel: CalendarViewModel = hiltViewModel() +) { + val lifecycleOwner = LocalLifecycleOwner.current + val uiState by viewModel.selectedDate.collectAsStateWithLifecycle(lifecycleOwner) + val calendarWeekState by viewModel.calendarWeekState.collectAsStateWithLifecycle(lifecycleOwner) + + LaunchedEffect(uiState.selectedDate) { + viewModel.getScrapWeekList() + } + + Column( + modifier = modifier + .background(Back) + ) { + Card( + modifier = Modifier + .border( + width = 0.dp, + color = Grey200, + shape = RoundedCornerShape(bottomStart = 20.dp, bottomEnd = 20.dp) + ) + .shadow( + shape = RoundedCornerShape(bottomStart = 20.dp, bottomEnd = 20.dp), + elevation = 1.dp + ), + + shape = RoundedCornerShape(bottomStart = 20.dp, bottomEnd = 20.dp), + ) { + HorizontalCalendarWeek( + modifier = Modifier + .fillMaxWidth() + .background(White), + selectedDate = uiState, + onDateSelected = { + viewModel.updateSelectedDate(it) + } + ) + } + + when (calendarWeekState.loadState) { + is UiState.Loading -> {} + is UiState.Empty -> { + CalendarWeekEmpty() + } + is UiState.Failure -> {} + is UiState.Success -> { + val scrapList = (calendarWeekState.loadState as UiState.Success).data + CalendarWeekSuccess(scrapList = scrapList, selectedDate = uiState.selectedDate) + } + } + } +} + +@Composable +fun CalendarWeekEmpty( + modifier: Modifier = Modifier +) { + Box( + contentAlignment = Alignment.Center + ) { + + + Text( + modifier = Modifier + .padding(top = 42.dp) + .fillMaxWidth(), + text = stringResource(id = R.string.calendar_empty_scrap), + textAlign = TextAlign.Center, + style = TerningTheme.typography.body5, + color = Grey400 + ) + } +} + +@Composable +fun CalendarWeekSuccess( + scrapList: List, + selectedDate: LocalDate, +) { + + CalendarScrapList(selectedDate = selectedDate, scrapList = scrapList) {} +} + + + + diff --git a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekState.kt b/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekState.kt new file mode 100644 index 000000000..8c661ee2e --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekState.kt @@ -0,0 +1,8 @@ +package com.terning.feature.calendar.week + +import com.terning.core.state.UiState +import com.terning.domain.entity.response.CalendarScrapDetailModel + +data class CalendarWeekState ( + val loadState: UiState> = UiState.Loading +) \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekWithScrap.kt b/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekWithScrap.kt deleted file mode 100644 index 6745379f9..000000000 --- a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekWithScrap.kt +++ /dev/null @@ -1,80 +0,0 @@ -package com.terning.feature.calendar.week - -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Card -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.shadow -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import com.terning.core.designsystem.theme.Back -import com.terning.core.designsystem.theme.Grey200 -import com.terning.core.designsystem.theme.Grey400 -import com.terning.core.designsystem.theme.TerningTheme -import com.terning.core.designsystem.theme.White -import com.terning.feature.R -import com.terning.feature.calendar.calendar.CalendarUiState -import com.terning.feature.calendar.scrap.model.Scrap -import com.terning.feature.calendar.scrap.CalendarScrapList -import java.time.LocalDate - -@Composable -fun CalendarWeekWithScrap( - modifier: Modifier = Modifier, - selectedDate: CalendarUiState, - scrapLists: List> = listOf(), - onDateSelected: (LocalDate) -> Unit -) { - Column( - modifier = modifier - .background(Back) - ) { - Card( - modifier = Modifier - .border( - width = 0.dp, - color = Grey200, - shape = RoundedCornerShape(bottomStart = 20.dp, bottomEnd = 20.dp) - ) - .shadow( - shape = RoundedCornerShape(bottomStart = 20.dp, bottomEnd = 20.dp), - elevation = 1.dp - ), - - shape = RoundedCornerShape(bottomStart = 20.dp, bottomEnd = 20.dp), - ) { - CalendarWeek( - modifier = Modifier - .fillMaxWidth() - .background(White), - selectedDate = selectedDate, - onDateSelected = onDateSelected - ) - } - CalendarScrapList( - selectedDate = selectedDate.selectedDate, - scrapLists = scrapLists, - noScrapScreen = { - Text( - modifier = Modifier - .padding(top = 42.dp) - .fillMaxWidth(), - text = stringResource(id = R.string.calendar_empty_scrap), - textAlign = TextAlign.Center, - style = TerningTheme.typography.body5, - color = Grey400 - ) - } - ) - } -} - - - diff --git a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeek.kt b/feature/src/main/java/com/terning/feature/calendar/week/HorizontalCalendarWeek.kt similarity index 98% rename from feature/src/main/java/com/terning/feature/calendar/week/CalendarWeek.kt rename to feature/src/main/java/com/terning/feature/calendar/week/HorizontalCalendarWeek.kt index 7ed5bf177..4bfe69ba4 100644 --- a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeek.kt +++ b/feature/src/main/java/com/terning/feature/calendar/week/HorizontalCalendarWeek.kt @@ -19,7 +19,7 @@ import java.time.LocalDate import java.time.YearMonth @Composable -fun CalendarWeek( +fun HorizontalCalendarWeek( selectedDate: CalendarUiState, modifier: Modifier = Modifier, onDateSelected: (LocalDate) -> Unit = {} diff --git a/feature/src/main/java/com/terning/feature/intern/InternRoute.kt b/feature/src/main/java/com/terning/feature/intern/InternRoute.kt index 198943c7a..8a035648a 100644 --- a/feature/src/main/java/com/terning/feature/intern/InternRoute.kt +++ b/feature/src/main/java/com/terning/feature/intern/InternRoute.kt @@ -71,7 +71,9 @@ fun InternScreen( color = Grey200, offsetY = 2.dp ), - onBackButtonClick = {}, + onBackButtonClick = { + navController.navigateUp() + }, ) }, bottomBar = { diff --git a/feature/src/main/java/com/terning/feature/mypage/MyPageViewModel.kt b/feature/src/main/java/com/terning/feature/mypage/MyPageViewModel.kt index c64ae552b..50efca522 100644 --- a/feature/src/main/java/com/terning/feature/mypage/MyPageViewModel.kt +++ b/feature/src/main/java/com/terning/feature/mypage/MyPageViewModel.kt @@ -1,12 +1,11 @@ package com.terning.feature.mypage import androidx.lifecycle.ViewModel -import com.terning.domain.repository.MockRepository import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class MyPageViewModel @Inject constructor(private val repository: MockRepository) : ViewModel() { +class MyPageViewModel @Inject constructor() : ViewModel() { } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt index eef3a7100..e0dcafa6f 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt @@ -42,6 +42,7 @@ fun SignInRoute( when (sideEffect) { is SignInSideEffect.ShowToast -> context.toast(sideEffect.message) is SignInSideEffect.NavigateToHome -> navController.navigateSignUp() + is SignInSideEffect.NavigateSignUp -> navController.navigateSignUp() } } } diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt index 412652e66..ef9f7dc62 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt @@ -4,5 +4,6 @@ import androidx.annotation.StringRes sealed class SignInSideEffect { data object NavigateToHome : SignInSideEffect() + data object NavigateSignUp : SignInSideEffect() data class ShowToast(@StringRes val message: Int) : SignInSideEffect() } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt index 639b9eb71..cb09c9e94 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt @@ -8,6 +8,9 @@ import com.kakao.sdk.common.model.ClientError import com.kakao.sdk.common.model.ClientErrorCause import com.kakao.sdk.user.UserApiClient import com.terning.core.state.UiState +import com.terning.domain.entity.request.SignInRequestModel +import com.terning.domain.repository.AuthRepository +import com.terning.domain.repository.TokenRepository import com.terning.feature.R import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow @@ -20,7 +23,14 @@ import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel -class SignInViewModel @Inject constructor() : ViewModel() { +class SignInViewModel @Inject constructor( + private val authRepository: AuthRepository, + private val tokenRepository: TokenRepository +) : ViewModel() { + + init { + tokenRepository.clearInfo() + } private val _signInState = MutableStateFlow(SignInState()) val signInState: StateFlow @@ -47,7 +57,7 @@ class SignInViewModel @Inject constructor() : ViewModel() { if (error != null) { signInFailure(context, error) } else if (token != null) { - signInSuccess(token) + signInSuccess(token.accessToken) } } } @@ -72,15 +82,36 @@ class SignInViewModel @Inject constructor() : ViewModel() { } } - private fun signInSuccess(token: OAuthToken) { - viewModelScope.launch { - _signInState.value = - _signInState.value.copy(accessToken = UiState.Success(token.accessToken)) - _signInSideEffects.emit(SignInSideEffect.NavigateToHome) + private suspend fun signInSuccess( + accessToken: String, + platform: String = KAKAO + ) { + authRepository.postSignIn( + accessToken, + SignInRequestModel(platform) + ).onSuccess { response -> + when { + response.accessToken == null -> _signInSideEffects.emit(SignInSideEffect.NavigateSignUp) + + else -> { + tokenRepository.setTokens( + response.accessToken ?: return, + response.refreshToken ?: return + ) + tokenRepository.setUserId(response.userId) + + _signInSideEffects.emit(SignInSideEffect.NavigateToHome) + } + } + }.onFailure { + _signInState.value = SignInState(UiState.Failure(it.message.toString())) + _signInSideEffects.emit(SignInSideEffect.ShowToast(R.string.server_failure)) } + } companion object { private const val KAKAO_NOT_LOGGED_IN = "statusCode=302" + private const val KAKAO = "KAKAO" } } diff --git a/feature/src/main/java/com/terning/feature/search/search/SearchRoute.kt b/feature/src/main/java/com/terning/feature/search/search/SearchRoute.kt index 17becd309..f554ba8eb 100644 --- a/feature/src/main/java/com/terning/feature/search/search/SearchRoute.kt +++ b/feature/src/main/java/com/terning/feature/search/search/SearchRoute.kt @@ -10,9 +10,15 @@ import androidx.compose.material3.HorizontalDivider 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.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.LocalLifecycleOwner +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.flowWithLifecycle import androidx.navigation.NavHostController import com.terning.core.designsystem.component.textfield.SearchTextField import com.terning.core.designsystem.component.topappbar.LogoTopAppBar @@ -20,6 +26,8 @@ import com.terning.core.designsystem.theme.Black import com.terning.core.designsystem.theme.Grey100 import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.extension.noRippleClickable +import com.terning.core.state.UiState +import com.terning.domain.entity.response.InternshipAnnouncement import com.terning.feature.R import com.terning.feature.search.search.component.ImageSlider import com.terning.feature.search.search.component.InternListType @@ -29,16 +37,46 @@ import com.terning.feature.search.searchprocess.navigation.navigateSearchProcess @Composable fun SearchRoute( navController: NavHostController, + viewModel: SearchViewModel = hiltViewModel(), ) { - SearchScreen( - navController = navController - ) + val lifecycleOwner = LocalLifecycleOwner.current + + val state by viewModel.state.collectAsStateWithLifecycle(lifecycleOwner = lifecycleOwner) + + LaunchedEffect(key1 = true) { + viewModel.getSearchViews() + } + + LaunchedEffect(viewModel.sideEffect, lifecycleOwner) { + viewModel.sideEffect.flowWithLifecycle(lifecycle = lifecycleOwner.lifecycle) + .collect { sideEffect -> + when (sideEffect) { + is SearchViewsSideEffect.Toast -> { + sideEffect.message + } + } + } + } + + when (state.searchViewsList) { + is UiState.Loading -> {} + is UiState.Empty -> {} + is UiState.Failure -> {} + is UiState.Success -> { + SearchScreen( + navController = navController, + searchViewsList = (state.searchViewsList as UiState.Success>).data + ) + } + + } } @Composable fun SearchScreen( modifier: Modifier = Modifier, navController: NavHostController, + searchViewsList: List, ) { val images = listOf( R.drawable.ic_nav_search, @@ -91,13 +129,21 @@ fun SearchScreen( color = Black ) - SearchInternList(type = InternListType.VIEW) + SearchInternList( + type = InternListType.VIEW, + searchViewsList = searchViewsList, + navController = navController + ) HorizontalDivider( thickness = 4.dp, modifier = Modifier.padding(vertical = 8.dp), color = Grey100, ) - SearchInternList(type = InternListType.SCRAP) + SearchInternList( + type = InternListType.SCRAP, + searchViewsList = searchViewsList, + navController = navController + ) } } } diff --git a/feature/src/main/java/com/terning/feature/search/search/SearchViewModel.kt b/feature/src/main/java/com/terning/feature/search/search/SearchViewModel.kt new file mode 100644 index 000000000..d99b6894b --- /dev/null +++ b/feature/src/main/java/com/terning/feature/search/search/SearchViewModel.kt @@ -0,0 +1,42 @@ +package com.terning.feature.search.search + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.terning.core.state.UiState +import com.terning.domain.repository.SearchRepository +import com.terning.feature.R +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class SearchViewModel @Inject constructor( + private val searchRepository: SearchRepository, +) : ViewModel() { + private val _state: MutableStateFlow = MutableStateFlow(SearchViewsState()) + val state: StateFlow = _state.asStateFlow() + + private val _sideEffect: MutableSharedFlow = MutableSharedFlow() + val sideEffect = _sideEffect.asSharedFlow() + + init { + getSearchViews() + } + + fun getSearchViews() { + viewModelScope.launch { + searchRepository.getSearchViewsList().onSuccess { searchViewsList -> + _state.value = _state.value.copy( + searchViewsList = UiState.Success(searchViewsList) + ) + }.onFailure { + _sideEffect.emit(SearchViewsSideEffect.Toast(R.string.server_failure)) + } + } + } +} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/search/search/SearchViewsSideEffect.kt b/feature/src/main/java/com/terning/feature/search/search/SearchViewsSideEffect.kt new file mode 100644 index 000000000..208b1fad3 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/search/search/SearchViewsSideEffect.kt @@ -0,0 +1,7 @@ +package com.terning.feature.search.search + +import androidx.annotation.StringRes + +sealed class SearchViewsSideEffect { + data class Toast(@StringRes val message: Int) : SearchViewsSideEffect() +} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/search/search/SearchViewsState.kt b/feature/src/main/java/com/terning/feature/search/search/SearchViewsState.kt new file mode 100644 index 000000000..d9cf41ed8 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/search/search/SearchViewsState.kt @@ -0,0 +1,8 @@ +package com.terning.feature.search.search + +import com.terning.core.state.UiState +import com.terning.domain.entity.response.InternshipAnnouncement + +data class SearchViewsState( + var searchViewsList: UiState> = UiState.Loading, +) \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/search/search/component/SearchIntern.kt b/feature/src/main/java/com/terning/feature/search/search/component/SearchIntern.kt index e2b6109f5..96e1c551a 100644 --- a/feature/src/main/java/com/terning/feature/search/search/component/SearchIntern.kt +++ b/feature/src/main/java/com/terning/feature/search/search/component/SearchIntern.kt @@ -1,29 +1,40 @@ package com.terning.feature.search.search.component -import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -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.wrapContentSize import androidx.compose.foundation.shape.RoundedCornerShape 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.shadow -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource +import androidx.compose.ui.draw.clip +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import androidx.navigation.NavHostController +import coil.compose.AsyncImage +import coil.request.ImageRequest import com.terning.core.designsystem.theme.Black -import com.terning.core.designsystem.theme.Grey400 import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.designsystem.theme.White +import com.terning.core.extension.customShadow +import com.terning.core.extension.noRippleClickable +import com.terning.domain.entity.response.InternshipAnnouncement import com.terning.feature.R +import com.terning.feature.intern.navigation.navigateIntern @Composable -fun SearchIntern() { +fun SearchIntern( + searchViews: InternshipAnnouncement, + navController: NavHostController, +) { Column( verticalArrangement = Arrangement.spacedBy( 10.dp, @@ -31,29 +42,40 @@ fun SearchIntern() { ), horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier - .shadow( - elevation = 4.dp, - // TODO 효빈 그림자 PR 풀 받아서 바꾸기 - spotColor = Color(0x26DDDDDD), - ambientColor = Color(0x26DDDDDD) - ) + .width(140.dp) .background( color = White, shape = RoundedCornerShape(size = 5.dp) ) .padding(vertical = 8.dp) + .noRippleClickable { + navController.navigateIntern() + } ) { - Image( - painter = painterResource(id = R.drawable.ic_nav_search), - contentDescription = null, + AsyncImage( + model = ImageRequest.Builder(LocalContext.current) + .data(searchViews.companyImage) + .crossfade(true) + .build(), + contentDescription = stringResource(id = R.string.search_image), + contentScale = ContentScale.Crop, modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - .background(Grey400) + .height(76.dp) + .customShadow(offsetY = 3.dp) + .wrapContentSize() + .clip( + RoundedCornerShape( + topStart = 5.dp, + topEnd = 5.dp + ) + ) ) + Text( - text = "[유한킴벌리]\n그린캠프 w. 대학생 숲 \n활동가 모집", - modifier = Modifier.padding(horizontal = 8.dp), + text = "${searchViews.title} ${searchViews.title}${searchViews.title}${searchViews.title}", + modifier = Modifier + .padding(horizontal = 8.dp) + .wrapContentSize(), style = TerningTheme.typography.body6, color = Black, overflow = TextOverflow.Ellipsis, diff --git a/feature/src/main/java/com/terning/feature/search/search/component/SearchInternList.kt b/feature/src/main/java/com/terning/feature/search/search/component/SearchInternList.kt index 0060685c0..f8abf167e 100644 --- a/feature/src/main/java/com/terning/feature/search/search/component/SearchInternList.kt +++ b/feature/src/main/java/com/terning/feature/search/search/component/SearchInternList.kt @@ -9,13 +9,17 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.navigation.NavHostController import com.terning.core.designsystem.theme.Grey400 import com.terning.core.designsystem.theme.TerningTheme +import com.terning.domain.entity.response.InternshipAnnouncement import com.terning.feature.R @Composable fun SearchInternList( type: InternListType, + searchViewsList: List, + navController: NavHostController ) { Column(modifier = Modifier.padding(horizontal = 24.dp)) { Text( @@ -33,8 +37,11 @@ fun SearchInternList( modifier = Modifier.padding(vertical = 8.dp), horizontalArrangement = Arrangement.spacedBy(12.dp), ) { - items(5) { - SearchIntern() + items(searchViewsList.size) { index -> + SearchIntern( + searchViews = searchViewsList[index], + navController = navController + ) } } } diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index d89353a51..bd05dff4f 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -2,8 +2,8 @@ Terning-Android - 서버통신 성공 - 서버통신 실패 + 서버통신에 성공했어요 + 서버통신에 실패했어요 @@ -31,6 +31,7 @@ 관심있는 인턴 공고 키워드를 검색해 보세요 요즘 대학생들에게 인기 있는 공고 지금 조회수가 많은 공고들이에요 + 공고 이미지 지금 스크랩수가 많은 공고들이에요