-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProductListScreen.kt
More file actions
133 lines (119 loc) · 4 KB
/
ProductListScreen.kt
File metadata and controls
133 lines (119 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package com.shopify.example.storefront
// [START complete-tutorial.display-products]
import android.util.Log
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import coil.compose.AsyncImage
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
@Composable
fun ProductListScreen(
viewModel: ProductListViewModel = viewModel()
) {
val products by viewModel.products.collectAsState()
val isLoading by viewModel.isLoading.collectAsState()
LaunchedEffect(Unit) {
viewModel.loadProducts()
}
Box(modifier = Modifier.fillMaxSize()) {
LazyColumn(
contentPadding = PaddingValues(16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
items(products) { product ->
ProductCard(
product = product,
onAddToCart = { viewModel.addToCart(product) }
)
}
}
if (isLoading) {
CircularProgressIndicator(
modifier = Modifier.align(Alignment.Center)
)
}
}
}
@Composable
fun ProductCard(
product: Product,
onAddToCart: () -> Unit
) {
Card(
modifier = Modifier.fillMaxWidth()
) {
Row(
modifier = Modifier.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
AsyncImage(
model = product.featuredImage?.url,
contentDescription = product.title,
modifier = Modifier.size(60.dp)
)
Spacer(modifier = Modifier.width(16.dp))
Column(modifier = Modifier.weight(1f)) {
Text(
text = product.title,
style = MaterialTheme.typography.titleMedium
)
product.firstVariantId?.let { _ ->
product.variants.edges.firstOrNull()?.node?.price?.let { price ->
Text(
text = "$${price.amount} ${price.currencyCode}",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
Button(onClick = onAddToCart) {
Text("Add")
}
}
}
}
class ProductListViewModel : ViewModel() {
private val client = StorefrontClient(
shopDomain = "{shop}.myshopify.com",
accessToken = "your-storefront-access-token"
)
private val _products = MutableStateFlow<List<Product>>(emptyList())
val products: StateFlow<List<Product>> = _products
private val _isLoading = MutableStateFlow(false)
val isLoading: StateFlow<Boolean> = _isLoading
fun loadProducts() {
viewModelScope.launch {
_isLoading.value = true
try {
_products.value = client.fetchProducts()
} catch (e: Exception) {
Log.e("Products", "Failed to load: ${e.message}")
} finally {
_isLoading.value = false
}
}
}
fun addToCart(product: Product) {
val variantId = product.firstVariantId ?: return
viewModelScope.launch {
try {
val cart = client.createCart(variantId)
Log.d("Cart", "Checkout URL: ${cart.checkoutUrl}")
} catch (e: Exception) {
Log.e("Cart", "Failed to create cart: ${e.message}")
}
}
}
}
// [END complete-tutorial.display-products]