Android Day 22 Let's add edit and save functionality to our Contact App

I first seperate the dialog to a seperate composible, so we are not having so much things cramp inside the main activity.

package com.williamjiamin.contactappdemo

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.williamjiamin.contactappdemo.ui.theme.ContactAppDemoTheme

class MainActivity : ComponentActivity() {
    @OptIn(ExperimentalMaterial3Api::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ContactAppDemoTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    var contactPersons by remember { mutableStateOf(listOf<Contact>()) }
                    var selectedContact by remember { mutableStateOf<Contact?>(null) }
                    var showPopUpWindow by remember { mutableStateOf(false) }

                    Column(
                        modifier = Modifier.fillMaxSize(),
                        verticalArrangement = Arrangement.Center
                    ) {
                        LazyColumn(
                            modifier = Modifier
                                .fillMaxWidth()
                                .weight(1f)
                                .padding(16.dp)
                        ) {
                            items(contactPersons) { contact ->
                                // Display each contact here
                                showingEveryContactPerson(
                                    everyContact = contact,
                                    onChangeClick = {
                                        // Logic for changing contact
                                        selectedContact = contact
                                    },
                                    onDeleteClick = {
                                        // Logic for deleting contact
                                        contactPersons = contactPersons.filter { it.id != contact.id }
                                    }
                                )
                            }
                        }

                        Button(
                            onClick = { showPopUpWindow = true },
                            modifier = Modifier
                                .fillMaxWidth()
                        ) {
                            Text("Add Contact")
                        }

                        if (showPopUpWindow) {
                            AddContactDialog(
                                onDismiss = { showPopUpWindow = false },
                                onSave = { newContact ->
                                    contactPersons = contactPersons + newContact
                                    showPopUpWindow = false
                                }
                            )
                        }

                        selectedContact?.let {
                            EditEveryContact(
                                everyContact = it,
                                onDismiss = { selectedContact = null },
                                onSave = { updatedContact ->
                                    contactPersons = contactPersons.map { contact ->
                                        if (contact.id == updatedContact.id) {
                                            updatedContact
                                        } else {
                                            contact
                                        }
                                    }
                                    selectedContact = null
                                }
                            )
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun AddContactDialog(
    onDismiss: () -> Unit,
    onSave: (Contact) -> Unit
) {
    var name by remember { mutableStateOf("") }
    var phone by remember { mutableStateOf("") }
    var email by remember { mutableStateOf("") }
    var address by remember { mutableStateOf("") }

    AlertDialog(
        onDismissRequest = onDismiss,
        title = { Text("Add Contact") },
        text = {
            Column {
                OutlinedTextField(
                    value = name,
                    onValueChange = { name = it },
                    label = { Text("Name") }
                )
                OutlinedTextField(
                    value = phone,
                    onValueChange = { phone = it },
                    label = { Text("Phone") }
                )
                OutlinedTextField(
                    value = email,
                    onValueChange = { email = it },
                    label = { Text("Email") }
                )
                OutlinedTextField(
                    value = address,
                    onValueChange = { address = it },
                    label = { Text("Address") }
                )
            }
        },
        confirmButton = {
            Button(onClick = {
                if (name.isNotEmpty()){
                    onSave(Contact(id = (0..10000).random(), name = name, phone = phone, email = email, address = address))
                }
            }) {
                Text("Save")
            }
        },
        dismissButton = {
            Button(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    )
}

@Composable
fun showingEveryContactPerson(
    everyContact: Contact,
    onChangeClick: () -> Unit,
    onDeleteClick: () -> Unit,
) {
    // Display each contact here

        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(8.dp)
                .border(5.dp, Color.LightGray, MaterialTheme.shapes.medium)
        ){
            Column (
                modifier = Modifier
                    .padding(8.dp)
                    .fillMaxWidth()

            ) {
                Text("Name: ${everyContact.name}")
                Text("Phone: ${everyContact.phone}")
                Text("Email: ${everyContact.email}")
                Text("Address: ${everyContact.address}")
                Spacer(modifier = Modifier.height(8.dp))
                Row (
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.Center
                ){
                    Button(onClick = onChangeClick,
                        modifier = Modifier
                            .padding(8.dp)
                    ) {
                        Text("Change")
                    }
                    Spacer(modifier = Modifier.width(8.dp))
                    Button(
                        onClick = onDeleteClick,
                        modifier = Modifier.padding(8.dp)
                    ) {
                        Text("Delete")
                    }
                }
            }
        }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EditEveryContact(
    everyContact: Contact,
    onDismiss: () -> Unit,
    onSave: (Contact) -> Unit) {

    var editedName by remember { mutableStateOf(everyContact.name) }
    var editedPhone by remember { mutableStateOf(everyContact.phone) }
    var editedEmail by remember { mutableStateOf(everyContact.email) }
    var editedAddress by remember { mutableStateOf(everyContact.address) }

    AlertDialog(
        onDismissRequest = onDismiss,
        title = { Text("Edit Contact") },
        text = {
            Column {
                OutlinedTextField(
                    value = editedName,
                    onValueChange = { editedName = it },
                    label = { Text("Name") }
                )
                OutlinedTextField(
                    value = editedPhone,
                    onValueChange = { editedPhone = it },
                    label = { Text("Phone") }
                )
                OutlinedTextField(
                    value = editedEmail,
                    onValueChange = { editedEmail = it },
                    label = { Text("Email") }
                )
                OutlinedTextField(
                    value = editedAddress,
                    onValueChange = { editedAddress = it },
                    label = { Text("Address") }
                )
            }
        },
        confirmButton = {
            Button(onClick = {
                onSave(
                    Contact(everyContact.id, editedName, editedPhone, editedEmail, editedAddress)
                )
            }) {
                Text("Save")
            }
        },
        dismissButton = {
            Button(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    )
}

data class Contact(
    val id: Int,
    var name: String,
    var phone: String,
    var email: String,
    var address: String,
)

And we finish our demo app. In the future , we are going to learn how to add database the this app.

Stay tuned!