diff --git a/.idea/androidTestResultsUserPreferences.xml b/.idea/androidTestResultsUserPreferences.xml
index 4cdeb5e9..eff1f9a8 100644
--- a/.idea/androidTestResultsUserPreferences.xml
+++ b/.idea/androidTestResultsUserPreferences.xml
@@ -3,6 +3,45 @@
diff --git a/app/src/main/java/com/eshc/goonersapp/navigation/GnrNavHost.kt b/app/src/main/java/com/eshc/goonersapp/navigation/GnrNavHost.kt
index 56cfee68..8360656d 100644
--- a/app/src/main/java/com/eshc/goonersapp/navigation/GnrNavHost.kt
+++ b/app/src/main/java/com/eshc/goonersapp/navigation/GnrNavHost.kt
@@ -19,7 +19,7 @@ import com.eshc.goonersapp.feature.team.navigation.clubDetailScreen
import com.eshc.goonersapp.feature.match.navigation.navigateToMatchDetail
import com.eshc.goonersapp.feature.team.navigation.navigateToPlayerDetail
import com.eshc.goonersapp.feature.team.navigation.playerDetailScreen
-import com.eshc.goonersapp.feature.team.navigation.teamHistoryScreen
+import com.eshc.goonersapp.feature.team.navigation.teamSearchScreen
import com.eshc.goonersapp.feature.team.navigation.teamScreen
const val mainNavigationRoute = "main_route"
@@ -71,35 +71,40 @@ fun GnrNavHost(
}
playerDetailScreen(
+ onBackIconClick = { navController.popBackStack() },
onShowSnackbar = onShowSnackbar
)
matchDetailScreen(
- onClickChat = {
- navController.navigateToChatRoom(it)
- },
+ onClickChat = { navController.navigateToChatRoom(it) },
+ onBackIconClick = { navController.popBackStack() },
onShowSnackbar = onShowSnackbar
)
- teamHistoryScreen(
- onPlayerClick = {
- navController.navigateToPlayerDetail(it)
- },
+
+ teamSearchScreen(
+ onPlayerClick = { navController.navigateToPlayerDetail(it) },
+ onBackIconClick = { navController.popBackStack() },
onShowSnackbar = onShowSnackbar
)
+
chatRoomScreen(
onShowSnackbar = onShowSnackbar
)
+
clubDetailScreen(
+ onBackIconClick = { navController.popBackStack() },
onShowSnackbar = onShowSnackbar
)
+
loginScreen(
onShowSnackbar = onShowSnackbar,
- onClickSignUp = {
- navController.navigateToSignUp()
- }
+ onClickSignUp = { navController.navigateToSignUp() },
+ onBackIconClick = { navController.popBackStack() }
)
+
signUpScreen(
- onShowSnackbar = onShowSnackbar
+ onShowSnackbar = onShowSnackbar,
+ onBackIconClick = { navController.popBackStack() }
)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/eshc/goonersapp/navigation/TopLevelDestination.kt b/app/src/main/java/com/eshc/goonersapp/navigation/TopLevelDestination.kt
index d86b8b66..bc0d921a 100644
--- a/app/src/main/java/com/eshc/goonersapp/navigation/TopLevelDestination.kt
+++ b/app/src/main/java/com/eshc/goonersapp/navigation/TopLevelDestination.kt
@@ -15,9 +15,9 @@ import com.eshc.goonersapp.feature.home.R as home
import com.eshc.goonersapp.feature.match.R as match
import com.eshc.goonersapp.feature.team.R as team
-val topLevelDestinationSet = TopLevelDestination.entries.map {
- it.route
-}.toSet()
+val topLevelDestinationSet = TopLevelDestination.entries
+ .map { destination -> destination.route }
+ .toSet()
enum class TopLevelDestination(
val selectedIcon: ImageVector,
diff --git a/app/src/main/java/com/eshc/goonersapp/ui/GnrApp.kt b/app/src/main/java/com/eshc/goonersapp/ui/GnrApp.kt
index e87d2356..0be01ef1 100644
--- a/app/src/main/java/com/eshc/goonersapp/ui/GnrApp.kt
+++ b/app/src/main/java/com/eshc/goonersapp/ui/GnrApp.kt
@@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.widthIn
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarDuration
@@ -18,7 +17,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -32,18 +30,21 @@ import com.eshc.goonersapp.core.data.util.NetworkConnectivityManager
import com.eshc.goonersapp.core.designsystem.IconPack
import com.eshc.goonersapp.core.designsystem.component.GnrNavigationBar
import com.eshc.goonersapp.core.designsystem.component.GnrNavigationBarItem
-import com.eshc.goonersapp.core.designsystem.component.TopLevelTopBar
+import com.eshc.goonersapp.core.designsystem.component.GnrTopLevelTopBar
import com.eshc.goonersapp.core.designsystem.iconpack.IcInfo
+import com.eshc.goonersapp.core.designsystem.iconpack.IcNotification
+import com.eshc.goonersapp.core.designsystem.iconpack.IcPeople
import com.eshc.goonersapp.core.designsystem.iconpack.IcSearch
-import com.eshc.goonersapp.core.designsystem.iconpack.IcUser
import com.eshc.goonersapp.core.designsystem.theme.ColorFF181818
+import com.eshc.goonersapp.core.designsystem.theme.ColorFF777777
+import com.eshc.goonersapp.core.designsystem.theme.ColorFF9E9E9E
import com.eshc.goonersapp.core.designsystem.theme.GnrTypography
import com.eshc.goonersapp.feature.home.navigation.navigateToHome
import com.eshc.goonersapp.feature.login.navigation.navigateToLogin
import com.eshc.goonersapp.feature.match.navigation.navigateToMatch
import com.eshc.goonersapp.feature.team.navigation.navigateToClubDetail
import com.eshc.goonersapp.feature.team.navigation.navigateToTeam
-import com.eshc.goonersapp.feature.team.navigation.navigateToTeamHistory
+import com.eshc.goonersapp.feature.team.navigation.navigateToSearch
import com.eshc.goonersapp.navigation.GnrNavHost
import com.eshc.goonersapp.navigation.TopLevelDestination
import kotlinx.coroutines.launch
@@ -96,9 +97,8 @@ fun GnrApp(
modifier = Modifier
.padding(horizontal = 8.dp)
.size(24.dp)
- .clickable {
- navController.navigateToClubDetail()
- }
+ .clickable { navController.navigateToClubDetail() },
+ tint = ColorFF777777
)
Icon(
imageVector = IconPack.IcSearch,
@@ -106,27 +106,49 @@ fun GnrApp(
modifier = Modifier
.padding(horizontal = 8.dp)
.size(24.dp)
- .clickable {
- navController.navigateToTeamHistory()
- }
+ .clickable { navController.navigateToSearch() },
+ tint = ColorFF777777
)
}
TopLevelDestination.HOME -> {
Icon(
- imageVector = IconPack.IcUser,
+ imageVector = IconPack.IcNotification,
+ contentDescription = null,
+ modifier = Modifier
+ .padding(horizontal = 8.dp)
+ .size(24.dp),
+ tint = ColorFF777777
+ )
+ Icon(
+ imageVector = IconPack.IcPeople,
contentDescription = null,
modifier = Modifier
.padding(horizontal = 8.dp)
.size(24.dp)
- .clickable {
- navController.navigateToLogin()
- }
+ .clickable { navController.navigateToLogin() },
+ tint = ColorFF777777
)
}
else -> {
-
+ Icon(
+ imageVector = IconPack.IcNotification,
+ contentDescription = null,
+ modifier = Modifier
+ .padding(horizontal = 8.dp)
+ .size(24.dp),
+ tint = ColorFF777777
+ )
+ Icon(
+ imageVector = IconPack.IcPeople,
+ contentDescription = null,
+ modifier = Modifier
+ .padding(horizontal = 8.dp)
+ .size(24.dp)
+ .clickable { navController.navigateToLogin() },
+ tint = ColorFF777777
+ )
}
}
}
@@ -172,9 +194,9 @@ fun GnrTopLevelBar(
topLevelDestination: TopLevelDestination,
icons: @Composable () -> Unit
) {
- TopLevelTopBar(
+ GnrTopLevelTopBar(
modifier = Modifier.padding(horizontal = 8.dp),
- title = topLevelDestination.name
+ title = stringResource(id = topLevelDestination.titleTextId)
) {
icons()
}
@@ -200,15 +222,19 @@ fun GnrBottomBar(
},
icon = {
Icon(
- modifier = Modifier.padding(bottom = 4.dp).heightIn(max = 18.dp),
+ modifier = Modifier
+ .padding(bottom = 4.dp)
+ .heightIn(max = 18.dp),
imageVector = destination.unselectedIcon,
- tint = Color(0xFF888888),
+ tint = ColorFF9E9E9E,
contentDescription = null,
)
},
selectedIcon = {
Icon(
- modifier = Modifier.padding(bottom = 4.dp).heightIn(max = 18.dp),
+ modifier = Modifier
+ .padding(bottom = 4.dp)
+ .heightIn(max = 18.dp),
imageVector = destination.selectedIcon,
contentDescription = null,
)
@@ -217,7 +243,7 @@ fun GnrBottomBar(
Text(
text = stringResource(id = destination.iconTextId),
style = GnrTypography.body2Regular.copy(
- color = if(selected) ColorFF181818 else Color(0xFF888888)
+ color = if(selected) ColorFF181818 else ColorFF9E9E9E
)
)
}
diff --git a/core/common/src/main/java/com/eshc/goonersapp/core/common/util/DateUtil.kt b/core/common/src/main/java/com/eshc/goonersapp/core/common/util/DateUtil.kt
index 35d01769..3140690c 100644
--- a/core/common/src/main/java/com/eshc/goonersapp/core/common/util/DateUtil.kt
+++ b/core/common/src/main/java/com/eshc/goonersapp/core/common/util/DateUtil.kt
@@ -3,41 +3,56 @@ package com.eshc.goonersapp.core.common.util
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
+import java.util.Locale
const val DefaultDatePattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
object DateUtil {
private val defaultDateFormat = DateTimeFormatter.ofPattern(DefaultDatePattern)
- fun getYearAndMonthString(date : String ) : String {
- if(date.isBlank()) return date
- return LocalDate.parse(date, defaultDateFormat).format(DateTimeFormatter.ofPattern("yyyy.MM"))
+ fun getYearAndMonthString(date: String): String {
+ if (date.isBlank()) return date
+ return LocalDate.parse(date, defaultDateFormat)
+ .format(DateTimeFormatter.ofPattern("yyyy.MM"))
+ }
+
+ fun getYearAndMonthAndDateString(date: String): String {
+ if (date.isBlank()) return date
+ return LocalDate.parse(date, defaultDateFormat)
+ .format(DateTimeFormatter.ofPattern("yyyy.MM.dd"))
}
- fun getYearAndMonthAndDateString(date : String ) : String {
- if(date.isBlank()) return date
- return LocalDate.parse(date, defaultDateFormat).format(DateTimeFormatter.ofPattern("yyyy.MM.dd"))
+ fun getYearAndMonthAndDateAndTimeString(date: String): String {
+ if (date.isBlank()) return date
+ return LocalDateTime.parse(date, defaultDateFormat)
+ .format(DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm"))
}
- fun getYearAndMonthAndDateAndTimeString(date : String ) : String {
- if(date.isBlank()) return date
- return LocalDateTime.parse(date, defaultDateFormat).format(DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm"))
+ fun getYearAndMonthAndDateAndDayAndTimeString(date: String): String {
+ if (date.isBlank()) return date
+ return LocalDateTime.parse(date, defaultDateFormat).format(
+ DateTimeFormatter.ofPattern(
+ "yyyy.MM.dd E HH:mm",
+ Locale.US
+ )
+ ).uppercase()
}
- fun getYearAndMonthAndDateAndDayAndTimeString(date : String ) : String {
- if(date.isBlank()) return date
- return LocalDateTime.parse(date, defaultDateFormat).format(DateTimeFormatter.ofPattern("yyyy.MM.dd E HH:mm")).uppercase()
+ fun getMonthAndDateAndDayString(date: String): String {
+ if (date.isBlank()) return date
+ return LocalDateTime.parse(date, defaultDateFormat)
+ .format(DateTimeFormatter.ofPattern("MM.dd E", Locale.US)).uppercase()
}
- fun getYearAndMonthAndDateLocalDate(date : String ) : LocalDate {
- if(date.isBlank()) return LocalDate.now()
+ fun getYearAndMonthAndDateLocalDate(date: String): LocalDate {
+ if (date.isBlank()) return LocalDate.now()
return LocalDate.parse(date, defaultDateFormat)
}
- fun getTimeString(date: String) : String {
- if(date.isBlank()) return date
+ fun getTimeString(date: String): String {
+ if (date.isBlank()) return date
return LocalDateTime.parse(date, defaultDateFormat).let {
- "${it.hour}:" + "${it.minute}".padStart(2,'0')
+ "${it.hour}:" + "${it.minute}".padStart(2, '0')
}
}
}
\ No newline at end of file
diff --git a/core/data/src/main/java/com/eshc/goonersapp/core/data/di/DataModule.kt b/core/data/src/main/java/com/eshc/goonersapp/core/data/di/DataModule.kt
index 3e7134dc..5370c28f 100644
--- a/core/data/src/main/java/com/eshc/goonersapp/core/data/di/DataModule.kt
+++ b/core/data/src/main/java/com/eshc/goonersapp/core/data/di/DataModule.kt
@@ -3,6 +3,7 @@ package com.eshc.goonersapp.core.data.di
import com.eshc.goonersapp.core.data.repository.ChatRepositoryImpl
import com.eshc.goonersapp.core.data.repository.MatchRepositoryImpl
import com.eshc.goonersapp.core.data.repository.PlayerRepositoryImpl
+import com.eshc.goonersapp.core.data.repository.SeasonRepositoryImpl
import com.eshc.goonersapp.core.data.repository.TeamRepositoryImpl
import com.eshc.goonersapp.core.data.repository.UserRepositoryImpl
import com.eshc.goonersapp.core.data.util.NetworkConnectivityManager
@@ -10,6 +11,7 @@ import com.eshc.goonersapp.core.data.util.NetworkConnectivityManagerImpl
import com.eshc.goonersapp.core.domain.repository.ChatRepository
import com.eshc.goonersapp.core.domain.repository.MatchRepository
import com.eshc.goonersapp.core.domain.repository.PlayerRepository
+import com.eshc.goonersapp.core.domain.repository.SeasonRepository
import com.eshc.goonersapp.core.domain.repository.TeamRepository
import com.eshc.goonersapp.core.domain.repository.UserRepository
import dagger.Binds
@@ -41,6 +43,11 @@ abstract class DataModule {
teamRepository: TeamRepositoryImpl,
): TeamRepository
+ @Binds
+ abstract fun bindsSeasonRepository(
+ seasonRepository: SeasonRepositoryImpl
+ ): SeasonRepository
+
@Binds
abstract fun bindsUserRepository(
userRepository: UserRepositoryImpl,
diff --git a/core/data/src/main/java/com/eshc/goonersapp/core/data/fake/FakeMatchRepositoryImpl.kt b/core/data/src/main/java/com/eshc/goonersapp/core/data/fake/FakeMatchRepositoryImpl.kt
index 1f0930a1..7da05adb 100644
--- a/core/data/src/main/java/com/eshc/goonersapp/core/data/fake/FakeMatchRepositoryImpl.kt
+++ b/core/data/src/main/java/com/eshc/goonersapp/core/data/fake/FakeMatchRepositoryImpl.kt
@@ -6,6 +6,7 @@ import com.eshc.goonersapp.core.domain.model.DataResult
import com.eshc.goonersapp.core.domain.model.match.Match
import com.eshc.goonersapp.core.domain.model.match.MatchData
import com.eshc.goonersapp.core.domain.model.match.MatchInformation
+import com.eshc.goonersapp.core.domain.model.match.MatchLineup
import com.eshc.goonersapp.core.domain.repository.MatchRepository
import com.eshc.goonersapp.core.network.fake.FakeMatchDataSource
import kotlinx.coroutines.flow.Flow
@@ -63,4 +64,12 @@ class FakeMatchRepositoryImpl @Inject constructor(
emit(result)
}
+ override fun getMatchLineup(matchId: Int): Flow> = flow {
+ val result = fakeMatchDataSource
+ .getMatchLineup(matchId)
+ .toDataResult { remote -> remote.toModel() }
+
+ emit(result)
+ }
+
}
\ No newline at end of file
diff --git a/core/data/src/main/java/com/eshc/goonersapp/core/data/fake/FakeSeasonRepositoryImpl.kt b/core/data/src/main/java/com/eshc/goonersapp/core/data/fake/FakeSeasonRepositoryImpl.kt
new file mode 100644
index 00000000..b1b2df05
--- /dev/null
+++ b/core/data/src/main/java/com/eshc/goonersapp/core/data/fake/FakeSeasonRepositoryImpl.kt
@@ -0,0 +1,47 @@
+package com.eshc.goonersapp.core.data.fake
+
+import com.eshc.goonersapp.core.data.mapper.toDataResult
+import com.eshc.goonersapp.core.data.mapper.toModel
+import com.eshc.goonersapp.core.domain.model.DataResult
+import com.eshc.goonersapp.core.domain.model.season.League
+import com.eshc.goonersapp.core.domain.model.season.Rank
+import com.eshc.goonersapp.core.domain.model.season.Season
+import com.eshc.goonersapp.core.domain.repository.SeasonRepository
+import com.eshc.goonersapp.core.network.fake.FakeSeasonDataSource
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flow
+import javax.inject.Inject
+
+class FakeSeasonRepositoryImpl @Inject constructor(
+ private val fakeSeasonDataSource: FakeSeasonDataSource
+): SeasonRepository {
+ override fun getSeasonListByTeam(teamId: Int): Flow>> = flow {
+ val result = fakeSeasonDataSource
+ .getSeasonListByTeam(teamId)
+ .toDataResult { remote -> remote.map { it.toModel() } }
+
+ emit(result)
+ }
+
+ override fun getLeagueListAsCurrentSeasonByTeam(
+ teamId: Int
+ ): Flow>> = flow {
+ val result = fakeSeasonDataSource
+ .getLeagueListAsCurrentSeasonByTeam(teamId)
+ .toDataResult { remote -> remote.map { it.toModel() } }
+
+ emit(result)
+ }
+
+ override fun getPreviewRankListByTeamAndSeason(
+ teamId: Int,
+ seasonId: Int,
+ ): Flow>> = flow {
+ val result = fakeSeasonDataSource
+ .getPreviewRankListByTeamAndSeason(teamId, seasonId)
+ .toDataResult { remote -> remote.map { it.toModel() } }
+
+ emit(result)
+ }
+
+}
\ No newline at end of file
diff --git a/core/data/src/main/java/com/eshc/goonersapp/core/data/mapper/MatchMapper.kt b/core/data/src/main/java/com/eshc/goonersapp/core/data/mapper/MatchMapper.kt
index 39b141e3..9f4712d0 100644
--- a/core/data/src/main/java/com/eshc/goonersapp/core/data/mapper/MatchMapper.kt
+++ b/core/data/src/main/java/com/eshc/goonersapp/core/data/mapper/MatchMapper.kt
@@ -1,17 +1,22 @@
package com.eshc.goonersapp.core.data.mapper
-import com.eshc.goonersapp.core.domain.model.match.LineUp
+import com.eshc.goonersapp.core.domain.model.match.PlayerLineup
import com.eshc.goonersapp.core.domain.model.match.Match
import com.eshc.goonersapp.core.domain.model.match.MatchData
import com.eshc.goonersapp.core.domain.model.match.MatchDetail
import com.eshc.goonersapp.core.domain.model.match.MatchInformation
+import com.eshc.goonersapp.core.domain.model.match.MatchLineup
import com.eshc.goonersapp.core.domain.model.match.NotablePlayer
import com.eshc.goonersapp.core.domain.model.match.Performance
+import com.eshc.goonersapp.core.domain.model.match.TeamLineup
import com.eshc.goonersapp.core.domain.model.match.toMatchDetailType
import com.eshc.goonersapp.core.network.model.match.RemoteMatch
import com.eshc.goonersapp.core.network.model.match.RemoteMatchData
import com.eshc.goonersapp.core.network.model.match.RemoteMatchDetail
import com.eshc.goonersapp.core.network.model.match.RemoteMatchInformation
+import com.eshc.goonersapp.core.network.model.match.RemoteMatchLineup
+import com.eshc.goonersapp.core.network.model.match.RemotePlayerLineup
+import com.eshc.goonersapp.core.network.model.match.RemoteTeamLineup
/**
* [RemoteMatch] Mapper
@@ -19,6 +24,7 @@ import com.eshc.goonersapp.core.network.model.match.RemoteMatchInformation
*/
fun RemoteMatch.toModel() = Match(
id = matchId,
+ seasonId = seasonId,
homeTeamId = homeTeamId,
homeTeamName = homeTeamName,
homeTeamImageUrl = homeTeamImage,
@@ -46,27 +52,13 @@ fun RemoteMatchInformation.toModel() = MatchInformation(
NotablePlayer(
playerId = remote.playerId,
playerName = remote.playerName,
- playerHeight = remote.height,
- playerWeight = remote.weight,
- playerImageUrl = remote.playerImage,
- playerPosition = remote.position,
- playerPositionInitial = remote.positionInitial,
- playerGoalCount = remote.goalCount
- )
- },
- lineUp = lineUp.map { remote ->
- LineUp(
- lineUpId = remote.lineUpId,
- matchId = remote.matchId,
- playerId = remote.playerId,
- teamId = remote.teamId,
- playerName = remote.playerName,
- playerBackNumber = remote.jerseyNumber,
- formationField = remote.formationField,
- formationPosition = remote.formationPosition,
- positionId = remote.positionId,
- positionCategory = remote.positionCategory,
- positionInitial = remote.positionInitial
+ playerHeight = remote.height ?: 0,
+ playerWeight = remote.weight ?: 0,
+ playerImageUrl = remote.playerImage ?: "",
+ playerPosition = remote.position ?: "",
+ playerPositionInitial = remote.positionInitial ?: "",
+ playerGoalCount = remote.goalCount ?: 0,
+ playerParticipationCount = remote.participationCount ?: 0
)
},
performance = Performance(
@@ -101,4 +93,34 @@ fun RemoteMatchDetail.toModel() = MatchDetail(
fun RemoteMatchData.toModel() = MatchData(
match = match.toModel(),
matchDetail = matchDetail.map { remote -> remote.toModel() }
-)
\ No newline at end of file
+)
+
+/**
+ * [RemoteMatchLineup] Mapper
+ * - Mapper [RemoteMatchLineup] to [MatchLineup]
+ */
+fun RemoteMatchLineup.toModel() = MatchLineup(
+ homeLineup = homeLineup.toModel(),
+ awayLineup = awayLineup.toModel()
+)
+
+fun RemoteTeamLineup.toModel() = TeamLineup(
+ teamId = teamId.toInt(),
+ formation = formation,
+ playerLineup = players.map { remote -> remote.toModel() }
+)
+
+fun RemotePlayerLineup.toModel() = PlayerLineup(
+ lineUpId = lineUpId,
+ matchId = matchId,
+ playerId = playerId,
+ teamId = teamId,
+ playerName = playerName,
+ playerImageUrl = playerImageUrl,
+ playerBackNumber = jerseyNumber,
+ formationField = formationField,
+ formationPosition = formationPosition,
+ positionId = positionId,
+ positionCategory = positionCategory,
+ positionInitial = positionInitial
+)
diff --git a/core/data/src/main/java/com/eshc/goonersapp/core/data/mapper/SeasonMapper.kt b/core/data/src/main/java/com/eshc/goonersapp/core/data/mapper/SeasonMapper.kt
new file mode 100644
index 00000000..35587407
--- /dev/null
+++ b/core/data/src/main/java/com/eshc/goonersapp/core/data/mapper/SeasonMapper.kt
@@ -0,0 +1,33 @@
+package com.eshc.goonersapp.core.data.mapper
+
+import com.eshc.goonersapp.core.domain.model.season.League
+import com.eshc.goonersapp.core.domain.model.season.Rank
+import com.eshc.goonersapp.core.domain.model.season.Season
+import com.eshc.goonersapp.core.network.model.season.RemoteLeague
+import com.eshc.goonersapp.core.network.model.season.RemoteRank
+import com.eshc.goonersapp.core.network.model.season.RemoteSeason
+
+fun RemoteLeague.toModel() = League(
+ leagueId = leagueId,
+ leagueName = leagueName,
+ shortCode = shortCode,
+ leagueImgUrl = leagueImageUrl,
+ seasonId = seasonId,
+ season = season,
+ teamId = teamId
+)
+
+fun RemoteSeason.toModel() = Season(seasonId = seasonId, season = season)
+
+fun RemoteRank.toModel() = Rank(
+ standingId = standingId,
+ position = position,
+ points = points,
+ wins = win,
+ loss = loss,
+ draw = draw,
+ goalDifference = goalDifference,
+ teamId = teamId,
+ teamName = teamName,
+ shortCode = shortCode
+)
\ No newline at end of file
diff --git a/core/data/src/main/java/com/eshc/goonersapp/core/data/repository/MatchRepositoryImpl.kt b/core/data/src/main/java/com/eshc/goonersapp/core/data/repository/MatchRepositoryImpl.kt
index 6a1bc887..a867ea9b 100644
--- a/core/data/src/main/java/com/eshc/goonersapp/core/data/repository/MatchRepositoryImpl.kt
+++ b/core/data/src/main/java/com/eshc/goonersapp/core/data/repository/MatchRepositoryImpl.kt
@@ -6,6 +6,7 @@ import com.eshc.goonersapp.core.domain.model.DataResult
import com.eshc.goonersapp.core.domain.model.match.Match
import com.eshc.goonersapp.core.domain.model.match.MatchData
import com.eshc.goonersapp.core.domain.model.match.MatchInformation
+import com.eshc.goonersapp.core.domain.model.match.MatchLineup
import com.eshc.goonersapp.core.domain.repository.MatchRepository
import com.eshc.goonersapp.core.network.MatchNetworkDataSource
import kotlinx.coroutines.flow.Flow
@@ -59,4 +60,12 @@ class MatchRepositoryImpl @Inject constructor(
emit(result)
}
+
+ override fun getMatchLineup(matchId: Int): Flow> = flow {
+ val result = matchNetworkDataSource
+ .getMatchLineup(matchId)
+ .toDataResult { remote -> remote.toModel() }
+
+ emit(result)
+ }
}
\ No newline at end of file
diff --git a/core/data/src/main/java/com/eshc/goonersapp/core/data/repository/SeasonRepositoryImpl.kt b/core/data/src/main/java/com/eshc/goonersapp/core/data/repository/SeasonRepositoryImpl.kt
new file mode 100644
index 00000000..37173894
--- /dev/null
+++ b/core/data/src/main/java/com/eshc/goonersapp/core/data/repository/SeasonRepositoryImpl.kt
@@ -0,0 +1,47 @@
+package com.eshc.goonersapp.core.data.repository
+
+import com.eshc.goonersapp.core.data.mapper.toDataResult
+import com.eshc.goonersapp.core.data.mapper.toModel
+import com.eshc.goonersapp.core.domain.model.DataResult
+import com.eshc.goonersapp.core.domain.model.season.League
+import com.eshc.goonersapp.core.domain.model.season.Rank
+import com.eshc.goonersapp.core.domain.model.season.Season
+import com.eshc.goonersapp.core.domain.repository.SeasonRepository
+import com.eshc.goonersapp.core.network.SeasonNetworkDataSource
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flow
+import javax.inject.Inject
+
+class SeasonRepositoryImpl @Inject constructor(
+ private val seasonNetworkDataSource: SeasonNetworkDataSource
+): SeasonRepository {
+ override fun getSeasonListByTeam(teamId: Int): Flow>> = flow {
+ val result = seasonNetworkDataSource
+ .getSeasonListByTeam(teamId)
+ .toDataResult { remote -> remote.map { it.toModel() } }
+
+ emit(result)
+ }
+
+ override fun getLeagueListAsCurrentSeasonByTeam(
+ teamId: Int
+ ): Flow>> = flow {
+ val result = seasonNetworkDataSource
+ .getLeagueListAsCurrentSeasonByTeam(teamId)
+ .toDataResult { remote -> remote.map { it.toModel() } }
+
+ emit(result)
+ }
+
+ override fun getPreviewRankListByTeamAndSeason(
+ teamId: Int,
+ seasonId: Int,
+ ): Flow>> = flow {
+ val result = seasonNetworkDataSource
+ .getPreviewRankListByTeamAndSeason(teamId, seasonId)
+ .toDataResult { remote -> remote.map { it.toModel() } }
+
+ emit(result)
+ }
+
+}
\ No newline at end of file
diff --git a/core/data/src/test/java/com/eshc/goonersapp/core/data/FakeMatchTest.kt b/core/data/src/test/java/com/eshc/goonersapp/core/data/FakeMatchRepositoryImplTest.kt
similarity index 76%
rename from core/data/src/test/java/com/eshc/goonersapp/core/data/FakeMatchTest.kt
rename to core/data/src/test/java/com/eshc/goonersapp/core/data/FakeMatchRepositoryImplTest.kt
index 8907f530..11720220 100644
--- a/core/data/src/test/java/com/eshc/goonersapp/core/data/FakeMatchTest.kt
+++ b/core/data/src/test/java/com/eshc/goonersapp/core/data/FakeMatchRepositoryImplTest.kt
@@ -5,7 +5,9 @@ import com.eshc.goonersapp.core.domain.model.DataResult
import com.eshc.goonersapp.core.domain.model.match.Match
import com.eshc.goonersapp.core.domain.model.match.MatchData
import com.eshc.goonersapp.core.domain.model.match.MatchInformation
+import com.eshc.goonersapp.core.domain.model.match.MatchLineup
import com.eshc.goonersapp.core.domain.model.match.Performance
+import com.eshc.goonersapp.core.domain.model.match.TeamLineup
import com.eshc.goonersapp.core.domain.repository.MatchRepository
import com.eshc.goonersapp.core.network.fake.FakeMatchDataSource
import kotlinx.coroutines.runBlocking
@@ -16,10 +18,10 @@ import org.junit.Test
/**
* Created By KanuKim97
*
- * [FakeMatchTest]
+ * [FakeMatchRepositoryImplTest]
* - FakeMatchRepository Test
*/
-class FakeMatchTest {
+class FakeMatchRepositoryImplTest {
private lateinit var fakeMatchDataSource: FakeMatchDataSource
private lateinit var fakeMatchRepository: MatchRepository
@@ -62,7 +64,6 @@ class FakeMatchTest {
assertEquals(
MatchInformation(
notablePlayer = null,
- lineUp = listOf(),
performance = Performance(opponentImageUrl = "", win = 0, draw = 0, lose = 0)
),
result.data
@@ -110,4 +111,30 @@ class FakeMatchTest {
}
}
}
+
+ @Test
+ fun testMatchLineupWithFake() = runBlocking {
+ fakeMatchRepository.getMatchLineup(38).collect { result ->
+ when (result) {
+ is DataResult.Success -> {
+ assertEquals(
+ MatchLineup(
+ homeLineup = TeamLineup(
+ teamId = 0,
+ formation = "",
+ playerLineup = emptyList()
+ ),
+ awayLineup = TeamLineup(
+ teamId = 0,
+ formation = "",
+ playerLineup = emptyList()
+ )
+ ),
+ result.data
+ )
+ }
+ is DataResult.Failure -> { /* Nothing */ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/core/data/src/test/java/com/eshc/goonersapp/core/data/FakeSeasonRepositoryImplTest.kt b/core/data/src/test/java/com/eshc/goonersapp/core/data/FakeSeasonRepositoryImplTest.kt
new file mode 100644
index 00000000..33097b18
--- /dev/null
+++ b/core/data/src/test/java/com/eshc/goonersapp/core/data/FakeSeasonRepositoryImplTest.kt
@@ -0,0 +1,111 @@
+package com.eshc.goonersapp.core.data
+
+import com.eshc.goonersapp.core.data.fake.FakeSeasonRepositoryImpl
+import com.eshc.goonersapp.core.domain.model.DataResult
+import com.eshc.goonersapp.core.domain.model.season.Rank
+import com.eshc.goonersapp.core.domain.repository.SeasonRepository
+import com.eshc.goonersapp.core.network.fake.FakeSeasonDataSource
+import kotlinx.coroutines.runBlocking
+import org.junit.Assert.assertEquals
+import org.junit.Assert.fail
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Created By KanuKim97
+ *
+ * [FakeSeasonRepositoryImplTest]
+ * - FakeSeasonRepository Test
+ */
+class FakeSeasonRepositoryImplTest {
+ private lateinit var fakeSeasonDataSource: FakeSeasonDataSource
+ private lateinit var fakeSeasonRepository: SeasonRepository
+
+ @Before
+ fun setUp() {
+ fakeSeasonDataSource = FakeSeasonDataSource()
+ fakeSeasonRepository = FakeSeasonRepositoryImpl(fakeSeasonDataSource)
+ }
+
+ @Test
+ fun fake_get_season_list_by_team_flow_collect_as_success() = runBlocking {
+ fakeSeasonRepository.getSeasonListByTeam(teamId = 19).collect { result ->
+ when (result) {
+ is DataResult.Success -> {
+ assertEquals(
+ "2023/2024",
+ result.data.first().season
+ )
+ }
+ is DataResult.Failure -> fail("Test should not be reached here")
+ }
+ }
+ }
+
+ @Test
+ fun fake_get_season_list_by_team_flow_collect_as_fail() = runBlocking {
+ fakeSeasonRepository.getSeasonListByTeam(teamId = 20).collect { result ->
+ when (result) {
+ is DataResult.Success -> fail("Test should not be reached here")
+ is DataResult.Failure -> assertEquals(404, result.code)
+ }
+ }
+ }
+
+ @Test
+ fun fake_get_league_list_as_current_season_by_team_as_success() = runBlocking {
+ fakeSeasonRepository.getLeagueListAsCurrentSeasonByTeam(19).collect { result ->
+ when(result) {
+ is DataResult.Success -> {
+ assertEquals(
+ 21366,
+ result.data.first().seasonId
+ )
+ }
+ is DataResult.Failure -> fail("Test should not be reached here")
+ }
+ }
+ }
+
+
+ @Test
+ fun fake_get_league_list_as_current_season_by_team_as_fail() = runBlocking {
+ fakeSeasonRepository.getLeagueListAsCurrentSeasonByTeam(20).collect { result ->
+ when(result) {
+ is DataResult.Success -> fail("Test should not be reached here")
+ is DataResult.Failure -> assertEquals(404, result.code)
+ }
+ }
+ }
+
+ @Test
+ fun fake_get_preview_rank_list_by_team_and_season_as_success() = runBlocking {
+ fakeSeasonRepository.getPreviewRankListByTeamAndSeason(
+ teamId = 19,
+ seasonId = 21366
+ ).collect { result ->
+ when (result) {
+ is DataResult.Success -> {
+ assertEquals(
+ listOf(),
+ result.data
+ )
+ }
+ is DataResult.Failure -> fail("Test should not be reached here")
+ }
+ }
+ }
+
+ @Test
+ fun fake_get_preview_rank_list_by_team_and_season_as_fail() = runBlocking {
+ fakeSeasonRepository.getPreviewRankListByTeamAndSeason(
+ teamId = 20,
+ seasonId = 21366
+ ).collect { result ->
+ when (result) {
+ is DataResult.Success -> fail("Test should not be reached here")
+ is DataResult.Failure -> assertEquals(404, result.code)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/component/MatchLeagueInfo.kt b/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/component/MatchLeagueInfo.kt
index 4c356951..bc53744b 100644
--- a/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/component/MatchLeagueInfo.kt
+++ b/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/component/MatchLeagueInfo.kt
@@ -57,7 +57,7 @@ fun MatchLeagueInfo(
)
}
)
- Spacer(modifier = Modifier.size(10.dp))
+ Spacer(modifier = Modifier.size(7.dp))
Text(
text = competitionName,
color = ColorFF181818,
diff --git a/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/component/TopBar.kt b/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/component/TopBar.kt
index ab81bd0b..dd08b6ad 100644
--- a/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/component/TopBar.kt
+++ b/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/component/TopBar.kt
@@ -1,12 +1,11 @@
package com.eshc.goonersapp.core.designsystem.component
+import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@@ -14,17 +13,15 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
import com.eshc.goonersapp.core.designsystem.IconPack
-import com.eshc.goonersapp.core.designsystem.iconpack.IcFootballClub
-import com.eshc.goonersapp.core.designsystem.theme.pretendard
+import com.eshc.goonersapp.core.designsystem.iconpack.IcIosArrowBack
+import com.eshc.goonersapp.core.designsystem.theme.GnrTypography
@Composable
-fun TopLevelTopBar(
- modifier: Modifier = Modifier,
+fun GnrTopLevelTopBar(
title : String,
+ modifier: Modifier = Modifier,
content : @Composable () -> Unit
){
Row(
@@ -34,7 +31,7 @@ fun TopLevelTopBar(
Text(
modifier = Modifier.padding(vertical = 8.dp).wrapContentHeight().weight(1f),
text = title,
- style = MaterialTheme.typography.headlineLarge,
+ style = GnrTypography.heading2SemiBold,
color = Color.Black,
)
content()
@@ -42,9 +39,10 @@ fun TopLevelTopBar(
}
@Composable
-fun TopBar(
- modifier: Modifier = Modifier,
+fun GnrTopBar(
title : String,
+ onBackIconClick: () -> Unit,
+ modifier: Modifier = Modifier,
content : @Composable () -> Unit = {}
){
Row(
@@ -52,9 +50,12 @@ fun TopBar(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
- imageVector = Icons.Default.ArrowBack,
+ imageVector = IconPack.IcIosArrowBack,
contentDescription = null,
- modifier= Modifier.padding(start = 8.dp,end = 8.dp).size(24.dp)
+ modifier= Modifier
+ .padding(start = 8.dp,end = 8.dp)
+ .size(24.dp)
+ .clickable(onClick = onBackIconClick)
)
Text(
modifier = Modifier.padding(vertical = 8.dp).wrapContentHeight().weight(1f),
diff --git a/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/iconpack/IcIosArrowBack.kt b/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/iconpack/IcIosArrowBack.kt
new file mode 100644
index 00000000..b81a5658
--- /dev/null
+++ b/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/iconpack/IcIosArrowBack.kt
@@ -0,0 +1,48 @@
+package com.eshc.goonersapp.core.designsystem.iconpack
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.PathFillType.Companion.NonZero
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.StrokeCap.Companion.Butt
+import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.ImageVector.Builder
+import androidx.compose.ui.graphics.vector.path
+import androidx.compose.ui.unit.dp
+import com.eshc.goonersapp.core.designsystem.IconPack
+
+public val IconPack.IcIosArrowBack: ImageVector
+ get() {
+ if (_iciosarrowback != null) {
+ return _iciosarrowback!!
+ }
+ _iciosarrowback = Builder(name = "IcIosArrowBack", defaultWidth = 10.0.dp, defaultHeight =
+ 18.0.dp, viewportWidth = 10.0f, viewportHeight = 18.0f).apply {
+ path(fill = SolidColor(Color(0xFF181818)), stroke = null, strokeLineWidth = 0.0f,
+ strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f,
+ pathFillType = NonZero) {
+ moveTo(1.4564f, 9.0014f)
+ lineTo(9.1754f, 16.7206f)
+ curveTo(9.323f, 16.868f, 9.3959f, 17.0444f, 9.394f, 17.2496f)
+ curveTo(9.392f, 17.4549f, 9.3173f, 17.6312f, 9.1697f, 17.7786f)
+ curveTo(9.0223f, 17.9262f, 8.846f, 18.0f, 8.6407f, 18.0f)
+ curveTo(8.4354f, 18.0f, 8.2591f, 17.9262f, 8.1117f, 17.7786f)
+ lineTo(0.4655f, 10.1384f)
+ curveTo(0.3039f, 9.9769f, 0.1859f, 9.7967f, 0.1116f, 9.5979f)
+ curveTo(0.0372f, 9.399f, 0.0f, 9.2002f, 0.0f, 9.0014f)
+ curveTo(0.0f, 8.8026f, 0.0372f, 8.6038f, 0.1116f, 8.4049f)
+ curveTo(0.1859f, 8.2061f, 0.3039f, 8.0259f, 0.4655f, 7.8643f)
+ lineTo(8.1117f, 0.2184f)
+ curveTo(8.2591f, 0.0708f, 8.4364f, -0.002f, 8.6437f, 0.0f)
+ curveTo(8.8508f, 0.0019f, 9.028f, 0.0766f, 9.1754f, 0.2241f)
+ curveTo(9.323f, 0.3716f, 9.3968f, 0.5479f, 9.3968f, 0.7532f)
+ curveTo(9.3968f, 0.9584f, 9.323f, 1.1348f, 9.1754f, 1.2822f)
+ lineTo(1.4564f, 9.0014f)
+ close()
+ }
+ }
+ .build()
+ return _iciosarrowback!!
+ }
+
+private var _iciosarrowback: ImageVector? = null
diff --git a/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/iconpack/IcNotification.kt b/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/iconpack/IcNotification.kt
new file mode 100644
index 00000000..4ece6a2d
--- /dev/null
+++ b/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/iconpack/IcNotification.kt
@@ -0,0 +1,71 @@
+package com.eshc.goonersapp.core.designsystem.iconpack
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.PathFillType.Companion.NonZero
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.StrokeCap.Companion.Butt
+import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.ImageVector.Builder
+import androidx.compose.ui.graphics.vector.path
+import androidx.compose.ui.unit.dp
+import com.eshc.goonersapp.core.designsystem.IconPack
+
+public val IconPack.IcNotification: ImageVector
+ get() {
+ if (_notification != null) {
+ return _notification!!
+ }
+ _notification = Builder(name = "Notification", defaultWidth = 23.0.dp, defaultHeight =
+ 26.0.dp, viewportWidth = 23.0f, viewportHeight = 26.0f).apply {
+ path(fill = SolidColor(Color(0xFFBBBBBB)), stroke = null, strokeLineWidth = 0.0f,
+ strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f,
+ pathFillType = NonZero) {
+ moveTo(1.1197f, 22.1964f)
+ curveTo(0.8024f, 22.1964f, 0.5365f, 22.099f, 0.3219f, 21.9042f)
+ curveTo(0.1073f, 21.7094f, 0.0f, 21.468f, 0.0f, 21.18f)
+ curveTo(0.0f, 20.892f, 0.1073f, 20.6507f, 0.3219f, 20.4562f)
+ curveTo(0.5365f, 20.2617f, 0.8024f, 20.1644f, 1.1197f, 20.1644f)
+ horizontalLineTo(2.6987f)
+ verticalLineTo(10.0561f)
+ curveTo(2.6987f, 8.2342f, 3.3183f, 6.6233f, 4.5576f, 5.2234f)
+ curveTo(5.7969f, 3.8236f, 7.3878f, 2.9283f, 9.3305f, 2.5375f)
+ verticalLineTo(1.6934f)
+ curveTo(9.3305f, 1.223f, 9.5118f, 0.8232f, 9.8743f, 0.4939f)
+ curveTo(10.2368f, 0.1646f, 10.677f, 0.0f, 11.1949f, 0.0f)
+ curveTo(11.7128f, 0.0f, 12.1535f, 0.1646f, 12.5172f, 0.4939f)
+ curveTo(12.8808f, 0.8232f, 13.0626f, 1.223f, 13.0626f, 1.6934f)
+ verticalLineTo(2.5375f)
+ curveTo(15.0053f, 2.9283f, 16.5963f, 3.8236f, 17.8356f, 5.2234f)
+ curveTo(19.0748f, 6.6233f, 19.6945f, 8.2342f, 19.6945f, 10.0561f)
+ verticalLineTo(20.1644f)
+ horizontalLineTo(21.2735f)
+ curveTo(21.5907f, 20.1644f, 21.8566f, 20.2618f, 22.0712f, 20.4566f)
+ curveTo(22.2858f, 20.6514f, 22.3931f, 20.8929f, 22.3931f, 21.1808f)
+ curveTo(22.3931f, 21.4689f, 22.2858f, 21.7101f, 22.0712f, 21.9046f)
+ curveTo(21.8566f, 22.0991f, 21.5907f, 22.1964f, 21.2735f, 22.1964f)
+ horizontalLineTo(1.1197f)
+ close()
+ moveTo(11.194f, 26.0f)
+ curveTo(10.4512f, 26.0f, 9.8161f, 25.7602f, 9.2888f, 25.2806f)
+ curveTo(8.7616f, 24.8011f, 8.4979f, 24.2246f, 8.4979f, 23.5511f)
+ horizontalLineTo(13.8952f)
+ curveTo(13.8952f, 24.2267f, 13.6307f, 24.8038f, 13.1017f, 25.2823f)
+ curveTo(12.5728f, 25.7608f, 11.9369f, 26.0f, 11.194f, 26.0f)
+ close()
+ moveTo(4.9379f, 20.1644f)
+ horizontalLineTo(17.4552f)
+ verticalLineTo(10.0561f)
+ curveTo(17.4552f, 8.4878f, 16.8442f, 7.1491f, 15.6221f, 6.0402f)
+ curveTo(14.4001f, 4.9312f, 12.9249f, 4.3767f, 11.1966f, 4.3767f)
+ curveTo(9.4683f, 4.3767f, 7.9931f, 4.9312f, 6.771f, 6.0402f)
+ curveTo(5.549f, 7.1491f, 4.9379f, 8.4878f, 4.9379f, 10.0561f)
+ verticalLineTo(20.1644f)
+ close()
+ }
+ }
+ .build()
+ return _notification!!
+ }
+
+private var _notification: ImageVector? = null
diff --git a/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/iconpack/IcPeople.kt b/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/iconpack/IcPeople.kt
new file mode 100644
index 00000000..4a6347a5
--- /dev/null
+++ b/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/iconpack/IcPeople.kt
@@ -0,0 +1,80 @@
+package com.eshc.goonersapp.core.designsystem.iconpack
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.PathFillType.Companion.NonZero
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.StrokeCap.Companion.Butt
+import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.ImageVector.Builder
+import androidx.compose.ui.graphics.vector.path
+import androidx.compose.ui.unit.dp
+import com.eshc.goonersapp.core.designsystem.IconPack
+
+public val IconPack.IcPeople: ImageVector
+ get() {
+ if (_icpeople != null) {
+ return _icpeople!!
+ }
+ _icpeople = Builder(name = "IcPeople", defaultWidth = 18.0.dp, defaultHeight = 20.0.dp,
+ viewportWidth = 18.0f, viewportHeight = 20.0f).apply {
+ path(fill = SolidColor(Color(0xFF777777)), stroke = null, strokeLineWidth = 0.0f,
+ strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f,
+ pathFillType = NonZero) {
+ moveTo(9.0f, 9.2574f)
+ curveTo(7.9393f, 9.2574f, 7.0313f, 8.8416f, 6.2759f, 8.0101f)
+ curveTo(5.5205f, 7.1787f, 5.1429f, 6.1791f, 5.1429f, 5.0115f)
+ curveTo(5.1429f, 3.8439f, 5.5205f, 2.8443f, 6.2759f, 2.0128f)
+ curveTo(7.0313f, 1.1814f, 7.9393f, 0.7656f, 9.0f, 0.7656f)
+ curveTo(10.0607f, 0.7656f, 10.9688f, 1.1814f, 11.7241f, 2.0128f)
+ curveTo(12.4795f, 2.8443f, 12.8571f, 3.8439f, 12.8571f, 5.0115f)
+ curveTo(12.8571f, 6.1791f, 12.4795f, 7.1787f, 11.7241f, 8.0101f)
+ curveTo(10.9688f, 8.8416f, 10.0607f, 9.2574f, 9.0f, 9.2574f)
+ close()
+ moveTo(0.0f, 18.0212f)
+ verticalLineTo(17.1612f)
+ curveTo(0.0f, 16.5769f, 0.1545f, 16.0303f, 0.4636f, 15.5213f)
+ curveTo(0.7727f, 15.0124f, 1.1885f, 14.6173f, 1.711f, 14.336f)
+ curveTo(2.9242f, 13.6955f, 4.1382f, 13.2151f, 5.353f, 12.8949f)
+ curveTo(6.5679f, 12.5746f, 7.7835f, 12.4145f, 9.0f, 12.4145f)
+ curveTo(10.2165f, 12.4145f, 11.4321f, 12.5746f, 12.647f, 12.8949f)
+ curveTo(13.8618f, 13.2151f, 15.0758f, 13.6955f, 16.289f, 14.336f)
+ curveTo(16.8115f, 14.6173f, 17.2273f, 15.0124f, 17.5364f, 15.5213f)
+ curveTo(17.8455f, 16.0303f, 18.0f, 16.5769f, 18.0f, 17.1612f)
+ verticalLineTo(18.0212f)
+ curveTo(18.0f, 18.4368f, 17.8718f, 18.7856f, 17.6155f, 19.0677f)
+ curveTo(17.3592f, 19.3499f, 17.0423f, 19.491f, 16.6649f, 19.491f)
+ horizontalLineTo(1.3352f)
+ curveTo(0.9577f, 19.491f, 0.6408f, 19.3499f, 0.3845f, 19.0677f)
+ curveTo(0.1282f, 18.7856f, 0.0f, 18.4368f, 0.0f, 18.0212f)
+ close()
+ moveTo(1.2857f, 18.0756f)
+ horizontalLineTo(16.7143f)
+ verticalLineTo(17.1612f)
+ curveTo(16.7143f, 16.8473f, 16.6224f, 16.5524f, 16.4386f, 16.2766f)
+ curveTo(16.2548f, 16.0008f, 16.0005f, 15.7677f, 15.6758f, 15.5771f)
+ curveTo(14.6176f, 15.0128f, 13.5265f, 14.5805f, 12.4025f, 14.2802f)
+ curveTo(11.2786f, 13.9799f, 10.1444f, 13.8298f, 9.0f, 13.8298f)
+ curveTo(7.8556f, 13.8298f, 6.7214f, 13.9799f, 5.5975f, 14.2802f)
+ curveTo(4.4735f, 14.5805f, 3.3824f, 15.0128f, 2.3242f, 15.5771f)
+ curveTo(1.9995f, 15.7677f, 1.7452f, 16.0008f, 1.5614f, 16.2766f)
+ curveTo(1.3776f, 16.5524f, 1.2857f, 16.8473f, 1.2857f, 17.1612f)
+ verticalLineTo(18.0756f)
+ close()
+ moveTo(9.0f, 7.8421f)
+ curveTo(9.7071f, 7.8421f, 10.3125f, 7.5649f, 10.8161f, 7.0106f)
+ curveTo(11.3196f, 6.4563f, 11.5714f, 5.7899f, 11.5714f, 5.0115f)
+ curveTo(11.5714f, 4.2331f, 11.3196f, 3.5667f, 10.8161f, 3.0124f)
+ curveTo(10.3125f, 2.4581f, 9.7071f, 2.1809f, 9.0f, 2.1809f)
+ curveTo(8.2929f, 2.1809f, 7.6875f, 2.4581f, 7.1839f, 3.0124f)
+ curveTo(6.6804f, 3.5667f, 6.4286f, 4.2331f, 6.4286f, 5.0115f)
+ curveTo(6.4286f, 5.7899f, 6.6804f, 6.4563f, 7.1839f, 7.0106f)
+ curveTo(7.6875f, 7.5649f, 8.2929f, 7.8421f, 9.0f, 7.8421f)
+ close()
+ }
+ }
+ .build()
+ return _icpeople!!
+ }
+
+private var _icpeople: ImageVector? = null
diff --git a/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/theme/Color.kt b/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/theme/Color.kt
index bbd63f34..914f4d46 100644
--- a/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/theme/Color.kt
+++ b/core/designsystem/src/main/java/com/eshc/goonersapp/core/designsystem/theme/Color.kt
@@ -36,9 +36,17 @@ val Color88FFFFFF = Color(0x88FFFFFF)
val ColorFFFECD44 = Color(0xFFFECD44)
val ColorFFE9343C = Color(0xFFE9343C)
+val ColorFFE6EDFC = Color(0xFFE6EDFC)
+
val BrushMainGradient = Brush.verticalGradient(
listOf(
ColorFF10358A,
ColorFF072872
)
-)
\ No newline at end of file
+)
+
+/**
+ * Player Detail Color
+ * */
+val ColorFFC10006 = Color(0xFFC10006)
+val ColorFF720509 = Color(0xFF720509)
\ No newline at end of file
diff --git a/core/designsystem/src/main/res/drawable/ic_ball.png b/core/designsystem/src/main/res/drawable/ic_ball.png
new file mode 100644
index 00000000..82462abc
Binary files /dev/null and b/core/designsystem/src/main/res/drawable/ic_ball.png differ
diff --git a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/match/Match.kt b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/match/Match.kt
index 6e785e70..0fbfa6d1 100644
--- a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/match/Match.kt
+++ b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/match/Match.kt
@@ -2,6 +2,7 @@ package com.eshc.goonersapp.core.domain.model.match
data class Match(
val id :Int = 0,
+ val seasonId : Int = 0,
val homeTeamId : Int = 0,
val homeTeamName : String = "",
val homeTeamImageUrl : String = "",
diff --git a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/match/MatchInformation.kt b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/match/MatchInformation.kt
index 271a29ec..95c8d2fc 100644
--- a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/match/MatchInformation.kt
+++ b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/match/MatchInformation.kt
@@ -2,7 +2,6 @@ package com.eshc.goonersapp.core.domain.model.match
data class MatchInformation(
val notablePlayer: NotablePlayer? = null,
- val lineUp: List,
val performance: Performance
)
@@ -14,21 +13,8 @@ data class NotablePlayer(
val playerImageUrl: String,
val playerPosition: String,
val playerPositionInitial: String,
- val playerGoalCount: Int
-)
-
-data class LineUp(
- val lineUpId: Double,
- val matchId: Int,
- val playerId: Int,
- val teamId: Int,
- val playerName: String,
- val playerBackNumber: Int,
- val formationField: String?,
- val formationPosition: Int?,
- val positionId: Int,
- val positionCategory: String,
- val positionInitial: String
+ val playerGoalCount: Int,
+ val playerParticipationCount : Int
)
data class Performance(
diff --git a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/match/MatchLineup.kt b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/match/MatchLineup.kt
new file mode 100644
index 00000000..91ba5773
--- /dev/null
+++ b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/match/MatchLineup.kt
@@ -0,0 +1,49 @@
+package com.eshc.goonersapp.core.domain.model.match
+
+import com.eshc.goonersapp.core.domain.model.player.Player
+
+data class MatchLineup(
+ val homeLineup : TeamLineup,
+ val awayLineup : TeamLineup
+){
+ fun getMyTeamLineup(myTeamId : Int) : TeamLineup {
+ return if(homeLineup.teamId == myTeamId) homeLineup else awayLineup
+ }
+}
+
+data class TeamLineup(
+ val teamId : Int,
+ val formation : String,
+ val playerLineup : List
+){
+ private fun getFormationAsList() : List {
+ return listOf(1) + formation.split("-").map { it.toIntOrNull() ?: 0 }
+ }
+
+
+ fun groupStartingPlayersByPosition(): List> {
+ val actualPositionList = getFormationAsList()
+ val sortedPlayers = playerLineup.filter { it.formationField != "null" }.sortedBy { it.formationPosition }
+
+ return actualPositionList.mapIndexed { index, i ->
+ val p = i - 1
+ val s = actualPositionList.subList(0, index).sum()
+ sortedPlayers.slice(s..s + p)
+ }
+ }
+}
+
+data class PlayerLineup(
+ val lineUpId: Long,
+ val matchId: Int,
+ val playerId: Int,
+ val teamId: Int,
+ val playerName: String,
+ val playerImageUrl : String,
+ val playerBackNumber: Int,
+ val formationField: String?,
+ val formationPosition: Int?,
+ val positionId: Int,
+ val positionCategory: String,
+ val positionInitial: String
+)
\ No newline at end of file
diff --git a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/season/League.kt b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/season/League.kt
new file mode 100644
index 00000000..1b8a2f68
--- /dev/null
+++ b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/season/League.kt
@@ -0,0 +1,11 @@
+package com.eshc.goonersapp.core.domain.model.season
+
+data class League(
+ val leagueId: Int,
+ val leagueName: String,
+ val shortCode: String,
+ val leagueImgUrl: String,
+ val seasonId: Int,
+ val season: String,
+ val teamId: Int
+)
\ No newline at end of file
diff --git a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/season/Rank.kt b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/season/Rank.kt
new file mode 100644
index 00000000..d6f8a8d1
--- /dev/null
+++ b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/season/Rank.kt
@@ -0,0 +1,14 @@
+package com.eshc.goonersapp.core.domain.model.season
+
+data class Rank(
+ val standingId: Int,
+ val position: Int,
+ val points: Int,
+ val wins: Int,
+ val loss: Int,
+ val draw: Int,
+ val goalDifference: Int,
+ val teamId: Int,
+ val teamName: String,
+ val shortCode: String
+)
\ No newline at end of file
diff --git a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/season/Season.kt b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/season/Season.kt
new file mode 100644
index 00000000..5fd1c252
--- /dev/null
+++ b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/model/season/Season.kt
@@ -0,0 +1,3 @@
+package com.eshc.goonersapp.core.domain.model.season
+
+data class Season(val seasonId: Int, val season: String)
\ No newline at end of file
diff --git a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/repository/MatchRepository.kt b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/repository/MatchRepository.kt
index bb41a976..e624246b 100644
--- a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/repository/MatchRepository.kt
+++ b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/repository/MatchRepository.kt
@@ -4,6 +4,7 @@ import com.eshc.goonersapp.core.domain.model.DataResult
import com.eshc.goonersapp.core.domain.model.match.Match
import com.eshc.goonersapp.core.domain.model.match.MatchData
import com.eshc.goonersapp.core.domain.model.match.MatchInformation
+import com.eshc.goonersapp.core.domain.model.match.MatchLineup
import kotlinx.coroutines.flow.Flow
interface MatchRepository {
@@ -18,4 +19,5 @@ interface MatchRepository {
fun getRecentlyMatch() : Flow>
+ fun getMatchLineup(matchId: Int) : Flow>
}
\ No newline at end of file
diff --git a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/repository/SeasonRepository.kt b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/repository/SeasonRepository.kt
new file mode 100644
index 00000000..e94f202c
--- /dev/null
+++ b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/repository/SeasonRepository.kt
@@ -0,0 +1,19 @@
+package com.eshc.goonersapp.core.domain.repository
+
+import com.eshc.goonersapp.core.domain.model.DataResult
+import com.eshc.goonersapp.core.domain.model.season.League
+import com.eshc.goonersapp.core.domain.model.season.Rank
+import com.eshc.goonersapp.core.domain.model.season.Season
+import kotlinx.coroutines.flow.Flow
+
+interface SeasonRepository {
+
+ fun getSeasonListByTeam(teamId: Int): Flow>>
+
+ fun getLeagueListAsCurrentSeasonByTeam(teamId: Int): Flow>>
+
+ fun getPreviewRankListByTeamAndSeason(
+ teamId: Int,
+ seasonId: Int
+ ): Flow>>
+}
\ No newline at end of file
diff --git a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/usecase/match/GetMatchLineupUseCase.kt b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/usecase/match/GetMatchLineupUseCase.kt
new file mode 100644
index 00000000..75f7adf4
--- /dev/null
+++ b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/usecase/match/GetMatchLineupUseCase.kt
@@ -0,0 +1,17 @@
+package com.eshc.goonersapp.core.domain.usecase.match
+
+import com.eshc.goonersapp.core.domain.model.DataResult
+import com.eshc.goonersapp.core.domain.model.match.MatchLineup
+import com.eshc.goonersapp.core.domain.repository.MatchRepository
+import kotlinx.coroutines.flow.Flow
+import javax.inject.Inject
+
+class GetMatchLineupUseCase @Inject constructor(
+ private val matchRepository: MatchRepository
+) {
+ operator fun invoke(
+ matchId: Int,
+ ): Flow> = matchRepository.getMatchLineup(
+ matchId
+ )
+}
\ No newline at end of file
diff --git a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/usecase/season/GetLeagueListAsCurrentSeasonByTeamUseCase.kt b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/usecase/season/GetLeagueListAsCurrentSeasonByTeamUseCase.kt
new file mode 100644
index 00000000..eac9ce27
--- /dev/null
+++ b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/usecase/season/GetLeagueListAsCurrentSeasonByTeamUseCase.kt
@@ -0,0 +1,15 @@
+package com.eshc.goonersapp.core.domain.usecase.season
+
+import com.eshc.goonersapp.core.domain.model.DataResult
+import com.eshc.goonersapp.core.domain.model.season.League
+import com.eshc.goonersapp.core.domain.repository.SeasonRepository
+import kotlinx.coroutines.flow.Flow
+import javax.inject.Inject
+
+class GetLeagueListAsCurrentSeasonByTeamUseCase @Inject constructor(
+ private val seasonRepository: SeasonRepository
+) {
+ operator fun invoke(
+ teamId: Int
+ ): Flow>> = seasonRepository.getLeagueListAsCurrentSeasonByTeam(teamId)
+}
\ No newline at end of file
diff --git a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/usecase/season/GetPreviewRankListByTeamAndSeasonUseCase.kt b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/usecase/season/GetPreviewRankListByTeamAndSeasonUseCase.kt
new file mode 100644
index 00000000..2851aad5
--- /dev/null
+++ b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/usecase/season/GetPreviewRankListByTeamAndSeasonUseCase.kt
@@ -0,0 +1,19 @@
+package com.eshc.goonersapp.core.domain.usecase.season
+
+import com.eshc.goonersapp.core.domain.model.DataResult
+import com.eshc.goonersapp.core.domain.model.season.Rank
+import com.eshc.goonersapp.core.domain.repository.SeasonRepository
+import kotlinx.coroutines.flow.Flow
+import javax.inject.Inject
+
+class GetPreviewRankListByTeamAndSeasonUseCase @Inject constructor(
+ private val seasonRepository: SeasonRepository
+) {
+ operator fun invoke(
+ teamId: Int,
+ seasonId: Int
+ ): Flow>> = seasonRepository.getPreviewRankListByTeamAndSeason(
+ teamId = teamId,
+ seasonId = seasonId
+ )
+}
\ No newline at end of file
diff --git a/core/domain/src/main/java/com/eshc/goonersapp/core/domain/usecase/season/GetSeasonListByTeamUseCase.kt b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/usecase/season/GetSeasonListByTeamUseCase.kt
new file mode 100644
index 00000000..385f9023
--- /dev/null
+++ b/core/domain/src/main/java/com/eshc/goonersapp/core/domain/usecase/season/GetSeasonListByTeamUseCase.kt
@@ -0,0 +1,15 @@
+package com.eshc.goonersapp.core.domain.usecase.season
+
+import com.eshc.goonersapp.core.domain.model.DataResult
+import com.eshc.goonersapp.core.domain.model.season.Season
+import com.eshc.goonersapp.core.domain.repository.SeasonRepository
+import kotlinx.coroutines.flow.Flow
+import javax.inject.Inject
+
+class GetSeasonListByTeamUseCase @Inject constructor(
+ private val seasonRepository: SeasonRepository
+) {
+ operator fun invoke(
+ teamId: Int
+ ): Flow>> = seasonRepository.getSeasonListByTeam(teamId)
+}
\ No newline at end of file
diff --git a/core/network/src/main/java/com/eshc/goonersapp/core/network/MatchNetworkDataSource.kt b/core/network/src/main/java/com/eshc/goonersapp/core/network/MatchNetworkDataSource.kt
index 2ccbb9df..c189d6f0 100644
--- a/core/network/src/main/java/com/eshc/goonersapp/core/network/MatchNetworkDataSource.kt
+++ b/core/network/src/main/java/com/eshc/goonersapp/core/network/MatchNetworkDataSource.kt
@@ -4,6 +4,7 @@ import com.eshc.goonersapp.core.network.model.NetworkResult
import com.eshc.goonersapp.core.network.model.match.RemoteMatch
import com.eshc.goonersapp.core.network.model.match.RemoteMatchData
import com.eshc.goonersapp.core.network.model.match.RemoteMatchInformation
+import com.eshc.goonersapp.core.network.model.match.RemoteMatchLineup
interface MatchNetworkDataSource {
@@ -20,4 +21,6 @@ interface MatchNetworkDataSource {
suspend fun getUpcomingMatches(): NetworkResult>
suspend fun getRecentlyMatch(): NetworkResult
+
+ suspend fun getMatchLineup(matchId: Int) : NetworkResult
}
\ No newline at end of file
diff --git a/core/network/src/main/java/com/eshc/goonersapp/core/network/api/MatchNetworkService.kt b/core/network/src/main/java/com/eshc/goonersapp/core/network/api/MatchNetworkService.kt
index 5ff24821..b93ee4af 100644
--- a/core/network/src/main/java/com/eshc/goonersapp/core/network/api/MatchNetworkService.kt
+++ b/core/network/src/main/java/com/eshc/goonersapp/core/network/api/MatchNetworkService.kt
@@ -4,6 +4,7 @@ import com.eshc.goonersapp.core.network.model.BaseResponse
import com.eshc.goonersapp.core.network.model.match.RemoteMatch
import com.eshc.goonersapp.core.network.model.match.RemoteMatchData
import com.eshc.goonersapp.core.network.model.match.RemoteMatchInformation
+import com.eshc.goonersapp.core.network.model.match.RemoteMatchLineup
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Path
@@ -40,4 +41,9 @@ interface MatchNetworkService {
suspend fun getRecentlyMatch(
@Query("teamId") teamId : Int = 19
) : Response>
+
+ @GET(value = "$MATCH_BASE_URL/lineup")
+ suspend fun getMatchLineup(
+ @Query("matchId") matchId: Int
+ ) : Response>
}
\ No newline at end of file
diff --git a/core/network/src/main/java/com/eshc/goonersapp/core/network/fake/FakeMatchDataSource.kt b/core/network/src/main/java/com/eshc/goonersapp/core/network/fake/FakeMatchDataSource.kt
index 1ff4a05c..29a88cbd 100644
--- a/core/network/src/main/java/com/eshc/goonersapp/core/network/fake/FakeMatchDataSource.kt
+++ b/core/network/src/main/java/com/eshc/goonersapp/core/network/fake/FakeMatchDataSource.kt
@@ -6,6 +6,8 @@ import com.eshc.goonersapp.core.network.model.match.Performance
import com.eshc.goonersapp.core.network.model.match.RemoteMatch
import com.eshc.goonersapp.core.network.model.match.RemoteMatchData
import com.eshc.goonersapp.core.network.model.match.RemoteMatchInformation
+import com.eshc.goonersapp.core.network.model.match.RemoteMatchLineup
+import com.eshc.goonersapp.core.network.model.match.RemoteTeamLineup
import javax.inject.Inject
/**
@@ -31,6 +33,10 @@ import javax.inject.Inject
*
* getRecentlyMatch()
* - return [NetworkResult.Success]
+ *
+ * getMatchLineup(matchId: Int)
+ * - if matchId is over 39 then return [NetworkResult.Error]
+ * - else return [NetworkResult.Success]
*/
class FakeMatchDataSource @Inject constructor(): MatchNetworkDataSource {
override suspend fun getMatch(matchId: Int): NetworkResult {
@@ -57,7 +63,6 @@ class FakeMatchDataSource @Inject constructor(): MatchNetworkDataSource {
NetworkResult.Success(
RemoteMatchInformation(
notablePlayer = null,
- lineUp = listOf(),
performance = Performance()
)
)
@@ -89,4 +94,16 @@ class FakeMatchDataSource @Inject constructor(): MatchNetworkDataSource {
)
}
+ override suspend fun getMatchLineup(matchId: Int): NetworkResult {
+ return if (matchId < 39) {
+ NetworkResult.Success(
+ RemoteMatchLineup(
+ homeLineup = RemoteTeamLineup(),
+ awayLineup = RemoteTeamLineup()
+ )
+ )
+ } else {
+ NetworkResult.Error(code = 404, message = "Not Found")
+ }
+ }
}
\ No newline at end of file
diff --git a/core/network/src/main/java/com/eshc/goonersapp/core/network/fake/FakeSeasonDataSource.kt b/core/network/src/main/java/com/eshc/goonersapp/core/network/fake/FakeSeasonDataSource.kt
new file mode 100644
index 00000000..9e406018
--- /dev/null
+++ b/core/network/src/main/java/com/eshc/goonersapp/core/network/fake/FakeSeasonDataSource.kt
@@ -0,0 +1,68 @@
+package com.eshc.goonersapp.core.network.fake
+
+import com.eshc.goonersapp.core.network.SeasonNetworkDataSource
+import com.eshc.goonersapp.core.network.model.NetworkResult
+import com.eshc.goonersapp.core.network.model.season.RemoteLeague
+import com.eshc.goonersapp.core.network.model.season.RemoteRank
+import com.eshc.goonersapp.core.network.model.season.RemoteSeason
+import javax.inject.Inject
+
+/**
+ * Created By KanuKim97
+ *
+ * [FakeSeasonDataSource]
+ * - fakeSeasonDataSource used in data Layer Test and network Layer Unit Test
+ */
+class FakeSeasonDataSource @Inject constructor(): SeasonNetworkDataSource {
+ override suspend fun getSeasonListByTeam(teamId: Int): NetworkResult> {
+ return if (teamId == 19) {
+ NetworkResult.Success(
+ listOf(
+ RemoteSeason(
+ seasonId = 21366,
+ season = "2023/2024"
+ ),
+ RemoteSeason(
+ seasonId = 21365,
+ season = "2022/2023"
+ )
+ )
+ )
+ } else {
+ NetworkResult.Error(code = 404, message = "Not Found")
+ }
+ }
+
+ override suspend fun getLeagueListAsCurrentSeasonByTeam(
+ teamId: Int
+ ): NetworkResult> {
+ return if (teamId == 19) {
+ NetworkResult.Success(
+ listOf(
+ RemoteLeague(
+ leagueId = 1,
+ leagueName = "Premier League",
+ shortCode = "PL",
+ leagueImageUrl = "",
+ seasonId = 21366,
+ season = "2023/2024",
+ teamId = teamId
+ )
+ )
+ )
+ } else {
+ NetworkResult.Error(code = 404, message = "Not Found")
+ }
+ }
+
+ override suspend fun getPreviewRankListByTeamAndSeason(
+ teamId: Int,
+ seasonId: Int,
+ ): NetworkResult> {
+ return if (teamId == 19 && seasonId < 21367) {
+ NetworkResult.Success(listOf())
+ } else {
+ NetworkResult.Error(404, "Not Found")
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/network/src/main/java/com/eshc/goonersapp/core/network/model/match/RemoteMatchInformation.kt b/core/network/src/main/java/com/eshc/goonersapp/core/network/model/match/RemoteMatchInformation.kt
index 8da92a8d..0ff42d67 100644
--- a/core/network/src/main/java/com/eshc/goonersapp/core/network/model/match/RemoteMatchInformation.kt
+++ b/core/network/src/main/java/com/eshc/goonersapp/core/network/model/match/RemoteMatchInformation.kt
@@ -6,7 +6,6 @@ import kotlinx.serialization.Serializable
@Serializable
data class RemoteMatchInformation(
@SerialName("notablePlayer") val notablePlayer: NotablePlayer? = null,
- @SerialName("lineUp") val lineUp: List,
@SerialName("performance") val performance: Performance
)
@@ -14,28 +13,13 @@ data class RemoteMatchInformation(
data class NotablePlayer(
@SerialName("player_id") val playerId: Int,
@SerialName("player_name") val playerName: String,
- @SerialName("height") val height: Int,
- @SerialName("weight") val weight: Int,
- @SerialName("player_image_url") val playerImage: String,
- @SerialName("position") val position: String,
- @SerialName("position_initial") val positionInitial: String,
- @SerialName("goal_count") val goalCount: Int
-)
-
-@Serializable
-data class LineUp(
- @SerialName("lineup_id") val lineUpId: Double = 0.0,
- @SerialName("match_id") val matchId: Int = 0,
- @SerialName("player_id") val playerId: Int = 0,
- @SerialName("team_id") val teamId: Int = 0,
- @SerialName("player_name") val playerName: String = "",
- @SerialName("player_image_url") val playerImageUrl: String = "",
- @SerialName("jersey_number") val jerseyNumber: Int = 0,
- @SerialName("formation_field") val formationField: String? = "",
- @SerialName("formation_position") val formationPosition: Int? = 0,
- @SerialName("position_id") val positionId: Int = 0,
- @SerialName("position_category") val positionCategory: String = "",
- @SerialName("position_initial") val positionInitial: String = ""
+ @SerialName("height") val height: Int?,
+ @SerialName("weight") val weight: Int?,
+ @SerialName("player_image_url") val playerImage: String?,
+ @SerialName("position") val position: String?,
+ @SerialName("position_initial") val positionInitial: String?,
+ @SerialName("goal_count") val goalCount: Int?,
+ @SerialName("participation_count") val participationCount: Int?
)
@Serializable
diff --git a/core/network/src/main/java/com/eshc/goonersapp/core/network/model/match/RemoteMatchLineup.kt b/core/network/src/main/java/com/eshc/goonersapp/core/network/model/match/RemoteMatchLineup.kt
new file mode 100644
index 00000000..40cf2f0d
--- /dev/null
+++ b/core/network/src/main/java/com/eshc/goonersapp/core/network/model/match/RemoteMatchLineup.kt
@@ -0,0 +1,33 @@
+package com.eshc.goonersapp.core.network.model.match
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class RemoteMatchLineup(
+ @SerialName("home_lineup") val homeLineup : RemoteTeamLineup = RemoteTeamLineup(),
+ @SerialName("away_lineup") val awayLineup : RemoteTeamLineup = RemoteTeamLineup(),
+)
+
+@Serializable
+data class RemoteTeamLineup(
+ @SerialName("team_id") val teamId : Long = 0L,
+ @SerialName("formaition") val formation : String = "",
+ @SerialName("players") val players : List = emptyList()
+)
+
+@Serializable
+data class RemotePlayerLineup(
+ @SerialName("lineup_id") val lineUpId: Long = 0L,
+ @SerialName("match_id") val matchId: Int = 0,
+ @SerialName("player_id") val playerId: Int = 0,
+ @SerialName("team_id") val teamId: Int = 0,
+ @SerialName("player_name") val playerName: String = "",
+ @SerialName("player_image_url") val playerImageUrl: String = "",
+ @SerialName("jersey_number") val jerseyNumber: Int = 0,
+ @SerialName("formation_field") val formationField: String? = "",
+ @SerialName("formation_position") val formationPosition: Int? = 0,
+ @SerialName("position_id") val positionId: Int = 0,
+ @SerialName("position_category") val positionCategory: String = "",
+ @SerialName("position_initial") val positionInitial: String = ""
+)
\ No newline at end of file
diff --git a/core/network/src/main/java/com/eshc/goonersapp/core/network/remote/MatchNetworkDataSourceImpl.kt b/core/network/src/main/java/com/eshc/goonersapp/core/network/remote/MatchNetworkDataSourceImpl.kt
index 56adf276..18897080 100644
--- a/core/network/src/main/java/com/eshc/goonersapp/core/network/remote/MatchNetworkDataSourceImpl.kt
+++ b/core/network/src/main/java/com/eshc/goonersapp/core/network/remote/MatchNetworkDataSourceImpl.kt
@@ -7,6 +7,7 @@ import com.eshc.goonersapp.core.network.model.handleApi
import com.eshc.goonersapp.core.network.model.match.RemoteMatch
import com.eshc.goonersapp.core.network.model.match.RemoteMatchData
import com.eshc.goonersapp.core.network.model.match.RemoteMatchInformation
+import com.eshc.goonersapp.core.network.model.match.RemoteMatchLineup
import javax.inject.Inject
import javax.inject.Singleton
@@ -51,4 +52,10 @@ class MatchNetworkDataSourceImpl @Inject constructor(
matchNetworkService.getRecentlyMatch()
}
}
+
+ override suspend fun getMatchLineup(matchId: Int): NetworkResult {
+ return handleApi {
+ matchNetworkService.getMatchLineup(matchId)
+ }
+ }
}
diff --git a/core/network/src/main/java/com/eshc/goonersapp/core/network/remote/SeasonNetworkDataSourceImpl.kt b/core/network/src/main/java/com/eshc/goonersapp/core/network/remote/SeasonNetworkDataSourceImpl.kt
index 46359a2f..7425ffdc 100644
--- a/core/network/src/main/java/com/eshc/goonersapp/core/network/remote/SeasonNetworkDataSourceImpl.kt
+++ b/core/network/src/main/java/com/eshc/goonersapp/core/network/remote/SeasonNetworkDataSourceImpl.kt
@@ -1,12 +1,9 @@
package com.eshc.goonersapp.core.network.remote
-import com.eshc.goonersapp.core.network.PlayerNetworkDataSource
import com.eshc.goonersapp.core.network.SeasonNetworkDataSource
-import com.eshc.goonersapp.core.network.api.PlayerNetworkService
import com.eshc.goonersapp.core.network.api.SeasonNetworkService
import com.eshc.goonersapp.core.network.model.NetworkResult
import com.eshc.goonersapp.core.network.model.handleApi
-import com.eshc.goonersapp.core.network.model.player.RemotePlayer
import com.eshc.goonersapp.core.network.model.season.RemoteLeague
import com.eshc.goonersapp.core.network.model.season.RemoteRank
import com.eshc.goonersapp.core.network.model.season.RemoteSeason
diff --git a/core/network/src/test/java/com/eshc/goonersapp/core/network/FakeMatchDataSourceTest.kt b/core/network/src/test/java/com/eshc/goonersapp/core/network/FakeMatchDataSourceTest.kt
index f1c878b5..0d66131a 100644
--- a/core/network/src/test/java/com/eshc/goonersapp/core/network/FakeMatchDataSourceTest.kt
+++ b/core/network/src/test/java/com/eshc/goonersapp/core/network/FakeMatchDataSourceTest.kt
@@ -2,9 +2,10 @@ package com.eshc.goonersapp.core.network
import com.eshc.goonersapp.core.network.fake.FakeMatchDataSource
import com.eshc.goonersapp.core.network.model.NetworkResult
-import com.eshc.goonersapp.core.network.model.match.LineUp
-import com.eshc.goonersapp.core.network.model.match.RemoteMatchDetail
+import com.eshc.goonersapp.core.network.model.match.Performance
import com.eshc.goonersapp.core.network.model.match.RemoteMatch
+import com.eshc.goonersapp.core.network.model.match.RemoteMatchDetail
+import com.eshc.goonersapp.core.network.model.match.RemoteMatchLineup
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Before
@@ -52,8 +53,8 @@ class FakeMatchDataSourceTest {
when (result) {
is NetworkResult.Success -> {
assertEquals(
- listOf(),
- result.data.lineUp
+ Performance(),
+ result.data.performance
)
}
is NetworkResult.Error -> {
@@ -113,4 +114,19 @@ class FakeMatchDataSourceTest {
}
}
+
+ @Test
+ fun fakeGetMatchLineup() = runBlocking {
+ when (val result = fakeMatchDataSource.getMatchLineup(38)) {
+ is NetworkResult.Success -> {
+ assertEquals(
+ RemoteMatchLineup(),
+ result.data
+ )
+ }
+ is NetworkResult.Error -> { /* Nothing */ }
+ is NetworkResult.Exception -> { /* Nothing */ }
+ }
+
+ }
}
\ No newline at end of file
diff --git a/core/network/src/test/java/com/eshc/goonersapp/core/network/FakeSeasonDataSourceTest.kt b/core/network/src/test/java/com/eshc/goonersapp/core/network/FakeSeasonDataSourceTest.kt
new file mode 100644
index 00000000..71d7d8dc
--- /dev/null
+++ b/core/network/src/test/java/com/eshc/goonersapp/core/network/FakeSeasonDataSourceTest.kt
@@ -0,0 +1,132 @@
+package com.eshc.goonersapp.core.network
+
+import com.eshc.goonersapp.core.network.fake.FakeSeasonDataSource
+import com.eshc.goonersapp.core.network.model.NetworkResult
+import com.eshc.goonersapp.core.network.model.season.RemoteRank
+import kotlinx.coroutines.runBlocking
+import org.junit.Assert.assertEquals
+import org.junit.Assert.fail
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Created By KanuKim97
+ *
+ * [FakeSeasonDataSourceTest]
+ * - [FakeSeasonDataSource] test codes
+ */
+class FakeSeasonDataSourceTest {
+ private lateinit var fakeSeasonDataSource: FakeSeasonDataSource
+
+ @Before
+ fun setUp() {
+ fakeSeasonDataSource = FakeSeasonDataSource()
+ }
+
+ @Test
+ fun fake_get_season_list_by_team_as_success() = runBlocking {
+ when (val result = fakeSeasonDataSource.getSeasonListByTeam(19)) {
+ is NetworkResult.Success -> {
+ assertEquals(
+ "2023/2024",
+ result.data.first().season
+ )
+ }
+ is NetworkResult.Error -> {
+ fail("Test should not be reached here, excepted Network Result.Success")
+ }
+ is NetworkResult.Exception -> {
+ fail("Test should not be reached here, excepted Network Result.Success")
+ }
+ }
+ }
+
+ @Test
+ fun fake_get_season_list_by_team_as_error() = runBlocking {
+ when (val result = fakeSeasonDataSource.getSeasonListByTeam(20)) {
+ is NetworkResult.Error -> {
+ assertEquals(404, result.code)
+ }
+ is NetworkResult.Success -> {
+ fail("Test should not be reached here, excepted Network Result.Error")
+ }
+ is NetworkResult.Exception -> {
+ fail("Test should not be reached here, excepted Network Result.Error")
+ }
+ }
+ }
+
+ @Test
+ fun fake_get_league_list_as_current_season_by_team_as_success() = runBlocking {
+ when (val result = fakeSeasonDataSource.getLeagueListAsCurrentSeasonByTeam(19)) {
+ is NetworkResult.Success -> {
+ assertEquals(
+ 21366,
+ result.data.first().seasonId
+ )
+ }
+ is NetworkResult.Error -> {
+ fail("Test should not be reached here, excepted Network Result.Success")
+ }
+ is NetworkResult.Exception -> {
+ fail("Test should not be reached here, excepted Network Result.Success")
+ }
+ }
+ }
+
+ @Test
+ fun fake_get_league_list_as_current_season_by_team_as_error() = runBlocking {
+ when (val result = fakeSeasonDataSource.getLeagueListAsCurrentSeasonByTeam(20)) {
+ is NetworkResult.Error -> {
+ assertEquals(404, result.code)
+ }
+ is NetworkResult.Success -> {
+ fail("Test should not be reached here, excepted Network Result.Error")
+ }
+ is NetworkResult.Exception -> {
+ fail("Test should not be reached here, excepted Network Result.Error")
+ }
+ }
+ }
+
+ @Test
+ fun fake_get_preview_rank_list_by_team_and_season_as_success() = runBlocking {
+ val result = fakeSeasonDataSource.getPreviewRankListByTeamAndSeason(
+ teamId = 19,
+ seasonId = 21366
+ )
+
+ when (result) {
+ is NetworkResult.Success -> {
+ assertEquals(listOf(), result.data)
+ }
+ is NetworkResult.Error -> {
+ fail("Test should not be reached here, excepted Network Result.Success")
+ }
+ is NetworkResult.Exception -> {
+ fail("Test should not be reached here, excepted Network Result.Success")
+ }
+ }
+ }
+
+
+ @Test
+ fun fake_get_preview_rank_list_by_team_and_season_as_error() = runBlocking {
+ val result = fakeSeasonDataSource.getPreviewRankListByTeamAndSeason(
+ teamId = 20,
+ seasonId = 21366
+ )
+
+ when (result) {
+ is NetworkResult.Error -> {
+ assertEquals(404, result.code)
+ }
+ is NetworkResult.Success -> {
+ fail("Test should not be reached here, excepted Network Result.Error")
+ }
+ is NetworkResult.Exception -> {
+ fail("Test should not be reached here, excepted Network Result.Error")
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/network/src/test/java/com/eshc/goonersapp/core/network/RemoteMatchApiTest.kt b/core/network/src/test/java/com/eshc/goonersapp/core/network/RemoteMatchApiTest.kt
index c525ad49..24d0ca50 100644
--- a/core/network/src/test/java/com/eshc/goonersapp/core/network/RemoteMatchApiTest.kt
+++ b/core/network/src/test/java/com/eshc/goonersapp/core/network/RemoteMatchApiTest.kt
@@ -117,4 +117,16 @@ class RemoteMatchApiTest {
val response = matchApi.getRecentlyMatch()
assertEquals(responseOkCode, response.code())
}
+
+ /**
+ * (Test Passed)
+ *
+ * Match Lineup network communication test
+ * - when response code is 200, Test Passed
+ */
+ @Test
+ fun test_GET_LINEUP_STATUS_IS_OK() = runBlocking {
+ val response = matchApi.getMatchLineup(18138603)
+ assertEquals(responseOkCode, response.code())
+ }
}
\ No newline at end of file
diff --git a/feature/home/src/main/java/com/eshc/goonersapp/feature/home/HomeScreen.kt b/feature/home/src/main/java/com/eshc/goonersapp/feature/home/HomeScreen.kt
index d1eec783..2a51ebe7 100644
--- a/feature/home/src/main/java/com/eshc/goonersapp/feature/home/HomeScreen.kt
+++ b/feature/home/src/main/java/com/eshc/goonersapp/feature/home/HomeScreen.kt
@@ -3,7 +3,6 @@ package com.eshc.goonersapp.feature.home
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
@@ -23,6 +22,7 @@ import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.eshc.goonersapp.core.common.util.DateUtil
+import com.eshc.goonersapp.core.designsystem.theme.ColorFF181818
import com.eshc.goonersapp.core.designsystem.theme.GnrTypography
import com.eshc.goonersapp.feature.home.component.DashboardCard
import com.eshc.goonersapp.feature.home.component.RecentlyMatchCard
@@ -41,12 +41,8 @@ fun HomeRoute(
val recentlyResultUiState by viewModel.recentlyResultUiStateFlow.collectAsStateWithLifecycle()
Scaffold(
- topBar = {
- topBar()
- },
- bottomBar = {
- bottomBar()
- }
+ topBar = { topBar() },
+ bottomBar = { bottomBar() }
) { padding ->
HomeScreen(
modifier = Modifier.padding(padding),
@@ -64,13 +60,13 @@ fun HomeScreen(
) {
LazyColumn(
modifier = modifier,
- contentPadding = PaddingValues(top = 12.dp)
+ contentPadding = PaddingValues(top = 30.dp)
) {
item {
- Spacer(modifier = Modifier.height(12.dp))
Text(
- modifier = Modifier.padding(start = 8.dp),
text = "Team Dashboard",
+ modifier = Modifier.padding(start = 8.dp),
+ color = ColorFF181818,
style = GnrTypography.subtitleMedium
)
DashboardCard()
@@ -78,10 +74,10 @@ fun HomeScreen(
item {
Text(
- modifier = Modifier.padding(start = 8.dp),
text = "Upcoming Matches",
+ modifier = Modifier.padding(start = 8.dp),
+ color = ColorFF181818,
style = GnrTypography.subtitleMedium,
- color = Color.Black,
)
when (upcomingMatchesUiState) {
is UpcomingMatchesUiState.Loading -> {
diff --git a/feature/home/src/main/java/com/eshc/goonersapp/feature/home/component/MatchCard.kt b/feature/home/src/main/java/com/eshc/goonersapp/feature/home/component/MatchCard.kt
index 3c5c4ea3..f50b7af3 100644
--- a/feature/home/src/main/java/com/eshc/goonersapp/feature/home/component/MatchCard.kt
+++ b/feature/home/src/main/java/com/eshc/goonersapp/feature/home/component/MatchCard.kt
@@ -26,6 +26,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
+import androidx.compose.ui.text.style.LineBreak
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
@@ -39,6 +40,7 @@ import com.eshc.goonersapp.core.designsystem.theme.ColorFF4C68A7
import com.eshc.goonersapp.core.designsystem.theme.ColorFF9E9E9E
import com.eshc.goonersapp.core.designsystem.theme.ColorFFC3CDE2
import com.eshc.goonersapp.core.designsystem.theme.ColorFFDCDCDC
+import com.eshc.goonersapp.core.designsystem.theme.ColorFFE6EDFC
import com.eshc.goonersapp.core.designsystem.theme.ColorFFF7F9FF
import com.eshc.goonersapp.core.designsystem.theme.GnrTypography
import com.eshc.goonersapp.core.domain.model.match.MatchDetail
@@ -84,7 +86,7 @@ fun RecentlyMatchCard(
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
- modifier = modifier.fillMaxWidth(),
+ modifier = modifier.fillMaxWidth().padding(bottom = 15.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
@@ -95,7 +97,9 @@ fun RecentlyMatchCard(
competitionName = competitionName,
verticalAlignment = Alignment.CenterVertically,
)
- Row {
+ Column(
+ horizontalAlignment = Alignment.End
+ ) {
Text(
text = time,
color = ColorFF4C68A7,
@@ -104,8 +108,14 @@ fun RecentlyMatchCard(
Spacer(modifier = modifier.size(5.dp))
Text(
text = location,
- color = ColorFF4C68A7,
- style = GnrTypography.descriptionMedium
+ color = ColorFF9E9E9E,
+ style = GnrTypography.descriptionMedium.copy(
+ lineBreak = LineBreak(
+ strategy = LineBreak.Strategy.Balanced,
+ strictness = LineBreak.Strictness.Strict,
+ wordBreak = LineBreak.WordBreak.Default
+ )
+ )
)
}
}
@@ -303,9 +313,10 @@ fun UpcomingHomeTeamInfo(
modifier = modifier.size(30.dp),
contentDescription = "Home Team Logo"
)
- Spacer(modifier = modifier.size(10.dp))
+ Spacer(modifier = modifier.size(7.dp))
Text(
text = homeShortName,
+ color = ColorFF181818,
style = GnrTypography.subtitleMedium
)
}
@@ -325,7 +336,7 @@ fun UpcomingAwayTeamInfo(
text = awayShortName,
style = GnrTypography.subtitleMedium
)
- Spacer(modifier = modifier.size(10.dp))
+ Spacer(modifier = modifier.size(7.dp))
AsyncImage(
model = awayUrl,
modifier = modifier.size(30.dp),
@@ -350,7 +361,7 @@ fun UpcomingMatchDateInfo(
),
border = BorderStroke(
width = 0.5.dp,
- color = ColorFFC3CDE2
+ color = ColorFFE6EDFC
)
) {
Row(
@@ -360,6 +371,7 @@ fun UpcomingMatchDateInfo(
content = {
Text(
text = time,
+ color = ColorFF4C68A7,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = GnrTypography.body2Medium
@@ -367,6 +379,7 @@ fun UpcomingMatchDateInfo(
Spacer(modifier = Modifier.size(5.dp))
Text(
text = location,
+ color = ColorFF4C68A7,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = GnrTypography.body2Medium
diff --git a/feature/login/src/main/java/com/eshc/goonersapp/feature/login/LoginScreen.kt b/feature/login/src/main/java/com/eshc/goonersapp/feature/login/LoginScreen.kt
index 3f8ab2d4..22303d9d 100644
--- a/feature/login/src/main/java/com/eshc/goonersapp/feature/login/LoginScreen.kt
+++ b/feature/login/src/main/java/com/eshc/goonersapp/feature/login/LoginScreen.kt
@@ -16,23 +16,23 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.eshc.goonersapp.core.designsystem.component.GnrTextFiled
-import com.eshc.goonersapp.core.designsystem.component.TopBar
-import com.eshc.goonersapp.core.designsystem.theme.pretendard
+import com.eshc.goonersapp.core.designsystem.component.GnrTopBar
@Composable
fun LoginScreen(
onShowSnackbar: (String) -> Unit,
- onClickSignUp : () -> Unit
+ onClickSignUp : () -> Unit,
+ onBackIconClick: () -> Unit
) {
Column(
modifier = Modifier.fillMaxSize()
) {
- TopBar(
- title = "LOGIN"
+ GnrTopBar(
+ title = "LOGIN",
+ onBackIconClick = onBackIconClick
)
Image(
@@ -113,6 +113,7 @@ fun LoginScreen(
fun PreviewLoginScreen() {
LoginScreen(
onShowSnackbar = {},
- onClickSignUp = {}
+ onClickSignUp = {},
+ onBackIconClick = {}
)
}
\ No newline at end of file
diff --git a/feature/login/src/main/java/com/eshc/goonersapp/feature/login/SignUpScreen.kt b/feature/login/src/main/java/com/eshc/goonersapp/feature/login/SignUpScreen.kt
index 5d630db7..6e6e8677 100644
--- a/feature/login/src/main/java/com/eshc/goonersapp/feature/login/SignUpScreen.kt
+++ b/feature/login/src/main/java/com/eshc/goonersapp/feature/login/SignUpScreen.kt
@@ -24,13 +24,14 @@ import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.eshc.goonersapp.core.designsystem.component.GnrTextFiled
-import com.eshc.goonersapp.core.designsystem.component.TopBar
+import com.eshc.goonersapp.core.designsystem.component.GnrTopBar
import com.eshc.goonersapp.core.designsystem.theme.pretendard
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun SignUpScreen(
onShowSnackbar: (String) -> Unit,
+ onBackIconClick: () -> Unit,
viewModel: SignUpViewModel = hiltViewModel()
) {
val inputTypeList by viewModel.signUpInputTypeList.collectAsStateWithLifecycle()
@@ -41,8 +42,9 @@ fun SignUpScreen(
Column(
modifier = Modifier.fillMaxSize()
) {
- TopBar(
- title = "SIGN UP"
+ GnrTopBar(
+ title = "SIGN UP",
+ onBackIconClick = onBackIconClick
)
LazyColumn(
modifier = Modifier
@@ -125,5 +127,8 @@ fun SignUpScreen(
@Preview
@Composable
fun PreviewSignUpScreen() {
- SignUpScreen(onShowSnackbar = {})
+ SignUpScreen(
+ onShowSnackbar = {},
+ onBackIconClick = {}
+ )
}
\ No newline at end of file
diff --git a/feature/login/src/main/java/com/eshc/goonersapp/feature/login/navigation/LoginNavigation.kt b/feature/login/src/main/java/com/eshc/goonersapp/feature/login/navigation/LoginNavigation.kt
index 660763a4..c7a12b67 100644
--- a/feature/login/src/main/java/com/eshc/goonersapp/feature/login/navigation/LoginNavigation.kt
+++ b/feature/login/src/main/java/com/eshc/goonersapp/feature/login/navigation/LoginNavigation.kt
@@ -20,26 +20,30 @@ fun NavController.navigateToSignUp(navOptions: NavOptions? = null) {
fun NavGraphBuilder.loginScreen(
onShowSnackbar : (String) -> Unit,
- onClickSignUp : () -> Unit
+ onClickSignUp : () -> Unit,
+ onBackIconClick: () -> Unit
) {
composable(
route = loginNavigationRoute
) {
LoginScreen(
onShowSnackbar = onShowSnackbar,
- onClickSignUp = onClickSignUp
+ onClickSignUp = onClickSignUp,
+ onBackIconClick = onBackIconClick
)
}
}
fun NavGraphBuilder.signUpScreen(
- onShowSnackbar : (String) -> Unit
+ onShowSnackbar : (String) -> Unit,
+ onBackIconClick: () -> Unit
) {
composable(
route = signUpNavigationRoute
) {
SignUpScreen(
- onShowSnackbar = onShowSnackbar
+ onShowSnackbar = onShowSnackbar,
+ onBackIconClick = onBackIconClick
)
}
}
diff --git a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/component/formation/FootballFieldBox.kt b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/component/formation/FootballFieldBox.kt
new file mode 100644
index 00000000..49972f3e
--- /dev/null
+++ b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/component/formation/FootballFieldBox.kt
@@ -0,0 +1,130 @@
+package com.eshc.goonersapp.feature.match.component.formation
+
+import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.detectDragGestures
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.offset
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.rotate
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.drawscope.Stroke
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.layout.onGloballyPositioned
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.eshc.goonersapp.core.designsystem.theme.BrushMainGradient
+import com.eshc.goonersapp.core.designsystem.theme.Color88FFFFFF
+
+@Composable
+fun FootballFieldBox(
+ modifier: Modifier = Modifier,
+ rotateDegree : Float = 0f
+) {
+ Box(
+ modifier = modifier
+ .fillMaxSize()
+ .clip(RoundedCornerShape(10.dp))
+ .background(BrushMainGradient)
+ .rotate(rotateDegree),
+ contentAlignment = Alignment.Center
+ ) {
+ Canvas(
+ modifier = modifier
+ ) {
+ drawArc(
+ color = Color88FFFFFF,
+ startAngle = 0f,
+ sweepAngle = 180f,
+ useCenter = false,
+ style = Stroke(width = 3f),
+ size = Size(width = size.width * 0.3f, height = size.height * 0.3f),
+ topLeft = Offset(size.width * 0.35f, (size.height * 0.15f) * -1f)
+ )
+ drawLine(
+ color = Color88FFFFFF,
+ start = Offset(0f, 0f),
+ end = Offset(0f, size.height),
+ strokeWidth = 3f
+ )
+ drawLine(
+ color = Color88FFFFFF,
+ start = Offset(0f, size.height),
+ end = Offset(size.width, size.height),
+ strokeWidth = 3f
+ )
+ drawLine(
+ color = Color88FFFFFF,
+ start = Offset(size.width, size.height),
+ end = Offset(size.width, 0f),
+ strokeWidth = 3f
+ )
+ drawLine(
+ color = Color88FFFFFF,
+ start = Offset(size.width, 0f),
+ end = Offset(0f, 0f),
+ strokeWidth = 3f
+ )
+ drawLine(
+ color = Color88FFFFFF,
+ start = Offset(size.width * 0.3f, size.height),
+ end = Offset(size.width * 0.3f, size.height * 0.84f),
+ strokeWidth = 3f
+ )
+ drawLine(
+ color = Color88FFFFFF,
+ start = Offset(size.width * 0.3f, size.height * 0.84f),
+ end = Offset(size.width * 0.7f, size.height * 0.84f),
+ strokeWidth = 3f
+ )
+ drawLine(
+ color = Color88FFFFFF,
+ start = Offset(size.width * 0.7f, size.height * 0.84f),
+ end = Offset(size.width * 0.7f, size.height),
+ strokeWidth = 3f
+ )
+ drawLine(
+ color = Color88FFFFFF,
+ start = Offset(size.width * 0.4f, size.height),
+ end = Offset(size.width * 0.4f, size.height * 0.9f),
+ strokeWidth = 3f
+ )
+ drawLine(
+ color = Color88FFFFFF,
+ start = Offset(size.width * 0.4f, size.height * 0.9f),
+ end = Offset(size.width * 0.6f, size.height * 0.9f),
+ strokeWidth = 3f
+ )
+ drawLine(
+ color = Color88FFFFFF,
+ start = Offset(size.width * 0.6f, size.height * 0.9f),
+ end = Offset(size.width * 0.6f, size.height),
+ strokeWidth = 3f
+ )
+ }
+
+ }
+
+}
+
+@Preview
+@Composable
+fun PreviewFormationBox(){
+ FootballFieldBox()
+}
\ No newline at end of file
diff --git a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/component/formation/LineUpPlayerCard.kt b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/component/formation/LineUpPlayerCard.kt
new file mode 100644
index 00000000..17c1273c
--- /dev/null
+++ b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/component/formation/LineUpPlayerCard.kt
@@ -0,0 +1,59 @@
+package com.eshc.goonersapp.feature.match.component.formation
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import coil.compose.AsyncImage
+import com.eshc.goonersapp.core.designsystem.theme.ColorFFDCDCDC
+import com.eshc.goonersapp.core.designsystem.theme.GnrTypography
+import com.eshc.goonersapp.core.domain.model.match.PlayerLineup
+
+@Composable
+fun RowScope.LineUpPlayerCard(
+ player: PlayerLineup,
+ modifier: Modifier = Modifier
+) {
+ Column(
+ modifier = modifier
+ .wrapContentHeight()
+ .weight(1f),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ AsyncImage(
+ modifier = Modifier
+ .size(46.dp)
+ .clip(CircleShape)
+ .background(ColorFFDCDCDC),
+ contentScale = ContentScale.Crop,
+ model = player.playerImageUrl,
+ contentDescription = null
+ )
+ Text(
+ modifier = Modifier
+ .padding(top = 2.dp)
+ .height(24.dp),
+ text = player.playerName,
+ style = GnrTypography.descriptionMedium.copy(
+ lineHeight = 11.sp
+ ),
+ maxLines = 2,
+ textAlign = TextAlign.Center,
+ color = ColorFFDCDCDC
+
+ )
+ }
+}
diff --git a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchDetailScreen.kt b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchDetailScreen.kt
index 8b3c36f2..309e4470 100644
--- a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchDetailScreen.kt
+++ b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchDetailScreen.kt
@@ -4,24 +4,20 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
-import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
+import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
-import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -29,57 +25,77 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
-import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.text.SpanStyle
-import androidx.compose.ui.text.buildAnnotatedString
-import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import coil.compose.AsyncImage
import com.eshc.goonersapp.core.common.state.UiState
import com.eshc.goonersapp.core.common.util.DateUtil
import com.eshc.goonersapp.core.designsystem.IconPack
import com.eshc.goonersapp.core.designsystem.component.GnrTabItem
+import com.eshc.goonersapp.core.designsystem.component.GnrTopBar
import com.eshc.goonersapp.core.designsystem.component.MatchLeagueInfo
import com.eshc.goonersapp.core.designsystem.iconpack.IcTalk
import com.eshc.goonersapp.core.designsystem.theme.ColorFF10358A
import com.eshc.goonersapp.core.designsystem.theme.ColorFF777777
-import com.eshc.goonersapp.core.designsystem.theme.ColorFFC3CDE2
-import com.eshc.goonersapp.core.designsystem.theme.ColorFFF5F5F5
-import com.eshc.goonersapp.core.designsystem.theme.ColorFFFFFFFF
import com.eshc.goonersapp.core.designsystem.theme.GnrTypography
import com.eshc.goonersapp.core.domain.model.match.MatchDetail
+import com.eshc.goonersapp.core.domain.model.match.MatchInformation
+import com.eshc.goonersapp.core.domain.model.match.MatchLineup
import com.eshc.goonersapp.core.domain.model.match.getScoreHistoryList
import com.eshc.goonersapp.feature.match.model.MatchUiModel
import com.eshc.goonersapp.feature.match.state.MatchDetailUiState
@Composable
fun MatchDetailRootScreen(
- viewModel: MatchDetailViewModel = hiltViewModel(),
+ onBackIconClick: () -> Unit,
+ onShowSnackbar: (String) -> Unit,
onClickChat: (MatchUiModel) -> Unit,
- onShowSnackbar: (String) -> Unit
+ viewModel: MatchDetailViewModel = hiltViewModel(),
) {
val matchData by viewModel.matchDetailUiState.collectAsStateWithLifecycle()
- MatchDetailScreen(
- matchDetailUiState = matchData,
- onClickChat = onClickChat
- )
+ val lineup by viewModel.lineupUiState.collectAsStateWithLifecycle()
+ val matchInformation by viewModel.matchInformationState.collectAsStateWithLifecycle()
+
+ Scaffold(
+ topBar = {
+ GnrTopBar(
+ title = "",
+ onBackIconClick = onBackIconClick,
+ content = {
+ MatchDetailTopBar(
+ match = matchData.match
+ )
+ }
+ )
+ }
+ ) { paddingValues ->
+ MatchDetailScreen(
+ matchDetailUiState = matchData,
+ lineupUiState = lineup,
+ matchInformationState = matchInformation,
+ onClickChat = onClickChat,
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(paddingValues)
+ )
+ }
}
@Composable
fun MatchDetailScreen(
matchDetailUiState: MatchDetailUiState,
- onClickChat: (MatchUiModel) -> Unit
+ lineupUiState: UiState,
+ matchInformationState : UiState,
+ onClickChat: (MatchUiModel) -> Unit,
+ modifier: Modifier = Modifier
) {
var selectedTab by remember { mutableStateOf(DetailTab.SUMMARY) }
val match = matchDetailUiState.match
val matchDetail = matchDetailUiState.matchDetailState
+
Box(
- modifier = Modifier
+ modifier = modifier
.fillMaxSize()
.background(Color.White)
) {
@@ -88,113 +104,37 @@ fun MatchDetailScreen(
.fillMaxSize()
) {
item {
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .padding(horizontal = 12.dp, vertical = 20.dp),
- verticalAlignment = Alignment.CenterVertically
- ) {
- MatchLeagueInfo(
- logoSize = 25.dp,
- logoPadding = 4.dp,
- competitionUrl = match.leagueImageUrl,
- competitionName = "Premier league",
- verticalAlignment = Alignment.CenterVertically,
- )
-
- Column(
- modifier = Modifier
- .wrapContentHeight()
- .weight(1f),
- horizontalAlignment = Alignment.End
- ) {
- Text(
- text = DateUtil.getYearAndMonthAndDateAndDayAndTimeString(match.matchDate),
- style = GnrTypography.body1SemiBold,
- color = ColorFF10358A,
- )
- Text(
- modifier = Modifier.padding(top = 4.dp),
- text = match.stadiumName,
- style = GnrTypography.body2Regular,
- color = ColorFF777777,
- )
- }
- }
-
- val annotatedScore = if (match.isFinished) buildAnnotatedString {
- withStyle(style = SpanStyle(ColorFF10358A)) { append("${match.homeScore} ") }
- withStyle(style = SpanStyle(ColorFFC3CDE2)) { append(":") }
- withStyle(style = SpanStyle(ColorFF10358A)) { append(" ${match.awayScore}") }
- } else buildAnnotatedString {
- withStyle(style = SpanStyle(ColorFF10358A)) { append(" vs ") }
- }
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .wrapContentHeight()
- .padding(horizontal = 24.dp),
- verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.SpaceAround
- ) {
- TeamLogoImageBox(
- teamLogoImageUrl = match.homeTeamImageUrl
- )
-
- Text(
- modifier = Modifier.padding(horizontal = 8.dp),
- text = annotatedScore,
- style = GnrTypography.heading1Bold,
- )
-
- TeamLogoImageBox(
- teamLogoImageUrl = match.awayTeamImageUrl
- )
- }
-
+ MatchInfoBoard(
+ match
+ )
}
+
item {
- when(matchDetail){
- is UiState.Success -> {
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .padding(
- top = 20.dp
- )
- .height(IntrinsicSize.Min),
- horizontalArrangement = Arrangement.Center,
- content = {
- MatchScoredHistory(
- modifier = Modifier.weight(1f),
- horizontalAlignment = Alignment.End,
- matchScoreHistoryList = matchDetail.data.getScoreHistoryList(match.homeTeamId)
- )
- VerticalDivider(
- modifier = Modifier
- .fillMaxHeight()
- .padding(horizontal = 12.dp)
- )
- MatchScoredHistory(
- modifier = Modifier.weight(1f),
- horizontalAlignment = Alignment.Start,
- matchScoreHistoryList = matchDetail.data.getScoreHistoryList(match.awayTeamId)
- )
- }
- )
- }
- is UiState.Loading -> {
- Box(
- modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp),
- contentAlignment = Alignment.Center
- ){
- CircularProgressIndicator()
+ if(match.isFinished){
+ when (matchDetail) {
+ is UiState.Success -> {
+ MatchScoreBoard(
+ match = match,
+ matchDetailList = matchDetail.data
+ )
}
- }
- else -> {
+ is UiState.Loading -> {
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(vertical = 8.dp),
+ contentAlignment = Alignment.Center
+ ) {
+ CircularProgressIndicator()
+ }
+
+ }
+ else -> {
+ //TODOx
+ }
}
}
@@ -227,12 +167,13 @@ fun MatchDetailScreen(
item {
when (selectedTab) {
DetailTab.SUMMARY -> {
-
- }
-
- DetailTab.COMMENT -> {
-
+ SummaryScreen(
+ match = match,
+ lineupUiState = lineupUiState,
+ matchInformationState = matchInformationState
+ )
}
+ DetailTab.COMMENT -> { /* TODO("Not yet implemented") */ }
}
}
}
@@ -270,49 +211,13 @@ fun RowScope.MatchScoredHistory(
matchScoreHistoryList.forEach { history ->
Text(
text = history.scoringRecordText,
- color = ColorFF10358A,
+ color = if(history.teamId == 19) ColorFF10358A else ColorFF777777,
style = GnrTypography.descriptionMedium
)
}
}
}
-@Composable
-fun TeamLogoImageBox(
- teamLogoImageUrl: String,
- modifier: Modifier = Modifier
-) {
- Box(
- modifier = modifier
- .size(88.dp)
- .clip(CircleShape)
- .background(
- ColorFFF5F5F5
- ),
- contentAlignment = Alignment.Center
- ) {
- Box(
- modifier = Modifier
- .shadow(
- elevation = 3.dp,
- shape = CircleShape
- )
- .size(72.dp)
- .clip(CircleShape)
- .background(
- ColorFFFFFFFF
- ),
- contentAlignment = Alignment.Center
- ) {
- AsyncImage(
- modifier = Modifier.fillMaxWidth(0.65f),
- model = teamLogoImageUrl,
- contentDescription = null,
- contentScale = ContentScale.FillWidth
- )
- }
- }
-}
enum class DetailTab {
SUMMARY, COMMENT
diff --git a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchDetailTopBar.kt b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchDetailTopBar.kt
new file mode 100644
index 00000000..8ceb5d8b
--- /dev/null
+++ b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchDetailTopBar.kt
@@ -0,0 +1,41 @@
+package com.eshc.goonersapp.feature.match.detail
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.dp
+import coil.compose.AsyncImage
+import com.eshc.goonersapp.core.designsystem.theme.ColorFF181818
+import com.eshc.goonersapp.core.designsystem.theme.GnrTypography
+import com.eshc.goonersapp.feature.match.model.MatchUiModel
+
+@Composable
+fun MatchDetailTopBar(
+ match : MatchUiModel
+){
+ Row(
+ modifier = Modifier
+ .fillMaxWidth(),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.spacedBy(7.dp, alignment = Alignment.Start)
+ ) {
+ AsyncImage(
+ modifier = Modifier.size(25.dp),
+ model = match.leagueImageUrl,
+ contentDescription = "League Logo"
+ )
+ Text(
+ text = match.getMatchTitle(),
+ style = GnrTypography.subtitleSemiBold,
+ color = ColorFF181818,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis
+ )
+ }
+}
\ No newline at end of file
diff --git a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchDetailViewModel.kt b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchDetailViewModel.kt
index 09ecc92d..e8eff62f 100644
--- a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchDetailViewModel.kt
+++ b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchDetailViewModel.kt
@@ -5,7 +5,11 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.eshc.goonersapp.core.common.state.UiState
import com.eshc.goonersapp.core.domain.model.DataResult
+import com.eshc.goonersapp.core.domain.model.match.MatchInformation
+import com.eshc.goonersapp.core.domain.model.match.MatchLineup
import com.eshc.goonersapp.core.domain.usecase.match.GetMatchDetailUseCase
+import com.eshc.goonersapp.core.domain.usecase.match.GetMatchInformationUseCase
+import com.eshc.goonersapp.core.domain.usecase.match.GetMatchLineupUseCase
import com.eshc.goonersapp.feature.match.model.MatchUiModel
import com.eshc.goonersapp.feature.match.model.toUiModel
import com.eshc.goonersapp.feature.match.state.MatchDetailUiState
@@ -19,6 +23,8 @@ import javax.inject.Inject
@HiltViewModel
class MatchDetailViewModel @Inject constructor(
getMatchDetailUseCase : GetMatchDetailUseCase,
+ getMatchLineupUseCase: GetMatchLineupUseCase,
+ getMatchInformationUseCase: GetMatchInformationUseCase,
savedStateHandle: SavedStateHandle,
) : ViewModel() {
private val _match = savedStateHandle.getStateFlow(MATCH_SAVED_STATE_KEY,MatchUiModel(0))
@@ -49,6 +55,46 @@ class MatchDetailViewModel @Inject constructor(
started = SharingStarted.Eagerly
)
+ val lineupUiState : StateFlow> = getMatchLineupUseCase(
+ matchId = _match.value.id
+ ).map {
+ when(it){
+ is DataResult.Success -> {
+ UiState.Success(
+ it.data
+ )
+ }
+ is DataResult.Failure -> {
+ UiState.Error
+ }
+ }
+ }.stateIn(
+ scope = viewModelScope,
+ initialValue = UiState.Loading,
+ started = SharingStarted.Eagerly
+ )
+
+ val matchInformationState : StateFlow> = getMatchInformationUseCase(
+ match = _match.value.id,
+ opponent = _match.value.getOpponentTeamId(19),
+ season = _match.value.seasonId
+ ).map {
+ when(it){
+ is DataResult.Success -> {
+ UiState.Success(
+ it.data
+ )
+ }
+ is DataResult.Failure -> {
+ UiState.Error
+ }
+ }
+ }.stateIn(
+ scope = viewModelScope,
+ initialValue = UiState.Loading,
+ started = SharingStarted.Eagerly
+ )
+
companion object {
private const val MATCH_SAVED_STATE_KEY = "match"
}
diff --git a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchInfoBoard.kt b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchInfoBoard.kt
new file mode 100644
index 00000000..c4f2c011
--- /dev/null
+++ b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchInfoBoard.kt
@@ -0,0 +1,229 @@
+package com.eshc.goonersapp.feature.match.detail
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.IntrinsicSize
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.layout.widthIn
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.lazy.LazyItemScope
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.shadow
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.text.SpanStyle
+import androidx.compose.ui.text.buildAnnotatedString
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.withStyle
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import coil.compose.AsyncImage
+import com.eshc.goonersapp.core.common.util.DateUtil
+import com.eshc.goonersapp.core.designsystem.theme.ColorFF10358A
+import com.eshc.goonersapp.core.designsystem.theme.ColorFF181818
+import com.eshc.goonersapp.core.designsystem.theme.ColorFF777777
+import com.eshc.goonersapp.core.designsystem.theme.ColorFF889AC4
+import com.eshc.goonersapp.core.designsystem.theme.ColorFFC3CDE2
+import com.eshc.goonersapp.core.designsystem.theme.ColorFFF5F5F5
+import com.eshc.goonersapp.core.designsystem.theme.ColorFFFFFFFF
+import com.eshc.goonersapp.core.designsystem.theme.GnrTypography
+import com.eshc.goonersapp.feature.match.model.MatchUiModel
+
+@Composable
+fun LazyItemScope.MatchInfoBoard(
+ match: MatchUiModel
+) {
+
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .wrapContentHeight()
+ .padding(horizontal = 24.dp),
+ horizontalArrangement = Arrangement.SpaceAround
+ ) {
+ TeamLogoImageBox(
+ modifier = Modifier
+ .wrapContentHeight()
+ .weight(1f),
+ teamLogoImageUrl = match.homeTeamImageUrl,
+ teamName = match.homeTeamName
+ )
+
+ if (match.isFinished) {
+ MatchResultBoard(
+ match
+ )
+ } else {
+ MatchFixtureBoard(
+ match
+ )
+ }
+
+ TeamLogoImageBox(
+ modifier = Modifier
+ .wrapContentHeight()
+ .weight(1f),
+ teamLogoImageUrl = match.awayTeamImageUrl,
+ teamName = match.awayTeamName
+ )
+ }
+}
+
+
+@Composable
+fun RowScope.MatchFixtureBoard(
+ match: MatchUiModel,
+ modifier: Modifier = Modifier
+) {
+ Column(
+ modifier = modifier.padding(horizontal = 8.dp),
+ horizontalAlignment = Alignment.CenterHorizontally
+
+ ) {
+ Column(
+ modifier = Modifier
+ .height(78.dp),
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Text(
+ text = DateUtil.getMonthAndDateAndDayString(match.matchDate),
+ style = GnrTypography.heading2SemiBold,
+ color = ColorFF889AC4
+ )
+ Text(
+ text = DateUtil.getTimeString(match.matchDate),
+ style = GnrTypography.heading2SemiBold,
+ color = ColorFF10358A
+ )
+
+ }
+ Text(
+ modifier = Modifier
+ .padding(top = 3.dp)
+ .widthIn(max = 140.dp),
+ text = match.stadiumName,
+ textAlign = TextAlign.Center,
+ style = GnrTypography.body2Regular,
+ color = ColorFF777777
+ )
+ }
+}
+
+@Composable
+fun RowScope.MatchResultBoard(
+ match: MatchUiModel,
+ modifier: Modifier = Modifier
+) {
+ val annotatedScore = if (match.isFinished) buildAnnotatedString {
+ withStyle(style = SpanStyle(ColorFF10358A)) { append("${match.homeScore} ") }
+ withStyle(style = SpanStyle(ColorFFC3CDE2)) { append(":") }
+ withStyle(style = SpanStyle(ColorFF10358A)) { append(" ${match.awayScore}") }
+ } else buildAnnotatedString {
+ withStyle(style = SpanStyle(ColorFF10358A)) { append(" vs ") }
+ }
+ Column(
+ modifier = modifier
+ .width(IntrinsicSize.Min)
+ .padding(horizontal = 8.dp),
+ horizontalAlignment = Alignment.CenterHorizontally
+
+ ) {
+ Column(
+ modifier = Modifier
+ .width(IntrinsicSize.Max)
+ .height(78.dp),
+ verticalArrangement = Arrangement.spacedBy(6.dp, Alignment.CenterVertically),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Text(
+ text = annotatedScore,
+ style = GnrTypography.heading1Bold.copy(
+ fontSize = 28.sp
+ ),
+ )
+ Text(
+ text = DateUtil.getYearAndMonthAndDateAndDayAndTimeString(match.matchDate),
+ style = GnrTypography.body1Medium,
+ color = ColorFF777777
+ )
+
+ }
+ Text(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(top = 3.dp),
+ text = match.stadiumName,
+ textAlign = TextAlign.Center,
+ style = GnrTypography.body2Regular,
+ color = ColorFF777777
+ )
+ }
+
+
+}
+
+
+@Composable
+fun TeamLogoImageBox(
+ teamName: String,
+ teamLogoImageUrl: String,
+ modifier: Modifier = Modifier
+) {
+ Column(
+ modifier = modifier,
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Box(
+ modifier = Modifier
+ .size(78.dp)
+ .clip(CircleShape)
+ .background(
+ ColorFFF5F5F5
+ ),
+ contentAlignment = Alignment.Center
+ ) {
+ Box(
+ modifier = Modifier
+ .shadow(
+ elevation = 3.dp,
+ shape = CircleShape
+ )
+ .size(64.dp)
+ .clip(CircleShape)
+ .background(
+ ColorFFFFFFFF
+ ),
+ contentAlignment = Alignment.Center
+ ) {
+ AsyncImage(
+ modifier = Modifier.fillMaxWidth(0.65f),
+ model = teamLogoImageUrl,
+ contentDescription = null,
+ contentScale = ContentScale.FillWidth
+ )
+ }
+ }
+
+ Text(
+ modifier = Modifier.padding(top = 3.dp),
+ text = teamName,
+ textAlign = TextAlign.Center,
+ color = ColorFF181818,
+ style = GnrTypography.body2SemiBold
+ )
+ }
+
+}
diff --git a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchScoreBoard.kt b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchScoreBoard.kt
new file mode 100644
index 00000000..f5921cd1
--- /dev/null
+++ b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/MatchScoreBoard.kt
@@ -0,0 +1,58 @@
+package com.eshc.goonersapp.feature.match.detail
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.IntrinsicSize
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyItemScope
+import androidx.compose.material3.Icon
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.unit.dp
+import com.eshc.goonersapp.core.domain.model.match.MatchDetail
+import com.eshc.goonersapp.core.domain.model.match.getScoreHistoryList
+import com.eshc.goonersapp.feature.match.model.MatchUiModel
+
+@Composable
+fun LazyItemScope.MatchScoreBoard(
+ match: MatchUiModel,
+ matchDetailList: List
+) {
+ if(match.isScorelessMatch) return
+
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(
+ top = 20.dp
+ )
+ .height(IntrinsicSize.Min),
+ horizontalArrangement = Arrangement.spacedBy(15.dp, Alignment.CenterHorizontally),
+ content = {
+ MatchScoredHistory(
+ modifier = Modifier.weight(1f),
+ horizontalAlignment = Alignment.End,
+ matchScoreHistoryList = matchDetailList.getScoreHistoryList(
+ match.homeTeamId
+ )
+ )
+ Icon(
+ modifier = Modifier.size(12.dp),
+ painter = painterResource(id = com.eshc.goonersapp.core.designsystem.R.drawable.ic_ball),
+ contentDescription = "ball"
+ )
+ MatchScoredHistory(
+ modifier = Modifier.weight(1f),
+ horizontalAlignment = Alignment.Start,
+ matchScoreHistoryList = matchDetailList.getScoreHistoryList(
+ match.awayTeamId
+ )
+ )
+ }
+ )
+}
\ No newline at end of file
diff --git a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/SummaryScreen.kt b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/SummaryScreen.kt
new file mode 100644
index 00000000..4f6877c0
--- /dev/null
+++ b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/detail/SummaryScreen.kt
@@ -0,0 +1,398 @@
+package com.eshc.goonersapp.feature.match.detail
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.IntrinsicSize
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.widthIn
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.CardDefaults
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.Text
+import androidx.compose.material3.VerticalDivider
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import coil.compose.AsyncImage
+import com.eshc.goonersapp.core.common.state.UiState
+import com.eshc.goonersapp.core.designsystem.component.GnrElevatedCard
+import com.eshc.goonersapp.core.designsystem.ext.gnrElevatedCardBorder
+import com.eshc.goonersapp.core.designsystem.theme.Color88FFFFFF
+import com.eshc.goonersapp.core.designsystem.theme.ColorFF10358A
+import com.eshc.goonersapp.core.designsystem.theme.ColorFF181818
+import com.eshc.goonersapp.core.designsystem.theme.ColorFF4C68A7
+import com.eshc.goonersapp.core.designsystem.theme.ColorFF889AC4
+import com.eshc.goonersapp.core.designsystem.theme.ColorFFDCDCDC
+import com.eshc.goonersapp.core.designsystem.theme.ColorFFE6EDFC
+import com.eshc.goonersapp.core.designsystem.theme.ColorFFFFFFFF
+import com.eshc.goonersapp.core.designsystem.theme.GnrTypography
+import com.eshc.goonersapp.core.domain.model.match.MatchInformation
+import com.eshc.goonersapp.core.domain.model.match.MatchLineup
+import com.eshc.goonersapp.core.domain.model.match.NotablePlayer
+import com.eshc.goonersapp.core.domain.model.match.Performance
+import com.eshc.goonersapp.feature.match.component.formation.FootballFieldBox
+import com.eshc.goonersapp.feature.match.component.formation.LineUpPlayerCard
+import com.eshc.goonersapp.feature.match.model.MatchUiModel
+
+@Composable
+fun SummaryScreen(
+ match : MatchUiModel,
+ lineupUiState: UiState,
+ matchInformationState: UiState,
+) {
+ Column(
+ modifier = Modifier
+ .padding(start = 14.dp, end = 14.dp, top = 22.dp, bottom = 10.dp)
+ ) {
+ when (lineupUiState) {
+ is UiState.Success -> {
+ Text(
+ text = "Line-Ups",
+ modifier = Modifier.padding(bottom = 16.dp),
+ style = GnrTypography.subtitleMedium,
+ color = ColorFF181818
+ )
+
+ LineUpBox(
+ matchLineup = lineupUiState.data,
+ modifier = Modifier.padding(bottom = 70.dp)
+ )
+ }
+
+ is UiState.Loading -> {
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(360.dp),
+ contentAlignment = Alignment.Center
+ ) {
+ CircularProgressIndicator()
+ }
+ }
+
+ else -> {
+
+ }
+ }
+ when (matchInformationState) {
+ is UiState.Success -> {
+ matchInformationState.data.notablePlayer?.let {
+ Text(
+ text = "Player To Watch For",
+ modifier = Modifier.padding(bottom = 16.dp),
+ style = GnrTypography.subtitleMedium,
+ color = ColorFF181818
+ )
+ PlayerToWatchForBox(
+ player = it,
+ modifier = Modifier
+ .padding(bottom = 70.dp)
+ .fillMaxWidth()
+ )
+ }
+
+ Text(
+ text = "Head To Head",
+ modifier = Modifier.padding(bottom = 16.dp),
+ style = GnrTypography.subtitleMedium,
+ color = ColorFF181818
+ )
+ HeadToHeadBox(
+ opponentTeamName = match.getOpponentTeamName(19),
+ performance = matchInformationState.data.performance,
+ modifier = Modifier.padding(bottom = 70.dp)
+ )
+
+ }
+
+ is UiState.Loading -> {
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(40.dp),
+ contentAlignment = Alignment.Center
+ ) {
+ CircularProgressIndicator()
+ }
+ }
+
+ else -> {
+
+ }
+ }
+ }
+}
+
+@Composable
+fun LineUpBox(
+ matchLineup: MatchLineup,
+ modifier: Modifier = Modifier
+) {
+ Box(
+ modifier = modifier
+ .fillMaxWidth()
+ .height(IntrinsicSize.Max)
+ ) {
+ FootballFieldBox(
+ modifier = Modifier.fillMaxSize(),
+ rotateDegree = 180f
+ )
+ PlayerLineUpBox(
+ matchLineup = matchLineup
+ )
+ }
+}
+
+
+@Composable
+fun PlayerToWatchForBox(
+ player: NotablePlayer,
+ modifier: Modifier = Modifier
+) {
+ Box(
+ modifier = modifier.background(
+ color = ColorFFE6EDFC,
+ shape = RoundedCornerShape(10.dp)
+ )
+ ) {
+ Column(
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ Row(
+ modifier = Modifier
+ .padding(top = 10.dp, bottom = 8.dp, end = 12.dp)
+ ) {
+ Text(
+ modifier = Modifier
+ .wrapContentHeight()
+ .weight(0.45f)
+ .padding(end = 18.dp),
+ text = "",
+ style = GnrTypography.heading2SemiBold,
+ color = ColorFF889AC4,
+ textAlign = TextAlign.End
+ )
+ Column(
+ modifier = Modifier
+ .wrapContentHeight()
+ .weight(0.55f)
+ ) {
+ Text(
+ text = player.playerName,
+ style = GnrTypography.body1Medium,
+ color = ColorFF10358A
+ )
+ Text(
+ text = player.playerPosition,
+ style = GnrTypography.descriptionRegular,
+ color = ColorFF10358A
+ )
+ }
+ }
+ PlayerStatToWatchForRow(
+ title = "Games",
+ stat = "${player.playerParticipationCount}",
+ modifier = Modifier.padding(bottom = 3.dp)
+ )
+ PlayerStatToWatchForRow(
+ title = "Goals",
+ stat = "${player.playerGoalCount}",
+ modifier = Modifier
+ )
+ }
+ Box(
+ modifier = Modifier.fillMaxWidth(0.4f),
+ contentAlignment = Alignment.BottomCenter
+ ) {
+ AsyncImage(
+ modifier = Modifier
+ .fillMaxWidth(0.85f),
+ model = player.playerImageUrl,
+ contentDescription = "player"
+ )
+ }
+
+ }
+}
+
+@Composable
+fun PlayerStatToWatchForRow(
+ title: String,
+ stat: String,
+ modifier: Modifier = Modifier
+) {
+ Row(
+ modifier = modifier
+ .background(color = Color88FFFFFF)
+ .padding(top = 10.dp, bottom = 8.dp, end = 12.dp)
+ ) {
+ Spacer(
+ modifier = Modifier
+ .wrapContentHeight()
+ .weight(0.45f)
+ )
+ Text(
+ modifier = Modifier
+ .wrapContentHeight()
+ .weight(0.45f),
+ text = title,
+ style = GnrTypography.body1Medium,
+ color = ColorFF181818
+ )
+ Text(
+ modifier = Modifier
+ .wrapContentHeight()
+ .weight(0.1f),
+ text = stat,
+ maxLines = 1,
+ textAlign = TextAlign.Center,
+ style = GnrTypography.body1Medium,
+ color = ColorFF10358A
+ )
+ }
+}
+
+@Composable
+fun PlayerLineUpBox(
+ matchLineup: MatchLineup
+) {
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(start = 12.dp, end = 12.dp, top = 16.dp, bottom = 16.dp),
+ verticalArrangement = Arrangement.spacedBy(26.dp)
+ ) {
+ matchLineup.getMyTeamLineup(19).groupStartingPlayersByPosition().forEach { players ->
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .weight(1f),
+ horizontalArrangement = Arrangement.SpaceAround
+ ) {
+ players.forEach { player ->
+ LineUpPlayerCard(
+ player = player
+ )
+ }
+
+ }
+ }
+ }
+}
+
+@Composable
+fun HeadToHeadBox(
+ opponentTeamName: String,
+ performance: Performance,
+ modifier: Modifier = Modifier
+) {
+ GnrElevatedCard(
+ colors = CardDefaults.cardColors(containerColor = ColorFFFFFFFF),
+ radius = 10.dp,
+ modifier = modifier
+ .fillMaxWidth()
+ .height(IntrinsicSize.Max)
+ .gnrElevatedCardBorder(10.dp)
+ ) {
+ Column(
+ modifier = Modifier.padding(top = 20.dp, bottom = 13.dp),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.spacedBy(13.dp)
+ ) {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.Center,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Text(
+ modifier = Modifier.padding(end = 10.dp),
+ text = "VS",
+ style = GnrTypography.subtitleMedium,
+ color = ColorFF4C68A7
+ )
+ AsyncImage(
+ modifier = Modifier.size(34.dp),
+ model = performance.opponentImageUrl,
+ contentDescription = "teamLogo",
+ contentScale = ContentScale.Crop
+ )
+ Text(
+ modifier = Modifier
+ .padding(start = 6.dp)
+ .widthIn(max = 120.dp),
+ text = opponentTeamName,
+ style = GnrTypography.body2Medium,
+ color = ColorFF181818, textAlign = TextAlign.Center
+ )
+ }
+ Row(
+ modifier = Modifier.fillMaxWidth().padding(),
+ horizontalArrangement = Arrangement.spacedBy(20.dp,Alignment.CenterHorizontally),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ MatchRecordText(
+ resultType = "Win",
+ resultCount = performance.win,
+ color = ColorFF10358A
+ )
+ VerticalDivider(
+ modifier = Modifier.height(25.dp),
+ thickness = 1.dp,
+ color = ColorFFDCDCDC
+ )
+ MatchRecordText(
+ resultType = "Draw",
+ resultCount = performance.draw,
+ color = ColorFF181818
+ )
+ VerticalDivider(
+ modifier = Modifier.height(25.dp),
+ thickness = 1.dp,
+ color = ColorFFDCDCDC
+ )
+ MatchRecordText(
+ resultType = "Loss",
+ resultCount = performance.lose,
+ color = ColorFF181818
+ )
+ }
+ }
+ }
+}
+
+@Composable
+fun MatchRecordText(
+ resultType : String,
+ resultCount : Int,
+ color : Color
+){
+ Row(
+ verticalAlignment = Alignment.CenterVertically
+ ){
+ Text(
+ modifier = Modifier
+ .padding(end = 6.dp),
+ text = resultType,
+ style = GnrTypography.body1Medium,
+ color = color
+ )
+ Text(
+ text = "$resultCount",
+ style = GnrTypography.heading1SemiBold,
+ color = color
+ )
+ }
+}
\ No newline at end of file
diff --git a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/model/MatchUiModel.kt b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/model/MatchUiModel.kt
index c761cff5..2539c6b1 100644
--- a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/model/MatchUiModel.kt
+++ b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/model/MatchUiModel.kt
@@ -12,33 +12,64 @@ import java.nio.charset.StandardCharsets
@Serializable
@Parcelize
data class MatchUiModel(
- val id :Int,
- val homeTeamName : String = "",
- val homeTeamImageUrl : String = "",
- val awayTeamName : String = "",
- val awayTeamImageUrl : String = "",
- val matchDate : String = "",
- val homeScore :Int = 0,
- val awayScore :Int = 0,
- val homeTeamId : Int = 0,
- val awayTeamId : Int = 0,
- val round :Int = 0,
- val isFinished :Boolean = false,
- val stadiumName : String = "",
- val leagueImageUrl : String = "",
+ val id: Int,
+ val seasonId: Int = 0,
+ val homeTeamName: String = "",
+ val homeTeamNickname: String = "",
+ val homeTeamImageUrl: String = "",
+ val awayTeamName: String = "",
+ val awayTeamNickname: String = "",
+ val awayTeamImageUrl: String = "",
+ val matchDate: String = "",
+ val homeScore: Int = 0,
+ val awayScore: Int = 0,
+ val homeTeamId: Int = 0,
+ val awayTeamId: Int = 0,
+ val round: Int = 0,
+ val isFinished: Boolean = false,
+ val stadiumName: String = "",
+ val leagueImageUrl: String = "",
) : Parcelable {
+ val isScorelessMatch: Boolean
+ get() = homeScore == 0 && awayScore == 0
+
override fun toString(): String {
return URLEncoder.encode(
Json.encodeToString(this),
StandardCharsets.UTF_8.toString()
)
}
+
+ fun getMatchTitle(): String {
+ val homeTeamNameTitle =
+ if (homeTeamNickname.isBlank() && homeTeamName.length >= 2) homeTeamName.substring(0..2)
+ .uppercase()
+ else homeTeamNickname
+
+ val awayTeamNameTitle =
+ if (awayTeamNickname.isBlank() && awayTeamName.length >= 2) awayTeamName.substring(0..2)
+ .uppercase()
+ else awayTeamNickname
+
+ return "$homeTeamNameTitle vs $awayTeamNameTitle"
+ }
+
+ fun getOpponentTeamId(myTeamId: Int): Int {
+ return if (homeTeamId == myTeamId) awayTeamId
+ else homeTeamId
+ }
+
+ fun getOpponentTeamName(myTeamId: Int): String {
+ return if (homeTeamId == myTeamId) awayTeamName
+ else homeTeamName
+ }
}
fun Match.toUiModel() = MatchUiModel(
id = id,
+ seasonId = seasonId,
homeTeamName = homeTeamName,
- homeTeamImageUrl= homeTeamImageUrl,
+ homeTeamImageUrl = homeTeamImageUrl,
homeTeamId = homeTeamId,
awayTeamName = awayTeamName,
awayTeamImageUrl = awayTeamImageUrl,
diff --git a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/navigation/MatchNavigation.kt b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/navigation/MatchNavigation.kt
index 62dd8bac..b1a3615e 100644
--- a/feature/match/src/main/java/com/eshc/goonersapp/feature/match/navigation/MatchNavigation.kt
+++ b/feature/match/src/main/java/com/eshc/goonersapp/feature/match/navigation/MatchNavigation.kt
@@ -45,17 +45,17 @@ fun NavGraphBuilder.matchScreen(
fun NavGraphBuilder.matchDetailScreen(
+ onBackIconClick: () -> Unit,
onClickChat : (MatchUiModel) -> Unit,
onShowSnackbar : (String) -> Unit
) {
composable(
route = "$matchDetailNavigationRoute?$matchArg={$matchArg}",
- arguments = listOf(
- navArgument(matchArg) { type = MatchType },
- ),
+ arguments = listOf(navArgument(matchArg) { type = MatchType })
) {
MatchDetailRootScreen(
onClickChat = onClickChat,
+ onBackIconClick = onBackIconClick,
onShowSnackbar = onShowSnackbar
)
}
diff --git a/feature/team/src/main/java/com/eshc/goonersapp/feature/team/club/ClubDetailScreen.kt b/feature/team/src/main/java/com/eshc/goonersapp/feature/team/club/ClubDetailScreen.kt
index 26649663..48910824 100644
--- a/feature/team/src/main/java/com/eshc/goonersapp/feature/team/club/ClubDetailScreen.kt
+++ b/feature/team/src/main/java/com/eshc/goonersapp/feature/team/club/ClubDetailScreen.kt
@@ -32,16 +32,16 @@ import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil.compose.AsyncImage
-import com.eshc.goonersapp.core.common.util.DateUtil
-import com.eshc.goonersapp.core.designsystem.component.TopBar
+import com.eshc.goonersapp.core.designsystem.component.GnrTopBar
import com.eshc.goonersapp.core.designsystem.theme.pretendard
import com.eshc.goonersapp.core.domain.model.match.Match
import com.eshc.goonersapp.feature.team.state.ClubDetailUiState
@Composable
fun ClubDetailRoute(
- clubDetailViewModel: ClubDetailViewModel = hiltViewModel(),
- onShowSnackbar : (String) -> Unit
+ onBackIconClick: () -> Unit,
+ onShowSnackbar : (String) -> Unit,
+ clubDetailViewModel: ClubDetailViewModel = hiltViewModel()
) {
val clubDetailUiState by clubDetailViewModel.clubDetail.collectAsStateWithLifecycle()
@@ -52,19 +52,22 @@ fun ClubDetailRoute(
}
ClubDetailScreen(
- clubDetailUiState
+ onBackIconClick = onBackIconClick,
+ clubDetailUiState = clubDetailUiState
)
}
@Composable
fun ClubDetailScreen(
+ onBackIconClick: () -> Unit,
clubDetailUiState: ClubDetailUiState
) {
Column(
modifier = Modifier.fillMaxSize()
) {
- TopBar(
- title = "CLUB"
+ GnrTopBar(
+ title = "CLUB",
+ onBackIconClick = onBackIconClick
)
when(clubDetailUiState){
is ClubDetailUiState.Success -> {
diff --git a/feature/team/src/main/java/com/eshc/goonersapp/feature/team/detail/PlayerDetailScreen.kt b/feature/team/src/main/java/com/eshc/goonersapp/feature/team/detail/PlayerDetailScreen.kt
index 757e8bf2..1f0e6174 100644
--- a/feature/team/src/main/java/com/eshc/goonersapp/feature/team/detail/PlayerDetailScreen.kt
+++ b/feature/team/src/main/java/com/eshc/goonersapp/feature/team/detail/PlayerDetailScreen.kt
@@ -1,6 +1,8 @@
package com.eshc.goonersapp.feature.team.detail
+import android.annotation.SuppressLint
import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -19,9 +21,14 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -38,33 +45,72 @@ import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil.compose.AsyncImage
+import com.eshc.goonersapp.core.designsystem.IconPack
import com.eshc.goonersapp.core.designsystem.component.GnrElevatedCard
import com.eshc.goonersapp.core.designsystem.component.GnrTabItem
import com.eshc.goonersapp.core.designsystem.ext.gnrElevatedCardBorder
+import com.eshc.goonersapp.core.designsystem.iconpack.IcIosArrowBack
+import com.eshc.goonersapp.core.designsystem.iconpack.IcNotification
import com.eshc.goonersapp.core.designsystem.theme.ColorFF10358A
import com.eshc.goonersapp.core.designsystem.theme.ColorFF181818
+import com.eshc.goonersapp.core.designsystem.theme.ColorFF720509
+import com.eshc.goonersapp.core.designsystem.theme.ColorFFC10006
import com.eshc.goonersapp.core.designsystem.theme.ColorFFF5F5F5
import com.eshc.goonersapp.core.designsystem.theme.ColorFFFFFFFF
import com.eshc.goonersapp.core.designsystem.theme.GnrTypography
import com.eshc.goonersapp.core.domain.model.player.Player
import com.eshc.goonersapp.feature.team.state.PlayerDetailUiState
+@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
+@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PlayerDetailRootScreen(
+ onBackIconClick: () -> Unit,
onShowSnackbar: (String) -> Unit,
viewModel : PlayerDetailViewModel = hiltViewModel()
) {
val playerDetailUiState by viewModel.playerDetailUiState.collectAsStateWithLifecycle()
var selectedTab by remember { mutableStateOf(DetailTab.PROFILE) }
- PlayerDetailScreen(
- playerDetailUiState = playerDetailUiState,
- selectedTab = selectedTab,
- onShowSnackbar = onShowSnackbar,
- onUpdateTab = {
- selectedTab = it
+ Scaffold(
+ topBar = {
+ TopAppBar(
+ title = { /*TODO*/ },
+ modifier = Modifier.fillMaxWidth(),
+ navigationIcon = {
+ Icon(
+ imageVector = IconPack.IcIosArrowBack,
+ contentDescription = null,
+ modifier = Modifier
+ .padding(horizontal = 8.dp)
+ .size(24.dp)
+ .clickable(onClick = onBackIconClick),
+ tint = ColorFFFFFFFF
+ )
+ },
+ actions = {
+ Icon(
+ imageVector = IconPack.IcNotification,
+ contentDescription = null,
+ modifier = Modifier
+ .padding(horizontal = 8.dp)
+ .size(24.dp)
+ .clickable { /* TODO("Not yet implemented") */ },
+ tint = ColorFFFFFFFF
+ )
+ },
+ colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent)
+ )
}
- )
+ ) { _ ->
+ PlayerDetailScreen(
+ playerDetailUiState = playerDetailUiState,
+ selectedTab = selectedTab,
+ onShowSnackbar = onShowSnackbar,
+ onUpdateTab = { tab -> selectedTab = tab },
+ modifier = Modifier
+ )
+ }
}
@@ -73,9 +119,11 @@ fun PlayerDetailScreen(
playerDetailUiState : PlayerDetailUiState,
selectedTab : DetailTab,
onShowSnackbar: (String) -> Unit,
- onUpdateTab : (DetailTab) -> Unit
+ onUpdateTab : (DetailTab) -> Unit,
+ modifier: Modifier = Modifier
) {
Surface(
+ modifier = modifier,
color = ColorFFFFFFFF
) {
when (playerDetailUiState) {
@@ -183,8 +231,8 @@ fun PlayerDetailImage(
.background(
Brush.verticalGradient(
listOf(
- Color(0xFFC10006),
- Color(0xFF720509)
+ ColorFFC10006,
+ ColorFF720509
)
)
),
@@ -218,7 +266,7 @@ fun PlayerDetailImage(
)
PlayerDetailBackNumberChip(
backNumber = player.backNumber,
- backgroundColor = Color(0xFFC10006),
+ backgroundColor = ColorFFC10006
)
}
Text(
diff --git a/feature/team/src/main/java/com/eshc/goonersapp/feature/team/history/TeamHistoryScreen.kt b/feature/team/src/main/java/com/eshc/goonersapp/feature/team/history/TeamHistoryScreen.kt
index 03faf120..52fb4a54 100644
--- a/feature/team/src/main/java/com/eshc/goonersapp/feature/team/history/TeamHistoryScreen.kt
+++ b/feature/team/src/main/java/com/eshc/goonersapp/feature/team/history/TeamHistoryScreen.kt
@@ -2,21 +2,41 @@ package com.eshc.goonersapp.feature.team.history
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
-import com.eshc.goonersapp.core.designsystem.component.TopBar
+import com.eshc.goonersapp.core.designsystem.component.GnrTopBar
@Composable
-fun TeamHistoryScreen(
+fun TeamSearchRootScreen(
+ onClick: (String) -> Unit,
+ onBackIconClick: () -> Unit,
+ onShowSnackbar: (String) -> Unit
+) {
+ Scaffold(
+ topBar = {
+ GnrTopBar(
+ title = "Search",
+ onBackIconClick = onBackIconClick
+ )
+ }
+ ) { paddingValues ->
+ TeamSearchScreen(
+ onClick = onClick,
+ modifier = Modifier.padding(paddingValues)
+ )
+ }
+}
+
+@Composable
+fun TeamSearchScreen(
onClick : (String) -> Unit,
- onShowSnackbar : (String) -> Unit
+ modifier: Modifier = Modifier,
) {
Column(
- modifier = Modifier.fillMaxSize()
+ modifier = modifier.fillMaxSize()
) {
- TopBar(
- title = "HISTORY"
- )
-
+ /* TODO("Not yet Implemented") */
}
}
\ No newline at end of file
diff --git a/feature/team/src/main/java/com/eshc/goonersapp/feature/team/navigation/TeamNavigation.kt b/feature/team/src/main/java/com/eshc/goonersapp/feature/team/navigation/TeamNavigation.kt
index c6425cf5..a4292c93 100644
--- a/feature/team/src/main/java/com/eshc/goonersapp/feature/team/navigation/TeamNavigation.kt
+++ b/feature/team/src/main/java/com/eshc/goonersapp/feature/team/navigation/TeamNavigation.kt
@@ -10,11 +10,11 @@ import androidx.navigation.navArgument
import com.eshc.goonersapp.feature.team.TeamRootScreen
import com.eshc.goonersapp.feature.team.club.ClubDetailRoute
import com.eshc.goonersapp.feature.team.detail.PlayerDetailRootScreen
-import com.eshc.goonersapp.feature.team.history.TeamHistoryScreen
+import com.eshc.goonersapp.feature.team.history.TeamSearchRootScreen
const val teamNavigationRoute = "team_route"
const val playerDetailNavigationRoute = "player_route"
-const val teamHistoryNavigationRoute = "team_history_route"
+const val teamSearchNavigationRoute = "team_search_route"
const val clubDetailNavigationRoute = "club_detail_route"
@@ -28,8 +28,8 @@ fun NavController.navigateToPlayerDetail(playerId: String, navOptions: NavOption
this.navigate(playerDetailNavigationRoute + "/${playerId}", navOptions)
}
-fun NavController.navigateToTeamHistory(navOptions: NavOptions? = null) {
- this.navigate(teamHistoryNavigationRoute, navOptions)
+fun NavController.navigateToSearch(navOptions: NavOptions? = null) {
+ this.navigate(teamSearchNavigationRoute, navOptions)
}
fun NavController.navigateToClubDetail(navOptions: NavOptions? = null) {
@@ -55,6 +55,7 @@ fun NavGraphBuilder.teamScreen(
}
fun NavGraphBuilder.playerDetailScreen(
+ onBackIconClick: () -> Unit,
onShowSnackbar: (String) -> Unit
) {
composable(
@@ -64,32 +65,37 @@ fun NavGraphBuilder.playerDetailScreen(
),
) {
PlayerDetailRootScreen(
+ onBackIconClick = onBackIconClick,
onShowSnackbar = onShowSnackbar
)
}
}
-fun NavGraphBuilder.teamHistoryScreen(
+fun NavGraphBuilder.teamSearchScreen(
onPlayerClick: (String) -> Unit,
+ onBackIconClick: () -> Unit,
onShowSnackbar: (String) -> Unit
) {
composable(
- route = teamHistoryNavigationRoute
+ route = teamSearchNavigationRoute
) {
- TeamHistoryScreen(
- onPlayerClick,
- onShowSnackbar
+ TeamSearchRootScreen(
+ onClick = onPlayerClick,
+ onBackIconClick = onBackIconClick,
+ onShowSnackbar = onShowSnackbar
)
}
}
fun NavGraphBuilder.clubDetailScreen(
+ onBackIconClick: () -> Unit,
onShowSnackbar: (String) -> Unit
) {
composable(
route = clubDetailNavigationRoute
) {
ClubDetailRoute(
+ onBackIconClick = onBackIconClick,
onShowSnackbar = onShowSnackbar
)
}