Skip to content

Commit 42fdaae

Browse files
authored
Merge pull request #458 from BCSDLab/feature/timetable_api_v2
[Feature] 시간표 로그인 기능 구현
2 parents cff1b23 + 1ecadc4 commit 42fdaae

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1286
-262
lines changed

data/src/main/java/in/koreatech/koin/data/api/auth/TimetableAuthApi.kt

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package `in`.koreatech.koin.data.api.auth
22

3+
import `in`.koreatech.koin.data.request.timetable.LecturesQueryRequest
34
import `in`.koreatech.koin.data.request.timetable.TimetableFrameCreateQueryRequest
45
import `in`.koreatech.koin.data.request.timetable.TimetableFrameQueryRequest
56
import `in`.koreatech.koin.data.request.timetable.TimetableLecturesQueryRequest
7+
import `in`.koreatech.koin.data.response.timetable.SemesterCheckResponse
68
import `in`.koreatech.koin.data.response.timetable.TimetableFrameResponse
79
import `in`.koreatech.koin.data.response.timetable.TimetableLecturesResponse
10+
import retrofit2.Response
811
import retrofit2.http.Body
912
import retrofit2.http.DELETE
1013
import retrofit2.http.GET
@@ -14,6 +17,9 @@ import retrofit2.http.Path
1417
import retrofit2.http.Query
1518

1619
interface TimetableAuthApi {
20+
@GET("/semesters/check")
21+
suspend fun getSemestersCheck(): SemesterCheckResponse
22+
1723
@GET("/v2/timetables/lecture")
1824
suspend fun getTimetableLectures(
1925
@Query("timetable_frame_id") timetableFrameId: Int
@@ -26,7 +32,7 @@ interface TimetableAuthApi {
2632

2733
@POST("/v2/timetables/lecture")
2834
suspend fun postTimetableLectures(
29-
@Body lectures: TimetableLecturesQueryRequest
35+
@Body lectures: LecturesQueryRequest
3036
): TimetableLecturesResponse
3137

3238
@PUT("/v2/timetables/frame/{id}")
@@ -43,7 +49,7 @@ interface TimetableAuthApi {
4349
@DELETE("/v2/timetables/frame")
4450
suspend fun deleteTimetableFrame()
4551

46-
@GET("/v2/timetables/frame")
52+
@GET("/v2/timetables/frames")
4753
suspend fun getTimetableFrames(
4854
@Query("semester") semester: String
4955
): List<TimetableFrameResponse>
@@ -53,6 +59,17 @@ interface TimetableAuthApi {
5359
@Path("id") id: Int
5460
)
5561

62+
@DELETE("/v2/timetables/frame/{frameId}/lecture/{lectureId}")
63+
suspend fun deleteTimetableFrameLecture(
64+
@Path("frameId") frameId: Int,
65+
@Path("lectureId") lectureId: Int
66+
): Response<Unit>
67+
68+
@DELETE("/v2/timetables/lectures")
69+
suspend fun deleteTimetableLectures(
70+
@Query("timetable_lecture_ids") lectureIds : List<Int>
71+
): Response<Unit>
72+
5673
@DELETE("/v2/all/timetables/frame")
5774
suspend fun deleteAllTimetableFrame()
5875
}

data/src/main/java/in/koreatech/koin/data/repository/TimetableRepositoryImpl.kt

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@ package `in`.koreatech.koin.data.repository
22

33
import com.google.gson.Gson
44
import com.google.gson.reflect.TypeToken
5+
import `in`.koreatech.koin.data.request.timetable.LecturesQueryRequest
6+
import `in`.koreatech.koin.data.request.timetable.toLectureQueryRequest
57
import `in`.koreatech.koin.data.request.timetable.toTimetableLecturesQueryRequest
68
import `in`.koreatech.koin.data.source.datastore.TimetableDataStore
79
import `in`.koreatech.koin.data.source.remote.TimetableRemoteDataSource
810
import `in`.koreatech.koin.domain.model.timetable.request.TimetableFrameCreateQuery
911
import `in`.koreatech.koin.domain.model.timetable.request.TimetableFrameQuery
1012
import `in`.koreatech.koin.domain.model.timetable.request.TimetableLecturesQuery
1113
import `in`.koreatech.koin.domain.model.timetable.response.Lecture
12-
import `in`.koreatech.koin.domain.model.timetable.response.Semester
1314
import `in`.koreatech.koin.domain.model.timetable.response.TimetableFrame
1415
import `in`.koreatech.koin.domain.model.timetable.response.TimetableLectures
1516
import `in`.koreatech.koin.domain.repository.TimetableRepository
1617
import kotlinx.coroutines.flow.Flow
1718
import kotlinx.coroutines.flow.firstOrNull
1819
import kotlinx.coroutines.flow.flow
19-
import java.lang.NullPointerException
2020
import javax.inject.Inject
2121

2222
class TimetableRepositoryImpl @Inject constructor(
@@ -25,8 +25,12 @@ class TimetableRepositoryImpl @Inject constructor(
2525
) : TimetableRepository {
2626
private val gson = Gson()
2727

28-
override fun getSemesters(): Flow<List<Semester>> = flow {
29-
emit(timetableRemoteDataSource.getSemesters().map { it.toSemester() })
28+
override fun getSemesters(): Flow<List<String>> = flow {
29+
emit(timetableRemoteDataSource.getSemesters().map { it.toSemester().semester })
30+
}
31+
32+
override fun getSemesterCheck(): Flow<List<String>> = flow {
33+
emit(timetableRemoteDataSource.getSemesterCheck().toSemesterCheck().semesters)
3034
}
3135

3236
override fun getLectures(semesterDate: String): Flow<List<Lecture>> = flow {
@@ -52,8 +56,7 @@ class TimetableRepositoryImpl @Inject constructor(
5256
}
5357

5458
override suspend fun putTimetableLectures(lectures: TimetableLecturesQuery): TimetableLectures =
55-
timetableRemoteDataSource.postTimetableLectures(lectures.toTimetableLecturesQueryRequest())
56-
.toTimetableLectures()
59+
timetableRemoteDataSource.putTimetableLectures(lectures.toTimetableLecturesQueryRequest()).toTimetableLectures()
5760

5861
override suspend fun putTimetableLectures(key: String, value: TimetableLectures): Result<TimetableLectures> = runCatching {
5962
timetableDataStore.putString(key, gson.toJson(value))
@@ -68,8 +71,11 @@ class TimetableRepositoryImpl @Inject constructor(
6871
TODO("Not yet implemented")
6972
}
7073

71-
override suspend fun postTimetableLectures(lectures: TimetableLecturesQuery): TimetableLectures {
72-
TODO("Not yet implemented")
74+
override suspend fun postTimetableLectures(frameId: Int, lectures: List<Lecture>): Result<TimetableLectures> = runCatching {
75+
timetableRemoteDataSource.postTimetableLectures(LecturesQueryRequest(
76+
timetableFrameId = frameId,
77+
timetableLecture = lectures.map { it.toLectureQueryRequest() }
78+
)).toTimetableLectures()
7379
}
7480

7581

@@ -81,8 +87,16 @@ class TimetableRepositoryImpl @Inject constructor(
8187
TODO("Not yet implemented")
8288
}
8389

84-
override suspend fun deleteTimetableLecture(id: Int) {
85-
TODO("Not yet implemented")
90+
override suspend fun deleteTimetableLecture(id: Int): Result<Unit> = runCatching {
91+
timetableRemoteDataSource.deleteTimetableLecture(id)
92+
}
93+
94+
override suspend fun deleteTimetableFrameLecture(frameId: Int, lectureId: Int): Result<Unit> = runCatching {
95+
timetableRemoteDataSource.deleteTimetableFrameLecture(frameId, lectureId)
96+
}
97+
98+
override suspend fun deleteTimetableLectures(lectureIds: List<Int>): Result<Unit> = runCatching {
99+
timetableRemoteDataSource.deleteTimetableLectures(lectureIds)
86100
}
87101

88102
override suspend fun deleteAllTimetableFrame() {
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package `in`.koreatech.koin.data.request.timetable
2+
3+
import com.google.gson.annotations.SerializedName
4+
import `in`.koreatech.koin.domain.model.timetable.response.Lecture
5+
6+
data class LecturesQueryRequest(
7+
@SerializedName("timetable_frame_id")
8+
val timetableFrameId: Int,
9+
@SerializedName("timetable_lecture")
10+
val timetableLecture: List<LectureQueryRequest>,
11+
)
12+
13+
data class LectureQueryRequest(
14+
@SerializedName("lecture_id")
15+
val lectureId: Int?,
16+
@SerializedName("class_title")
17+
val classTitle: String,
18+
@SerializedName("class_time")
19+
val classTime: List<Int>,
20+
@SerializedName("class_place")
21+
val classPlace: String,
22+
@SerializedName("professor")
23+
val professor: String,
24+
@SerializedName("grades")
25+
val grades: String,
26+
@SerializedName("memo")
27+
val memo: String,
28+
)
29+
30+
fun Lecture.toLectureQueryRequest() = LectureQueryRequest(
31+
lectureId = id,
32+
classTitle = name,
33+
classTime = classTime,
34+
classPlace = "",
35+
professor = professor,
36+
grades = grades,
37+
memo = ""
38+
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package `in`.koreatech.koin.data.response.timetable
2+
3+
import com.google.gson.annotations.SerializedName
4+
import `in`.koreatech.koin.domain.model.timetable.response.SemesterCheck
5+
6+
data class SemesterCheckResponse(
7+
@SerializedName("user_id")
8+
val userId: Int,
9+
@SerializedName("semesters")
10+
val semesters: List<String>,
11+
) {
12+
fun toSemesterCheck() = SemesterCheck(
13+
userId = userId,
14+
semesters = semesters
15+
)
16+
}

data/src/main/java/in/koreatech/koin/data/source/remote/TimetableRemoteDataSource.kt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package `in`.koreatech.koin.data.source.remote
22

33
import `in`.koreatech.koin.data.api.TimetableApi
44
import `in`.koreatech.koin.data.api.auth.TimetableAuthApi
5+
import `in`.koreatech.koin.data.request.timetable.LecturesQueryRequest
56
import `in`.koreatech.koin.data.request.timetable.TimetableFrameCreateQueryRequest
67
import `in`.koreatech.koin.data.request.timetable.TimetableFrameQueryRequest
78
import `in`.koreatech.koin.data.request.timetable.TimetableLecturesQueryRequest
89
import `in`.koreatech.koin.data.response.timetable.LectureResponse
10+
import `in`.koreatech.koin.data.response.timetable.SemesterCheckResponse
911
import `in`.koreatech.koin.data.response.timetable.SemesterResponse
1012
import `in`.koreatech.koin.data.response.timetable.TimetableFrameResponse
1113
import `in`.koreatech.koin.data.response.timetable.TimetableLecturesResponse
@@ -17,6 +19,8 @@ class TimetableRemoteDataSource @Inject constructor(
1719
) {
1820
suspend fun getSemesters(): List<SemesterResponse> = timetableApi.getSemesters()
1921

22+
suspend fun getSemesterCheck(): SemesterCheckResponse = timetableAuthApi.getSemestersCheck()
23+
2024
suspend fun getLectures(semesterDate: String): List<LectureResponse> =
2125
timetableApi.getLectures(semesterDate)
2226

@@ -36,7 +40,7 @@ class TimetableRemoteDataSource @Inject constructor(
3640
): TimetableFrameResponse = timetableAuthApi.putTimetableFrame(id, frame)
3741

3842
suspend fun postTimetableLectures(
39-
lectures: TimetableLecturesQueryRequest
43+
lectures: LecturesQueryRequest
4044
): TimetableLecturesResponse = timetableAuthApi.postTimetableLectures(lectures)
4145

4246

@@ -51,5 +55,14 @@ class TimetableRemoteDataSource @Inject constructor(
5155
id: Int
5256
) = timetableAuthApi.deleteTimetableLecture(id)
5357

58+
suspend fun deleteTimetableFrameLecture(
59+
frameId: Int,
60+
lectureId: Int
61+
) = timetableAuthApi.deleteTimetableFrameLecture(frameId, lectureId)
62+
63+
suspend fun deleteTimetableLectures(
64+
lectureIds: List<Int>
65+
) = timetableAuthApi.deleteTimetableLectures(lectureIds)
66+
5467
suspend fun deleteAllTimetableFrame() = timetableAuthApi.deleteAllTimetableFrame()
5568
}

domain/src/main/java/in/koreatech/koin/domain/model/timetable/response/Lecture.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ data class Lecture(
2020
) {
2121
fun toTimetableLecture() = TimetableLecture(
2222
id = id,
23-
lectureId = 0,
23+
lectureId = id,
2424
regularNumber = regularNumber,
2525
code = code,
2626
designScore = designScore,
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package `in`.koreatech.koin.domain.model.timetable.response
2+
3+
data class SemesterCheck(
4+
val userId: Int,
5+
val semesters: List<String>
6+
)

domain/src/main/java/in/koreatech/koin/domain/repository/TimetableRepository.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import `in`.koreatech.koin.domain.model.timetable.request.TimetableFrameCreateQu
44
import `in`.koreatech.koin.domain.model.timetable.request.TimetableFrameQuery
55
import `in`.koreatech.koin.domain.model.timetable.request.TimetableLecturesQuery
66
import `in`.koreatech.koin.domain.model.timetable.response.Lecture
7-
import `in`.koreatech.koin.domain.model.timetable.response.Semester
87
import `in`.koreatech.koin.domain.model.timetable.response.TimetableFrame
98
import `in`.koreatech.koin.domain.model.timetable.response.TimetableLectures
109
import kotlinx.coroutines.flow.Flow
1110

1211
interface TimetableRepository {
13-
fun getSemesters(): Flow<List<Semester>>
12+
fun getSemesters(): Flow<List<String>>
13+
fun getSemesterCheck(): Flow<List<String>>
1414
fun getLectures(semesterDate: String): Flow<List<Lecture>>
1515
fun getTimetableFrames(semester: String): Flow<List<TimetableFrame>>
1616

@@ -21,10 +21,13 @@ interface TimetableRepository {
2121
suspend fun putTimetableLectures(key: String, value: TimetableLectures): Result<TimetableLectures>
2222
suspend fun putTimetableFrame(id: Int, frame: TimetableFrameQuery): TimetableFrame
2323

24-
suspend fun postTimetableLectures(lectures: TimetableLecturesQuery): TimetableLectures
24+
suspend fun postTimetableLectures(frameId: Int, lectures: List<Lecture>): Result<TimetableLectures>
2525
suspend fun postTimetableFrame(frame: TimetableFrameCreateQuery): TimetableFrame
2626

2727
suspend fun deleteTimetableFrame()
28-
suspend fun deleteTimetableLecture(id: Int)
28+
suspend fun deleteTimetableLecture(id: Int): Result<Unit>
29+
suspend fun deleteTimetableLectures(lectureIds: List<Int>): Result<Unit>
30+
suspend fun deleteTimetableFrameLecture(frameId: Int, lectureId: Int): Result<Unit>
31+
2932
suspend fun deleteAllTimetableFrame()
3033
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package `in`.koreatech.koin.domain.usecase.timetable
2+
3+
import `in`.koreatech.koin.domain.model.timetable.response.Lecture
4+
import `in`.koreatech.koin.domain.model.timetable.response.TimetableLectures
5+
import `in`.koreatech.koin.domain.repository.TimetableRepository
6+
import javax.inject.Inject
7+
8+
class AddTimetableLectureUseCase @Inject constructor(
9+
private val timetableRepository: TimetableRepository
10+
) {
11+
suspend operator fun invoke(frameId: Int, lectures: List<Lecture>): Result<TimetableLectures> {
12+
return timetableRepository.postTimetableLectures(frameId, lectures)
13+
}
14+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package `in`.koreatech.koin.domain.usecase.timetable
2+
3+
import `in`.koreatech.koin.domain.repository.TimetableRepository
4+
import javax.inject.Inject
5+
6+
class DeleteTimetableFrameLectureUseCase @Inject constructor(
7+
private val timetableRepository: TimetableRepository
8+
) {
9+
suspend operator fun invoke(frameId: Int, lectureId: Int): Result<Unit> {
10+
return timetableRepository.deleteTimetableFrameLecture(frameId, lectureId)
11+
}
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package `in`.koreatech.koin.domain.usecase.timetable
2+
3+
import `in`.koreatech.koin.domain.repository.TimetableRepository
4+
import javax.inject.Inject
5+
6+
class DeleteTimetableLectureUseCase @Inject constructor(
7+
private val timetableRepository: TimetableRepository
8+
) {
9+
suspend operator fun invoke(id: Int): Result<Unit> {
10+
return timetableRepository.deleteTimetableLecture(id)
11+
}
12+
}
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
package `in`.koreatech.koin.domain.usecase.timetable
22

3-
import `in`.koreatech.koin.domain.model.timetable.response.Semester
43
import `in`.koreatech.koin.domain.repository.TimetableRepository
54
import kotlinx.coroutines.flow.Flow
65
import javax.inject.Inject
76

87
class GetSemesterUseCase @Inject constructor(
98
private val timetableRepository: TimetableRepository
109
) {
11-
operator fun invoke(): Flow<List<Semester>> =
12-
timetableRepository.getSemesters()
10+
operator fun invoke(isAnonymous: Boolean): Flow<List<String>> =
11+
if (isAnonymous) timetableRepository.getSemesters() else timetableRepository.getSemesterCheck()
1312
}

feature/timetable/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ dependencies {
2727
implementation(platform(libs.compose.bom))
2828
implementation(libs.compose.material2)
2929
implementation(libs.bundles.compose.m3)
30+
implementation(libs.kotlinxCollectionsImmutable)
3031

3132
implementation(libs.timber)
3233

feature/timetable/src/main/java/in/koreatech/koin/feature/timetable/component/LectureBox.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ fun LectureBox(
5050
derivedStateOf { selectedLecture == lecture }
5151
}
5252
val isAdded by remember(lecture, timetableEvents) {
53-
derivedStateOf { timetableEvents.any {lecture.id == it.id} }
53+
derivedStateOf { timetableEvents.any {lecture.id == it.lectureId} }
5454
}
5555

5656
Row(

0 commit comments

Comments
 (0)