@@ -35,6 +35,7 @@ import androidx.compose.ui.tooling.preview.Preview
3535import androidx.compose.ui.unit.dp
3636import androidx.hilt.navigation.compose.hiltViewModel
3737import com.no5ing.bbibbi.R
38+ import coil.compose.AsyncImage
3839import com.no5ing.bbibbi.data.model.post.AIPost
3940import com.no5ing.bbibbi.data.repository.Arguments
4041import com.no5ing.bbibbi.presentation.component.AIPhotoInfoBaloon
@@ -45,39 +46,46 @@ import com.no5ing.bbibbi.presentation.component.button.CustomCTAButton
4546import com.no5ing.bbibbi.presentation.feature.view.common.CustomAlertDialog
4647import com.no5ing.bbibbi.presentation.feature.view_model.post.GetAIPostsViewModel
4748import com.no5ing.bbibbi.presentation.feature.view_model.post.GetAiImageCountViewModel
49+ import com.no5ing.bbibbi.presentation.feature.view_model.post.GetAiImageTypesViewModel
4850import com.no5ing.bbibbi.presentation.theme.bbibbiScheme
4951import com.no5ing.bbibbi.presentation.theme.bbibbiTypo
5052import com.no5ing.bbibbi.util.LocalSessionState
53+ import com.no5ing.bbibbi.util.asyncImagePainter
5154import java.time.LocalDate
5255
5356
5457@Composable
5558fun FamilyStudioPage (
59+ aiPostType : String = "",
5660 onDispose : () -> Unit = {},
5761 onTapCreateImage : () -> Unit = {},
5862 onTapAiPost : (AIPost ) -> Unit = {},
5963 postsViewModel : GetAIPostsViewModel = hiltViewModel(),
6064 aiImageCountViewModel : GetAiImageCountViewModel = hiltViewModel(),
65+ aiImageTypesViewModel : GetAiImageTypesViewModel = hiltViewModel(),
6166 isTermDialogEnabled : State <Boolean > = mutableStateOf(true),
6267 onDisagreeTerm : () -> Unit = {},
6368 onAgreeTerm : () -> Unit = {},
6469 onClickTerm : () -> Unit = {},
6570) {
6671 val aiImageState = aiImageCountViewModel.uiState.collectAsState()
72+ val typesState = aiImageTypesViewModel.uiState.collectAsState()
6773 LaunchedEffect (Unit ) {
74+ val postArgs = Arguments (
75+ arguments = if (aiPostType.isNotEmpty()) mapOf (" aiPostType" to aiPostType.uppercase()) else emptyMap()
76+ )
6877 if (postsViewModel.isInitialize()) {
69- postsViewModel.invoke(Arguments () )
78+ postsViewModel.invoke(postArgs )
7079 } else {
7180 postsViewModel.refresh()
7281 }
7382
74- aiImageCountViewModel.invoke(Arguments ())
75- }
76- val photoCount = if (aiImageState.value.isReady()) {
77- aiImageState.value.data.familyAiImageCount
78- } else {
79- 0
83+ aiImageCountViewModel.invoke(postArgs)
84+ aiImageTypesViewModel.invoke(Arguments ())
8085 }
86+ val matchedType = if (typesState.value.isReady()) {
87+ typesState.value.data.results.find { it.aiPostType == aiPostType }
88+ } else null
8189 CustomAlertDialog (
8290 title = " 이미지사용약관" ,
8391 description = " AI 이미지 기능을 사용하려면\n 약관에 대한 동의가 필요해요" ,
@@ -101,11 +109,8 @@ fun FamilyStudioPage(
101109 onDispose = onDispose,
102110 title = " 가족 사진관"
103111 )
104- val scrollState = rememberScrollState()
105- Column (
106- modifier = Modifier
107- .verticalScroll(state = scrollState)
108- ) {
112+ if (matchedType != null ) {
113+ val dateRange = formatDateRange(matchedType.startDate, matchedType.endDate)
109114 Column (
110115 modifier = Modifier .padding(vertical = 20 .dp, horizontal = 20 .dp)
111116 ) {
@@ -122,78 +127,80 @@ fun FamilyStudioPage(
122127 .padding(vertical = 2 .dp, horizontal = 6 .dp)
123128 ) {
124129 Text (
125- text = " 추석 " ,
130+ text = matchedType.getTypeName() ,
126131 color = MaterialTheme .bbibbiScheme.backgroundPrimary,
127132 style = MaterialTheme .bbibbiTypo.bodyTwoBold,
128133 )
129134 }
130135 Box (modifier = Modifier .width(6 .dp))
131136 Text (
132- text = " 9/29~10/27 " ,
137+ text = dateRange ,
133138 color = MaterialTheme .bbibbiScheme.textPrimary,
134139 style = MaterialTheme .bbibbiTypo.headTwoBold,
135140 )
136141 Spacer (modifier = Modifier .width(4 .dp))
137142 AIPhotoInfoBaloon ()
138143 }
139144 Text (
140- text = " ${photoCount } 개의 추억" ,
145+ text = " ${matchedType.postCount } 개의 추억" ,
141146 color = MaterialTheme .bbibbiScheme.textPrimary,
142147 style = MaterialTheme .bbibbiTypo.bodyOneRegular,
143148 )
144-
145149 }
146150 Box (modifier = Modifier .height(16 .dp))
147- Image (
148- painter = painterResource(id = R .drawable.family_studio_banner ),
151+ AsyncImage (
152+ model = asyncImagePainter(source = matchedType.imageUrl ),
149153 contentDescription = null ,
150154 modifier = Modifier .fillMaxWidth(),
151- contentScale = ContentScale .FillWidth
155+ contentScale = ContentScale .FillWidth ,
152156 )
153157 }
154-
155158 }
156159 FamilyStudioPageFeed (
157160 postItemsState = postsViewModel.uiState,
158161 onTapContent = onTapAiPost,
159162 onPullToRefresh = {
160- aiImageCountViewModel.invoke(Arguments ())
163+ val refreshArgs = Arguments (
164+ arguments = if (aiPostType.isNotEmpty()) mapOf (" aiPostType" to aiPostType.uppercase()) else emptyMap()
165+ )
166+ aiImageCountViewModel.invoke(refreshArgs)
161167 }
162168 )
163169 }
164170
165- Box (
166- modifier = Modifier
167- .padding(horizontal = 12 .dp, vertical = 15 .dp)
168- .navigationBarsPadding()
169- .align(Alignment .BottomCenter )
170- ) {
171-
172- CustomCTAButton (
173- modifier = Modifier .fillMaxWidth(),
174- contentPadding = PaddingValues (vertical = 18 .dp),
175- onClick = onTapCreateImage,
176- isActive = aiImageState.value.isReady() && aiImageState.value.data.hasAvailableImage()
171+ if (isWithinDateRange(matchedType?.startDate, matchedType?.endDate)) {
172+ Box (
173+ modifier = Modifier
174+ .padding(horizontal = 12 .dp, vertical = 15 .dp)
175+ .navigationBarsPadding()
176+ .align(Alignment .BottomCenter )
177177 ) {
178- Text (
179- text = " 이미지 만들기" ,
180- color = MaterialTheme .bbibbiScheme.backgroundPrimary,
181- style = MaterialTheme .bbibbiTypo.bodyOneBold,
182- )
183- Image (
184- painter = painterResource(id = R .drawable.ai),
185- contentDescription = null ,
186- modifier = Modifier .size(22 .dp),
187- contentScale = ContentScale .FillWidth
188- )
189- if (aiImageState.value.isReady()) {
190- val count = aiImageState.value.data
191- Spacer (modifier = Modifier .width(3 .dp))
178+ CustomCTAButton (
179+ modifier = Modifier .fillMaxWidth(),
180+ contentPadding = PaddingValues (vertical = 18 .dp),
181+ onClick = onTapCreateImage,
182+ isActive = aiImageState.value.isReady() && aiImageState.value.data.hasAvailableImage()
183+ ) {
192184 Text (
193- text = " ( ${count.availableAiImageCount} /3) " ,
185+ text = " 이미지 만들기 " ,
194186 color = MaterialTheme .bbibbiScheme.backgroundPrimary,
195- style = MaterialTheme .bbibbiTypo.bodyTwoRegular ,
187+ style = MaterialTheme .bbibbiTypo.bodyOneBold ,
196188 )
189+ Image (
190+ painter = painterResource(id = R .drawable.ai),
191+ contentDescription = null ,
192+ modifier = Modifier .size(22 .dp),
193+ contentScale = ContentScale .FillWidth
194+ )
195+ if (aiImageState.value.isReady()) {
196+ val count = aiImageState.value.data
197+ Spacer (modifier = Modifier .width(3 .dp))
198+ Text (
199+ text = " (${count.availableAiImageCount} /3)" ,
200+ color = MaterialTheme .bbibbiScheme.backgroundPrimary,
201+ style = MaterialTheme .bbibbiTypo.bodyTwoRegular,
202+ )
203+ }
197204 }
198205 }
199206 }
@@ -204,6 +211,28 @@ fun FamilyStudioPage(
204211 }
205212}
206213
214+ private fun isWithinDateRange (startDate : String? , endDate : String? ): Boolean {
215+ if (startDate == null || endDate == null ) return false
216+ return try {
217+ val today = LocalDate .now()
218+ val start = LocalDate .parse(startDate)
219+ val end = LocalDate .parse(endDate)
220+ ! today.isBefore(start) && ! today.isAfter(end)
221+ } catch (e: Exception ) {
222+ false
223+ }
224+ }
225+
226+ private fun formatDateRange (startDate : String , endDate : String ): String {
227+ return try {
228+ val start = LocalDate .parse(startDate)
229+ val end = LocalDate .parse(endDate)
230+ " ${start.monthValue} /${start.dayOfMonth} ~${end.monthValue} /${end.dayOfMonth} "
231+ } catch (e: Exception ) {
232+ " $startDate ~$endDate "
233+ }
234+ }
235+
207236@Preview(
208237 showBackground = true ,
209238 name = " FamilyStudioPage" ,
0 commit comments