Last active
June 13, 2025 06:38
-
-
Save Sprajapati123/a00902213abce5e7a21545152a8fc97c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.c36b.view | |
import android.app.Activity | |
import android.net.Uri | |
import android.os.Bundle | |
import android.util.Log | |
import android.widget.Toast | |
import androidx.activity.ComponentActivity | |
import androidx.activity.compose.setContent | |
import androidx.activity.enableEdgeToEdge | |
import androidx.compose.foundation.Image | |
import androidx.compose.foundation.clickable | |
import androidx.compose.foundation.interaction.MutableInteractionSource | |
import androidx.compose.foundation.layout.Box | |
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.lazy.LazyColumn | |
import androidx.compose.foundation.shape.RoundedCornerShape | |
import androidx.compose.foundation.text.KeyboardOptions | |
import androidx.compose.material.icons.Icons | |
import androidx.compose.material.icons.filled.Email | |
import androidx.compose.material3.Button | |
import androidx.compose.material3.Icon | |
import androidx.compose.material3.OutlinedTextField | |
import androidx.compose.material3.Scaffold | |
import androidx.compose.material3.Text | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.getValue | |
import androidx.compose.runtime.mutableIntStateOf | |
import androidx.compose.runtime.mutableStateOf | |
import androidx.compose.runtime.remember | |
import androidx.compose.runtime.setValue | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.layout.ContentScale | |
import androidx.compose.ui.platform.LocalContext | |
import androidx.compose.ui.res.painterResource | |
import androidx.compose.ui.text.input.KeyboardType | |
import androidx.compose.ui.tooling.preview.Preview | |
import androidx.compose.ui.unit.dp | |
import coil.compose.AsyncImage | |
import com.example.c36b.R | |
import com.example.c36b.model.ProductModel | |
import com.example.c36b.repository.ProductRepository | |
import com.example.c36b.repository.ProductRepositoryImpl | |
import com.example.c36b.repository.UserRepository | |
import com.example.c36b.utils.ImageUtils | |
import com.example.c36b.view.ui.theme.C36BmasterTheme | |
import com.example.c36b.viewmodel.ProductViewModel | |
class AddProductActivity : ComponentActivity() { | |
lateinit var imageUtils: ImageUtils | |
var selectedImageUri by mutableStateOf<Uri?>(null) | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
enableEdgeToEdge() | |
imageUtils = ImageUtils(this, this) | |
imageUtils.registerLaunchers { uri -> | |
selectedImageUri = uri | |
} | |
setContent { | |
AddProductBody( | |
selectedImageUri = selectedImageUri, | |
onPickImage = { imageUtils.launchImagePicker() } | |
) | |
} | |
} | |
} | |
@Composable | |
fun AddProductBody( | |
selectedImageUri: Uri?, | |
onPickImage: () -> Unit | |
) { | |
var productName by remember { mutableStateOf("") } | |
var productPrice by remember { mutableStateOf("") } | |
var productDescription by remember { mutableStateOf("") } | |
val repo = remember { ProductRepositoryImpl() } | |
val viewModel = remember { ProductViewModel(repo) } | |
val context = LocalContext.current | |
val activity = context as? Activity | |
Scaffold { innerPadding -> | |
LazyColumn( | |
modifier = Modifier | |
.fillMaxSize() | |
.padding(innerPadding) | |
) { | |
item { | |
Box( | |
modifier = Modifier | |
.fillMaxWidth() | |
.height(200.dp) | |
.clickable( | |
indication = null, | |
interactionSource = remember { MutableInteractionSource() } | |
) { | |
onPickImage() | |
} | |
.padding(10.dp) | |
) { | |
if (selectedImageUri != null) { | |
AsyncImage( | |
model = selectedImageUri, | |
contentDescription = "Selected Image", | |
modifier = Modifier.fillMaxSize(), | |
contentScale = ContentScale.Crop | |
) | |
} else { | |
Image( | |
painterResource(R.drawable.img), | |
contentDescription = null, | |
modifier = Modifier.fillMaxSize(), | |
contentScale = ContentScale.Crop | |
) | |
} | |
} | |
OutlinedTextField( | |
modifier = Modifier | |
.fillMaxWidth() | |
.padding(horizontal = 10.dp), | |
shape = RoundedCornerShape(12.dp), | |
placeholder = { Text("Product Name") }, | |
value = productName, | |
onValueChange = { productName = it } | |
) | |
OutlinedTextField( | |
modifier = Modifier | |
.fillMaxWidth() | |
.padding(horizontal = 10.dp), | |
shape = RoundedCornerShape(12.dp), | |
placeholder = { Text("Product Description") }, | |
value = productDescription, | |
onValueChange = { productDescription = it } | |
) | |
OutlinedTextField( | |
modifier = Modifier | |
.fillMaxWidth() | |
.padding(horizontal = 10.dp), | |
shape = RoundedCornerShape(12.dp), | |
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), | |
placeholder = { Text("Product Price") }, | |
value = productPrice, | |
onValueChange = { productPrice = it } | |
) | |
Button( | |
onClick = { | |
if (selectedImageUri != null) { | |
viewModel.uploadImage(context, selectedImageUri) { imageUrl -> | |
if (imageUrl != null) { | |
val model = ProductModel( | |
"", | |
productName, | |
productPrice.toIntOrNull() ?: 0, | |
productDescription, | |
imageUrl | |
) | |
viewModel.addProduct(model) { success, message -> | |
Toast.makeText(context, message, Toast.LENGTH_LONG).show() | |
if (success) activity?.finish() | |
} | |
} else { | |
Log.e("Upload Error", "Failed to upload image to Cloudinary") | |
} | |
} | |
} else { | |
Toast.makeText( | |
context, | |
"Please select an image first", | |
Toast.LENGTH_SHORT | |
).show() | |
} | |
}, | |
modifier = Modifier | |
.fillMaxWidth() | |
.padding(10.dp) | |
) { | |
Text("Submit") | |
} | |
} | |
} | |
} | |
} | |
@Preview(showBackground = true) | |
@Composable | |
fun ProductBodyPreview() { | |
AddProductBody( | |
selectedImageUri = null, // or pass a mock Uri if needed | |
onPickImage = {} // no-op | |
) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- Add Permission in your android manifest --> | |
<uses-permission android:name="android.permission.INTERNET"/> | |
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
implementation("com.cloudinary:cloudinary-android:2.1.0") | |
implementation("com.squareup.picasso:picasso:2.8") | |
implementation("io.coil-kt:coil-compose:2.2.2") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.c36b.utils | |
import android.Manifest | |
import android.app.Activity | |
import android.content.Intent | |
import android.net.Uri | |
import android.os.Build | |
import android.provider.MediaStore | |
import android.util.Log | |
import androidx.activity.result.ActivityResultLauncher | |
import androidx.activity.result.ActivityResultRegistryOwner | |
import androidx.activity.result.contract.ActivityResultContracts | |
import androidx.core.content.ContextCompat | |
import android.content.pm.PackageManager | |
class ImageUtils(private val activity: Activity, private val registryOwner: ActivityResultRegistryOwner) { | |
private lateinit var galleryLauncher: ActivityResultLauncher<Intent> | |
private lateinit var permissionLauncher: ActivityResultLauncher<String> | |
private var onImageSelectedCallback: ((Uri?) -> Unit)? = null | |
fun registerLaunchers(onImageSelected: (Uri?) -> Unit) { | |
onImageSelectedCallback = onImageSelected | |
// Register for selecting image from gallery | |
galleryLauncher = registryOwner.activityResultRegistry.register( | |
"galleryLauncher", ActivityResultContracts.StartActivityForResult() | |
) { result -> | |
val uri = result.data?.data | |
if (result.resultCode == Activity.RESULT_OK && uri != null) { | |
onImageSelectedCallback?.invoke(uri) | |
} else { | |
Log.e("ImageUtils", "Image selection cancelled or failed") | |
} | |
} | |
// Register permission request | |
permissionLauncher = registryOwner.activityResultRegistry.register( | |
"permissionLauncher", ActivityResultContracts.RequestPermission() | |
) { isGranted -> | |
if (isGranted) { | |
openGallery() | |
} else { | |
Log.e("ImageUtils", "Permission denied") | |
} | |
} | |
} | |
fun launchImagePicker() { | |
val permission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { | |
Manifest.permission.READ_MEDIA_IMAGES | |
} else { | |
Manifest.permission.READ_EXTERNAL_STORAGE | |
} | |
if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { | |
permissionLauncher.launch(permission) | |
} else { | |
openGallery() | |
} | |
} | |
private fun openGallery() { | |
val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI).apply { | |
type = "image/*" | |
} | |
galleryLauncher.launch(intent) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.c36b.repository | |
import android.content.Context | |
import android.net.Uri | |
import com.example.c36b.model.ProductModel | |
interface ProductRepository { | |
fun addProduct(productModel: ProductModel, callback: (Boolean, String) -> Unit) | |
fun deleteProduct(productId: String, callback: (Boolean, String) -> Unit) | |
fun getProductById(productId: String, callback: (Boolean, String, ProductModel?) -> Unit) | |
fun getAllProduct(callback: (Boolean, String, List<ProductModel>?) -> Unit) | |
fun updateProduct( | |
productId: String, | |
data: MutableMap<String, Any?>, | |
callback: (Boolean, String) -> Unit | |
) | |
fun uploadImage(context: Context,imageUri: Uri, callback: (String?) -> Unit) | |
fun getFileNameFromUri(context: Context,uri: Uri): String? | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.c36b.repository | |
import android.content.Context | |
import android.net.Uri | |
import android.os.Handler | |
import android.os.Looper | |
import android.provider.OpenableColumns | |
import com.cloudinary.Cloudinary | |
import com.cloudinary.utils.ObjectUtils | |
import com.example.c36b.model.ProductModel | |
import com.google.firebase.database.DataSnapshot | |
import com.google.firebase.database.DatabaseError | |
import com.google.firebase.database.FirebaseDatabase | |
import com.google.firebase.database.ValueEventListener | |
import java.io.InputStream | |
import java.util.concurrent.Executors | |
class ProductRepositoryImpl : ProductRepository { | |
val database = FirebaseDatabase.getInstance() | |
val ref = database.reference.child("products") | |
private val cloudinary = Cloudinary( | |
mapOf( | |
"cloud_name" to "dxwr7qza9", | |
"api_key" to "545811657876156", | |
"api_secret" to "Oo50NMS-vrURt3gETED4ibe21uo" | |
) | |
) | |
override fun uploadImage(context: Context, imageUri: Uri, callback: (String?) -> Unit) { | |
val executor = Executors.newSingleThreadExecutor() | |
executor.execute { | |
try { | |
val inputStream: InputStream? = context.contentResolver.openInputStream(imageUri) | |
var fileName = getFileNameFromUri(context, imageUri) | |
// ✅ Fix: Remove extensions from file name before upload | |
fileName = fileName?.substringBeforeLast(".") ?: "uploaded_image" | |
val response = cloudinary.uploader().upload( | |
inputStream, ObjectUtils.asMap( | |
"public_id", fileName, | |
"resource_type", "image" | |
) | |
) | |
var imageUrl = response["url"] as String? | |
imageUrl = imageUrl?.replace("http://", "https://") | |
// ✅ Run UI updates on the Main Thread | |
Handler(Looper.getMainLooper()).post { | |
callback(imageUrl) | |
} | |
} catch (e: Exception) { | |
e.printStackTrace() | |
Handler(Looper.getMainLooper()).post { | |
callback(null) | |
} | |
} | |
} | |
} | |
override fun getFileNameFromUri(context: Context, uri: Uri): String? { | |
var fileName: String? = null | |
val cursor = context.contentResolver.query(uri, null, null, null, null) | |
cursor?.use { | |
if (it.moveToFirst()) { | |
val nameIndex = it.getColumnIndex(OpenableColumns.DISPLAY_NAME) | |
if (nameIndex != -1) { | |
fileName = it.getString(nameIndex) | |
} | |
} | |
} | |
return fileName | |
} | |
override fun addProduct( | |
productModel: ProductModel, | |
callback: (Boolean, String) -> Unit | |
) { | |
var id = ref.push().key.toString() | |
productModel.productId = id | |
ref.child(id).setValue(productModel).addOnCompleteListener { | |
if (it.isSuccessful) { | |
callback(true, "product added") | |
} else { | |
callback(false, "${it.exception?.message}") | |
} | |
} | |
} | |
override fun deleteProduct( | |
productId: String, | |
callback: (Boolean, String) -> Unit | |
) { | |
ref.child(productId).removeValue().addOnCompleteListener { | |
if (it.isSuccessful) { | |
callback(true, "product deleted") | |
} else { | |
callback(false, "${it.exception?.message}") | |
} | |
} | |
} | |
override fun getProductById( | |
productId: String, | |
callback: (Boolean, String, ProductModel?) -> Unit | |
) { | |
ref.child(productId).addValueEventListener(object : ValueEventListener { | |
override fun onDataChange(snapshot: DataSnapshot) { | |
if (snapshot.exists()) { | |
var products = snapshot.getValue(ProductModel::class.java) | |
if (products != null) { | |
callback(true, "product fetched", products) | |
} | |
} | |
} | |
override fun onCancelled(error: DatabaseError) { | |
callback(false, error.message, null) | |
} | |
}) | |
} | |
override fun getAllProduct( | |
callback: (Boolean, String, List<ProductModel>?) -> Unit | |
) { | |
ref.addValueEventListener(object : ValueEventListener { | |
override fun onDataChange(snapshot: DataSnapshot) { | |
var allProducts = mutableListOf<ProductModel>() | |
if (snapshot.exists()) { | |
for (eachData in snapshot.children) { | |
var products = eachData.getValue(ProductModel::class.java) | |
if (products != null) { | |
allProducts.add(products) | |
} | |
} | |
callback(true, "fetched", allProducts) | |
} | |
} | |
override fun onCancelled(error: DatabaseError) { | |
callback(false, error.message, null) | |
} | |
}) | |
} | |
override fun updateProduct( | |
productId: String, | |
data: MutableMap<String, Any?>, | |
callback: (Boolean, String) -> Unit | |
) { | |
ref.child(productId).setValue(data).addOnCompleteListener { | |
if (it.isSuccessful) { | |
callback(true, "product updated") | |
} else { | |
callback(false, "${it.exception?.message}") | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.c36b.viewmodel | |
import android.content.Context | |
import android.net.Uri | |
import androidx.lifecycle.LiveData | |
import androidx.lifecycle.MutableLiveData | |
import androidx.lifecycle.ViewModel | |
import com.example.c36b.model.ProductModel | |
import com.example.c36b.repository.ProductRepository | |
class ProductViewModel(val repo: ProductRepository) : ViewModel() { | |
fun uploadImage(context: Context,imageUri: Uri, callback: (String?) -> Unit){ | |
repo.uploadImage(context,imageUri,callback) | |
} | |
fun addProduct(productModel: ProductModel, callback: (Boolean, String) -> Unit) { | |
repo.addProduct(productModel, callback) | |
} | |
fun deleteProduct(productId: String, callback: (Boolean, String) -> Unit) { | |
repo.deleteProduct(productId, callback) | |
} | |
private val _products = MutableLiveData<ProductModel?>() | |
val products: LiveData<ProductModel?> get() = _products | |
private val _allProducts = MutableLiveData<List<ProductModel?>>() | |
val allProducts: LiveData<List<ProductModel?>> get() = _allProducts | |
private val _isLoading = MutableLiveData<Boolean>() | |
val isLoading: LiveData<Boolean> get() = _isLoading | |
fun getProductById(productId: String) { | |
repo.getProductById(productId) { success, message, products -> | |
if (success && products != null) { | |
_products.postValue(products) | |
} else { | |
_products.postValue(null) | |
} | |
} | |
} | |
fun getAllProduct() { | |
_isLoading.value = true | |
repo.getAllProduct { success, message, products -> | |
if (success && products != null) { | |
_allProducts.postValue(products) | |
_isLoading.value = false | |
} else { | |
_isLoading.value = false | |
_allProducts.postValue(emptyList()) | |
} | |
} | |
} | |
fun updateProduct( | |
productId: String, data: MutableMap<String, Any?>, callback: (Boolean, String) -> Unit | |
) { | |
repo.updateProduct(productId, data, callback) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.c36b.view | |
import android.app.Activity | |
import android.net.Uri | |
import android.os.Bundle | |
import android.widget.Toast | |
import androidx.activity.ComponentActivity | |
import androidx.activity.compose.setContent | |
import androidx.activity.enableEdgeToEdge | |
import androidx.compose.foundation.Image | |
import androidx.compose.foundation.clickable | |
import androidx.compose.foundation.interaction.MutableInteractionSource | |
import androidx.compose.foundation.layout.Box | |
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.lazy.LazyColumn | |
import androidx.compose.foundation.shape.RoundedCornerShape | |
import androidx.compose.foundation.text.KeyboardOptions | |
import androidx.compose.material3.Button | |
import androidx.compose.material3.OutlinedTextField | |
import androidx.compose.material3.Scaffold | |
import androidx.compose.material3.Text | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.LaunchedEffect | |
import androidx.compose.runtime.getValue | |
import androidx.compose.runtime.livedata.observeAsState | |
import androidx.compose.runtime.mutableStateOf | |
import androidx.compose.runtime.remember | |
import androidx.compose.runtime.setValue | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.layout.ContentScale | |
import androidx.compose.ui.platform.LocalContext | |
import androidx.compose.ui.res.painterResource | |
import androidx.compose.ui.text.input.KeyboardType | |
import androidx.compose.ui.tooling.preview.Preview | |
import androidx.compose.ui.unit.dp | |
import coil.compose.AsyncImage | |
import com.example.c36b.R | |
import com.example.c36b.model.ProductModel | |
import com.example.c36b.repository.ProductRepositoryImpl | |
import com.example.c36b.utils.ImageUtils | |
import com.example.c36b.view.ui.theme.C36BmasterTheme | |
import com.example.c36b.viewmodel.ProductViewModel | |
class UpdateProductActivity : ComponentActivity() { | |
lateinit var imageUtils: ImageUtils | |
var selectedImageUri by mutableStateOf<Uri?>(null) | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
enableEdgeToEdge() | |
imageUtils = ImageUtils(this, this) | |
imageUtils.registerLaunchers { uri -> | |
selectedImageUri = uri | |
} | |
setContent { | |
UpdateProductBody( | |
selectedImageUri = selectedImageUri, | |
onPickImage = { imageUtils.launchImagePicker() } | |
) | |
} | |
} | |
} | |
@Composable | |
fun UpdateProductBody( | |
selectedImageUri: Uri?, | |
onPickImage: () -> Unit | |
) { | |
var productName by remember { mutableStateOf("") } | |
var productPrice by remember { mutableStateOf("") } | |
var productDescription by remember { mutableStateOf("") } | |
var repo = remember { ProductRepositoryImpl() } | |
val viewModel = remember { ProductViewModel(repo) } | |
val context = LocalContext.current | |
val activity = context as? Activity | |
val productId: String? = activity?.intent?.getStringExtra("productId") | |
val data = viewModel.products.observeAsState(initial = null) | |
LaunchedEffect(Unit) { | |
viewModel.getProductById(productId.toString()) | |
} | |
productName = data.value?.name ?: "" | |
productPrice = data.value?.price.toString() | |
productDescription = data.value?.desc ?: "" | |
Scaffold { innerPadding -> | |
LazyColumn( | |
modifier = Modifier | |
.fillMaxSize() | |
.padding(innerPadding) | |
) { | |
item { | |
Box( | |
modifier = Modifier | |
.fillMaxWidth() | |
.height(200.dp) | |
.clickable( | |
indication = null, | |
interactionSource = remember { MutableInteractionSource() } | |
) { | |
onPickImage() | |
} | |
.padding(10.dp) | |
) { | |
when { | |
selectedImageUri != null -> { | |
AsyncImage( | |
model = selectedImageUri, | |
contentDescription = "Selected Image", | |
modifier = Modifier.fillMaxSize(), | |
contentScale = ContentScale.Crop | |
) | |
} | |
!data.value?.imageUrl.isNullOrEmpty() -> { | |
AsyncImage( | |
model = data.value!!.imageUrl, | |
contentDescription = "Existing Image from DB", | |
modifier = Modifier.fillMaxSize(), | |
contentScale = ContentScale.Crop | |
) | |
} | |
else -> { | |
Image( | |
painter = painterResource(R.drawable.img), | |
contentDescription = "Placeholder Image", | |
modifier = Modifier.fillMaxSize(), | |
contentScale = ContentScale.Crop | |
) | |
} | |
} | |
} | |
OutlinedTextField( | |
modifier = Modifier | |
.fillMaxWidth() | |
.padding(horizontal = 10.dp), | |
shape = RoundedCornerShape(12.dp), | |
placeholder = { | |
Text("Product Name") | |
}, | |
value = productName, | |
onValueChange = { input -> | |
productName = input | |
}) | |
OutlinedTextField( | |
modifier = Modifier | |
.fillMaxWidth() | |
.padding(horizontal = 10.dp), | |
shape = RoundedCornerShape(12.dp), | |
placeholder = { | |
Text("Product Name") | |
}, | |
value = productDescription, | |
onValueChange = { input -> | |
productDescription = input | |
}) | |
OutlinedTextField( | |
modifier = Modifier | |
.fillMaxWidth() | |
.padding(horizontal = 10.dp), | |
shape = RoundedCornerShape(12.dp), | |
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), | |
placeholder = { | |
Text("Product price") | |
}, | |
value = productPrice, | |
onValueChange = { input -> | |
productPrice = input | |
}) | |
Button(onClick = { | |
viewModel.uploadImage(context, selectedImageUri!!) { imageUrl -> | |
if(imageUrl != null){ | |
var maps = mutableMapOf<String, Any?>() | |
maps["productId"] = productId | |
maps["name"] = productName | |
maps["desc"] = productDescription | |
maps["price"] = productPrice.toInt() | |
maps["imageUrl"] = imageUrl | |
viewModel.updateProduct(productId.toString(), maps) { success, message -> | |
if (success) { | |
Toast.makeText(context, message, Toast.LENGTH_LONG).show() | |
activity?.finish() | |
} else { | |
Toast.makeText(context, message, Toast.LENGTH_LONG).show() | |
} | |
} | |
} | |
} | |
}) { | |
Text("Submit") | |
} | |
} | |
} | |
} | |
} | |
@Preview(showBackground = true) | |
@Composable | |
fun UpdateBodyPreview() { | |
UpdateProductBody( | |
selectedImageUri = null, // or pass a mock Uri if needed | |
onPickImage = {}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment