Commit a0fdee66c47822b560761d176324b4afc3548580

Authored by Luciana Fratean
0 parents

Initial commit with all project files#

Showing 77 changed files with 2928 additions and 0 deletions
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
... ...
# Default ignored files
/shelf/
/workspace.xml
... ...
CupcakeOrder
\ No newline at end of file
... ...
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>
\ No newline at end of file
... ...
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="21" />
</component>
</project>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-02-03T19:31:41.692201600Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\Paul\.android\avd\Medium_Phone_API_35_2.avd" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState>
</selectionStates>
</component>
</project>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="CHOOSE_PER_TEST" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="jbr-21" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
... ...
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="GlancePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="GlancePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="GlancePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewDeviceShouldUseNewSpec" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
</profile>
</component>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="2.0.0" />
</component>
</project>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>
\ No newline at end of file
... ...
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>
</project>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
... ...
/build
\ No newline at end of file
... ...
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
id("com.google.gms.google-services")
}
android {
namespace = "com.example.pizzaorder"
compileSdk = 35
defaultConfig {
applicationId = "com.example.pizzaorder"
minSdk = 24
targetSdk = 35
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
compose = true
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
implementation(libs.androidx.navigation.runtime.ktx)
implementation(libs.androidx.navigation.compose)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
// Import the Firebase BoM
implementation(platform("com.google.firebase:firebase-bom:33.8.0"))
// TODO: Add the dependencies for Firebase products you want to use
// When using the BoM, don't specify versions in Firebase dependencies
implementation("com.google.firebase:firebase-analytics")
// Add the dependencies for any other desired Firebase products
// https://firebase.google.com/docs/android/setup#available-libraries
implementation("com.google.firebase:firebase-auth")
implementation("com.google.firebase:firebase-firestore")
}
\ No newline at end of file
... ...
{
"project_info": {
"project_number": "322090362921",
"project_id": "cupcakeorder-40545",
"storage_bucket": "cupcakeorder-40545.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:322090362921:android:bfcf253213b3fbd2069438",
"android_client_info": {
"package_name": "com.example.pizzaorder"
}
},
"oauth_client": [
{
"client_id": "322090362921-4m16acpm3qa3a3f5c8fbdrraioo45k21.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyA_WB-ldFu9LuDcdcxZRVwVUv4KQpF4TKc"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "322090362921-4m16acpm3qa3a3f5c8fbdrraioo45k21.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}
],
"configuration_version": "1"
}
\ No newline at end of file
... ...
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
... ...
package com.example.pizzaorder
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.example.pizzaorder", appContext.packageName)
}
}
\ No newline at end of file
... ...
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.PizzaOrder"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.PizzaOrder">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
\ No newline at end of file
... ...
package com.example.pizzaorder
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import com.example.pizzaorder.ui.theme.PizzaTheme
import com.google.firebase.FirebaseApp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
FirebaseApp.initializeApp(this)
setContent {
PizzaTheme {
PizzaApp()
}
}
}
}
... ...
package com.example.pizzaorder
import android.content.Context
import android.content.Intent
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.example.pizzaorder.ui.BurgerScreen
import com.example.pizzaorder.ui.ForgotPasswordScreen
import com.example.pizzaorder.ui.LoginScreen
import com.example.pizzaorder.ui.OrderPlacedScreen
import com.example.pizzaorder.ui.OrderSummaryScreen
import com.example.pizzaorder.ui.OrderViewModel
import com.example.pizzaorder.ui.PizzaScreen
import com.example.pizzaorder.ui.SignUpScreen
import com.example.pizzaorder.ui.StartOrderScreen
import com.google.firebase.auth.FirebaseAuth
enum class PizzaScreenPages(@StringRes val title: Int) {
Login(title = R.string.login),
SignUp(title = R.string.signup),
ForgotPassword(title = R.string.forgot_password),
Start(title = R.string.start_order),
Pizza(title = R.string.choose_pizza_type),
Burger(title = R.string.choose_burger_type),
Pickup(title = R.string.choose_pickup_date),
Summary(title = R.string.order_summary),
OrderPlaced(title = R.string.order_placed)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PizzaAppBar(
currentScreen: PizzaScreenPages,
canNavigateBack: Boolean,
navigateUp: () -> Unit,
onMenuClicked: () -> Unit,
modifier: Modifier = Modifier
) {
TopAppBar(
title = { Text(stringResource(currentScreen.title)) },
colors = TopAppBarDefaults.mediumTopAppBarColors(
containerColor = MaterialTheme.colorScheme.primaryContainer
),
modifier = modifier,
navigationIcon = {
if (canNavigateBack) {
IconButton(onClick = navigateUp) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = stringResource(R.string.back_button)
)
}
}
},
actions = {
IconButton(onClick = onMenuClicked) {
Icon(
imageVector = Icons.Default.MoreVert,
contentDescription = stringResource(R.string.menu_button)
)
}
}
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PizzaApp(
viewModel: OrderViewModel = viewModel(),
navController: NavHostController = rememberNavController()
) {
val backStackEntry by navController.currentBackStackEntryAsState()
val currentScreen = PizzaScreenPages.valueOf(
backStackEntry?.destination?.route ?: PizzaScreenPages.Start.name
)
val isAuthenticated = FirebaseAuth.getInstance().currentUser != null
var showBottomSheet by remember { mutableStateOf(false) }
var showLoginDialog by remember { mutableStateOf(false) }
val sheetState = rememberModalBottomSheetState()
val scope = rememberCoroutineScope()
if (showLoginDialog) {
AlertDialog(
onDismissRequest = {showLoginDialog = false},
title = { Text("Login Required") },
text = { Text("You need to log in to access this feature.") },
confirmButton = {
Button(onClick = {showLoginDialog = false}) {
Text("OK")
}
}
)
}
if (showBottomSheet) {
ModalBottomSheet(
onDismissRequest = { showBottomSheet = false },
sheetState = sheetState
) {
MenuContent(
onHomeClicked = {
showBottomSheet = false
if (isAuthenticated) {
navController.navigate(PizzaScreenPages.Start.name)
} else {
showLoginDialog = true
}
},
onOrdersClicked = {
showBottomSheet = false
if (isAuthenticated) {
navController.navigate(PizzaScreenPages.Summary.name)
} else {
showLoginDialog = true
}
},
onLogoutClicked = {
FirebaseAuth.getInstance().signOut()
showBottomSheet = false
navController.navigate(PizzaScreenPages.Login.name) {
popUpTo(PizzaScreenPages.Login.name) { inclusive = true }
}
}
)
}
}
Scaffold(
topBar = {
PizzaAppBar(
currentScreen = currentScreen,
canNavigateBack = navController.previousBackStackEntry != null,
navigateUp = { navController.navigateUp() },
onMenuClicked = { showBottomSheet = true }
)
},
bottomBar = {
}
) { innerPadding ->
val uiState by viewModel.uiState.collectAsState()
NavHost(
navController = navController,
startDestination = if (isAuthenticated) PizzaScreenPages.Start.name else PizzaScreenPages.Login.name,
modifier = Modifier.padding(innerPadding)
) {
composable(route = PizzaScreenPages.Login.name) {
LoginScreen(
navController = navController,
modifier = Modifier
.fillMaxSize()
.padding(dimensionResource(R.dimen.padding_medium))
)
}
composable(route = PizzaScreenPages.SignUp.name) {
SignUpScreen(
navController = navController,
modifier = Modifier
.fillMaxSize()
.padding(dimensionResource(R.dimen.padding_medium))
)
}
composable(route = PizzaScreenPages.ForgotPassword.name) {
ForgotPasswordScreen(
navController = navController,
modifier = Modifier
.fillMaxSize()
.padding(dimensionResource(R.dimen.padding_medium))
)
}
composable(route = PizzaScreenPages.Start.name) {
StartOrderScreen(
navController = navController,
modifier = Modifier.fillMaxSize())
}
composable(route = PizzaScreenPages.Pizza.name) {
PizzaScreen(
viewModel = viewModel,
navController = navController)
}
composable(route = PizzaScreenPages.Burger.name) {
BurgerScreen(
viewModel = viewModel,
navController = navController)
}
composable(route = PizzaScreenPages.Summary.name) {
OrderSummaryScreen(
viewModel = viewModel,
onBack = { navController.popBackStack() },
onPlace = { navController.navigate(PizzaScreenPages.OrderPlaced.name) })
}
composable(route = PizzaScreenPages.OrderPlaced.name) {
OrderPlacedScreen(
onBack = {
viewModel.clearOrder()
navController.navigate(PizzaScreenPages.Start.name) }
)
}
}
}
}
@Composable
fun MenuContent(
onHomeClicked: () -> Unit,
onOrdersClicked: () -> Unit,
onLogoutClicked: () -> Unit
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Text(
text = "Menu",
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(bottom = 8.dp)
)
HorizontalDivider()
Button(
onClick = onHomeClicked,
modifier = Modifier.fillMaxWidth()
) {
Text("Home")
}
Button(
onClick = onOrdersClicked,
modifier = Modifier.fillMaxWidth()
) {
Text("Orders")
}
Button(
onClick = onLogoutClicked,
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(containerColor = Color.Red)
) {
Text("Logout")
}
}
}
... ...
package com.example.pizzaorder.data
import com.example.pizzaorder.R
import com.example.pizzaorder.ui.MenuItem
object DataSource {
val pizzaOptions = listOf(
MenuItem("Margherita Pizza", 8.99, R.drawable.pizza_marguerita, "Pizza"),
MenuItem("Pepperoni Pizza", 9.99, R.drawable.pizza_diavola, "Pizza"),
MenuItem("Quattro Formaggi", 10.99, R.drawable.pizza_quattro_formaggi, "Pizza"),
MenuItem("Capriciosa", 11.99, R.drawable.pizza_capricciosa, "Pizza")
)
val burgerOptions = listOf(
MenuItem("Classic Burger", 6.99, R.drawable.classic_burger, "Burger"),
MenuItem("Cheeseburger", 7.49, R.drawable.cheeseburger, "Burger"),
MenuItem("Veggie Burger", 6.99, R.drawable.veggie_burger, "Burger"),
MenuItem("Bacon Burger", 8.99, R.drawable.bacon_burger, "Burger")
)
}
... ...
package com.example.pizzaorder.data
data class OrderUiState(
val userEmail: String = "",
val firstName: String = "",
val lastName: String = "",
val address: String = "",
val quantity: Int = 0,
val pizzaType: String = "",
val date: String = "",
val price: String = "",
val pickupOptions: List<String> = listOf()
)
... ...
package com.example.pizzaorder.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
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.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import com.example.pizzaorder.PizzaScreenPages
import java.text.NumberFormat
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BurgerScreen(viewModel: OrderViewModel, navController: NavHostController) {
val menuItems by viewModel.menuItems.collectAsState()
val totalPrice by viewModel.totalPrice.collectAsState()
var showDialog by remember { mutableStateOf(false) }
Scaffold(
// topBar = {
// TopAppBar(
// title = { Text(stringResource(PizzaScreenPages.Burger.title)) },
// navigationIcon = {
// IconButton(onClick = { navController.navigateUp() }) {
// Icon(Icons.Default.ArrowBack, contentDescription = "Back")
// }
// }
// )
// }
) { innerPadding ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
.padding(16.dp)
) {
Text("Choose Your Burger", style = MaterialTheme.typography.headlineMedium)
LazyColumn {
items(menuItems.filter { it.category == "Burger" }) { item ->
BurgerItemRow(item = item, onQuantityChanged = { quantity ->
viewModel.updateQuantity(item, quantity)
})
}
}
HorizontalDivider(modifier = Modifier.padding(vertical = 16.dp))
Text("Total: $totalPrice", style = MaterialTheme.typography.headlineSmall)
Button(
onClick = { showDialog = true },
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.error)
) {
Text("Clear Order")
}
Button(
onClick = { navController.navigate(PizzaScreenPages.Summary.name) },
modifier = Modifier.fillMaxWidth()
) {
Text("Proceed to Order Summary")
}
if (showDialog) {
AlertDialog(
onDismissRequest = { showDialog = false },
title = { Text("Confirm Clear Order") },
text = { Text("Are you sure you want to clear your order? This action cannot be undone.") },
confirmButton = {
Button(
onClick = {
viewModel.clearOrder()
showDialog = false
}
) {
Text("Yes, Clear Order")
}
},
dismissButton = {
OutlinedButton(onClick = { showDialog = false }) {
Text("Cancel")
}
}
)
}
}
}
}
@Composable
fun BurgerItemRow(item: MenuItem, onQuantityChanged: (Int) -> Unit) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Box (
modifier = Modifier
.size(100.dp)
.padding(8.dp)
){
Image(
painter = painterResource(id = item.imageRes),
contentDescription = item.name,
modifier = Modifier.size(80.dp)
)
}
Column(modifier = Modifier
.weight(1f)
.padding(start = 16.dp)) {
Text(item.name, style = MaterialTheme.typography.bodyLarge)
Text("Price: ${NumberFormat.getCurrencyInstance().format(item.price)}")
}
Row(verticalAlignment = Alignment.CenterVertically) {
IconButton(onClick = { if (item.quantity > 0) onQuantityChanged(item.quantity - 1) }) {
Icon(Icons.Default.KeyboardArrowDown, contentDescription = "Decrease")
}
Text(text = item.quantity.toString(), modifier = Modifier.padding(horizontal = 8.dp))
IconButton(onClick = { onQuantityChanged(item.quantity + 1) }) {
Icon(Icons.Default.KeyboardArrowUp, contentDescription = "Increase")
}
}
}
}
\ No newline at end of file
... ...
package com.example.pizzaorder.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
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.graphics.Color
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavHostController
import com.example.pizzaorder.R
import com.google.firebase.auth.FirebaseAuth
@Composable
fun ForgotPasswordScreen(
navController: NavHostController,
modifier: Modifier = Modifier
) {
var email by remember { mutableStateOf("") }
var message by remember { mutableStateOf("") }
Column(
modifier = modifier,
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
TextField(
value = email,
onValueChange = { email = it },
label = { Text(stringResource(R.string.forgot_email_field)) },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_medium)))
Button(
onClick = {
FirebaseAuth.getInstance().sendPasswordResetEmail(email)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
message = "Password reset email sent."
} else {
message = task.exception?.message ?: "Failed to send email."
}
}
},
modifier = Modifier.fillMaxWidth()
) {
Text(stringResource(R.string.forgot_password_button))
}
if (message.isNotEmpty()) {
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small)))
Text(message, color = if (message.contains("sent")) Color.Green else Color.Red)
}
}
}
... ...
package com.example.pizzaorder.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
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.material3.Button
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
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.graphics.Color
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.NavController
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import com.example.pizzaorder.PizzaScreenPages
import com.example.pizzaorder.R
import com.example.pizzaorder.ui.theme.PizzaTheme
import com.google.firebase.auth.FirebaseAuth
@Composable
fun LoginScreen(
//onLoginButtonClicked: @Composable () -> Unit,
navController: NavHostController = rememberNavController(),
modifier: Modifier = Modifier
) {
var username by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var showDialog by remember { mutableStateOf(false) }
var errorMessage by remember { mutableStateOf("") }
Column (
modifier = modifier,
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
TextField(
value = username,
onValueChange = { username = it },
label = {Text(stringResource(R.string.login_user_field))},
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small)))
TextField(
value = password,
onValueChange = { password = it },
label = {Text(stringResource(R.string.login_passwd_field))},
visualTransformation = PasswordVisualTransformation(),
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_medium)))
Button(
onClick = { handleLogin(
username = username,
password = password,
navController = navController,
showDialogUpdater = { show, message ->
showDialog = show
errorMessage = message
})
},
modifier = Modifier.fillMaxWidth()
) {
Text(stringResource(R.string.login_button))
}
if (errorMessage.isNotEmpty()) {
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small)))
Text(errorMessage, color = Color.Red)
}
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small)))
Button(
onClick = { navController.navigate(PizzaScreenPages.SignUp.name) },
modifier = Modifier.fillMaxWidth()
) {
Text(stringResource(R.string.signup_button))
}
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small)))
Button(
onClick = { navController.navigate(PizzaScreenPages.ForgotPassword.name) },
modifier = Modifier.fillMaxWidth()
) {
Text(stringResource(R.string.forgot_password_button))
}
}
}
private fun handleLogin(
username: String,
password: String,
navController: NavController,
showDialogUpdater: (Boolean, String) -> Unit
) {
//if (username == "user" && password == "password") {
// if (username == "" && password == "") {
// navController.navigate(PizzaScreenPages.Start.name)
// return true
// } else {
// showDialogUpdater(true, "Invalid username or password.")
// return false
// }
if (username.isEmpty() || password.isEmpty()) {
showDialogUpdater(true, "Add the username(email) and the password!")
return
}
FirebaseAuth.getInstance().signInWithEmailAndPassword(username, password)
.addOnCompleteListener {task ->
if (task.isSuccessful) {
navController.navigate(PizzaScreenPages.Start.name)
} else {
showDialogUpdater(true, task.exception?.message ?: "Adresă de mail sau parolă incorectă")
}
}
}
@Preview
@Composable
fun LoginScreenPreview() {
PizzaTheme {
LoginScreen(
navController = rememberNavController(),
modifier = Modifier
.fillMaxSize()
)
}
}
\ No newline at end of file
... ...
package com.example.pizzaorder.ui
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import com.example.pizzaorder.PizzaScreenPages
import com.example.pizzaorder.R
@Composable
fun OrderPlacedScreen(onBack: () -> Unit) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Order Placed!",
style = MaterialTheme.typography.headlineMedium,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Thank you for your order. Your food will be prepared shortly!",
style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(32.dp))
Button(
onClick = onBack,
modifier = Modifier.fillMaxWidth()
) {
Text("Back to Home")
}
}
}
\ No newline at end of file
... ...
package com.example.pizzaorder.ui
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.pizzaorder.R
import com.example.pizzaorder.data.OrderUiState
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import java.text.NumberFormat
data class MenuItem(
val name: String,
val price: Double,
val imageRes: Int,
val category: String,
val quantity: Int = 0,
)
class OrderViewModel : ViewModel() {
private val auth: FirebaseAuth = FirebaseAuth.getInstance()
private val database: FirebaseFirestore = FirebaseFirestore.getInstance()
private val _uiState = MutableStateFlow(
OrderUiState(
userEmail = auth.currentUser?.email ?: "Guest",
firstName = "",
lastName = "",
address = ""
)
)
val uiState: StateFlow<OrderUiState> = _uiState.asStateFlow()
init {
fetchUserDetails()
}
private val _menuItems = MutableStateFlow(
listOf(
MenuItem("Marguerita", 8.99, R.drawable.pizza_marguerita, "Pizza"),
MenuItem("Diavola", 9.99, R.drawable.pizza_diavola, "Pizza"),
MenuItem("Quattro Formaggi", 10.99, R.drawable.pizza_quattro_formaggi, "Pizza"),
MenuItem("Capricciosa", 11.99, R.drawable.pizza_capricciosa, "Pizza"),
MenuItem("Classic Burger", 6.99, R.drawable.classic_burger, "Burger"),
MenuItem("Cheeseburger", 7.49, R.drawable.cheeseburger, "Burger"),
MenuItem("Veggie Burger", 6.99, R.drawable.veggie_burger, "Burger"),
MenuItem("Bacon Burger", 8.99, R.drawable.bacon_burger, "Burger")
)
)
val menuItems: StateFlow<List<MenuItem>> = _menuItems.asStateFlow()
val _selectedItems = MutableStateFlow<List<Pair<String, Double>>>(emptyList())
// val selectedItems: StateFlow<List<Pair<String, Double>>> = _selectedItems.asStateFlow()
val selectedItems: StateFlow<List<MenuItem>> = _menuItems
.map { it.filter { item -> item.quantity > 0 } }
.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
fun updateQuantity(item: MenuItem, newQuantity: Int) {
_menuItems.update { currentList ->
currentList.map { if (it.name == item.name) it.copy(quantity = newQuantity) else it }
}
}
val totalPrice: StateFlow<String> = _menuItems.map { list ->
val total = list.sumOf { it.price * it.quantity }
NumberFormat.getCurrencyInstance().format(total)
}.stateIn(viewModelScope, SharingStarted.Eagerly, "$0.00")
private fun fetchUserDetails() {
auth.currentUser?.let { user ->
database.collection("users").document(user.uid).get()
.addOnSuccessListener { document ->
val firstName = document.getString("firstName") ?: ""
val lastName = document.getString("lastName") ?: ""
val address = document.getString("address") ?: ""
_uiState.update {
it.copy(
firstName = firstName,
lastName = lastName,
address = address
)
}
}
}
}
fun isAuthenticated(): Boolean {
return auth.currentUser != null
}
fun clearItems() {
_selectedItems.value = emptyList()
}
fun resetOrder() {
_uiState.value = OrderUiState(
// pickupOptions = pickupOptions(),
userEmail = auth.currentUser?.email ?: "Guest"
)
clearItems() // Clear selected items when resetting the order
}
fun clearOrder() {
_menuItems.update { currentList ->
currentList.map {it.copy(quantity = 0)}
}
}
}
... ...
package com.example.pizzaorder.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
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.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import com.example.pizzaorder.PizzaScreenPages
import java.text.NumberFormat
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PizzaScreen(viewModel: OrderViewModel, navController: NavHostController) {
val menuItems by viewModel.menuItems.collectAsState()
val totalPrice by viewModel.totalPrice.collectAsState()
var showDialog by remember { mutableStateOf(false) }
Scaffold(
// topBar = {
// TopAppBar(
// title = { Text(stringResource(PizzaScreenPages.Pizza.title)) },
// navigationIcon = {
// IconButton(onClick = { navController.navigateUp() }) {
// Icon(Icons.Default.ArrowBack, contentDescription = "Back")
// }
// }
// )
// }
) { innerPadding ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
.padding(16.dp)
) {
Text("Choose Your Pizza", style = MaterialTheme.typography.headlineMedium)
LazyColumn {
items(menuItems.filter { it.category == "Pizza" }) { item ->
PizzaItemRow(item = item, onQuantityChanged = { quantity ->
viewModel.updateQuantity(item, quantity)
})
}
}
HorizontalDivider(modifier = Modifier.padding(vertical = 16.dp))
Text("Total: $totalPrice", style = MaterialTheme.typography.headlineSmall)
Button(
onClick = { showDialog = true },
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.error)
) {
Text("Clear Order")
}
Button(
onClick = { navController.navigate(PizzaScreenPages.Summary.name) },
modifier = Modifier.fillMaxWidth()
) {
Text("Proceed to Order Summary")
}
if (showDialog) {
AlertDialog(
onDismissRequest = { showDialog = false },
title = { Text("Confirm Clear Order") },
text = { Text("Are you sure you want to clear your order? This action cannot be undone.") },
confirmButton = {
Button(
onClick = {
viewModel.clearOrder()
showDialog = false
}
) {
Text("Yes, Clear Order")
}
},
dismissButton = {
OutlinedButton(onClick = { showDialog = false }) {
Text("Cancel")
}
}
)
}
}
}
}
@Composable
fun PizzaItemRow(item: MenuItem, onQuantityChanged: (Int) -> Unit) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Box (
modifier = Modifier
.size(100.dp)
.padding(8.dp)
) {
Image(
painter = painterResource(id = item.imageRes),
contentDescription = item.name,
// modifier = Modifier.size(80.dp)
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop
)
}
Column(modifier = Modifier
.weight(1f)
.padding(start = 16.dp)) {
Text(item.name, style = MaterialTheme.typography.bodyLarge)
Text("Price: ${NumberFormat.getCurrencyInstance().format(item.price)}")
}
Row(verticalAlignment = Alignment.CenterVertically) {
IconButton(onClick = { if (item.quantity > 0) onQuantityChanged(item.quantity - 1) }) {
Icon(Icons.Default.KeyboardArrowDown, contentDescription = "Decrease")
}
Text(text = item.quantity.toString(), modifier = Modifier.padding(horizontal = 8.dp))
IconButton(onClick = { onQuantityChanged(item.quantity + 1) }) {
Icon(Icons.Default.KeyboardArrowUp, contentDescription = "Increase")
}
}
}
}
//@Composable
//fun PizzaScreen(
// viewModel: OrderViewModel,
// navController: NavHostController
//) {
// SelectOptionScreen(
// title = stringResource(R.string.order_pizza),
// options = listOf(
// "Margherita" to 8.99,
// "Pepperoni" to 9.99,
// "BBQ Chicken" to 10.99,
// "Veggie Delight" to 7.99
// ),
// onAddItem = { item, price -> viewModel.addItem(item, price)},
// onBack = { navController.popBackStack() }
// )
//}
\ No newline at end of file
... ...
package com.example.pizzaorder.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import com.example.pizzaorder.R
import java.text.NumberFormat
//@Composable
//fun SelectOptionScreen(
// title: String,
// options: List<Pair<String, Double>>,
// onAddItem: (String, Double) -> Unit,
// onBack: () -> Unit,
// modifier: Modifier = Modifier
//) {
// Column(
// modifier = modifier
// .fillMaxSize()
// .padding(dimensionResource(R.dimen.padding_medium)),
// verticalArrangement = Arrangement.SpaceBetween
// ) {
// Text(
// text = title,
// style = MaterialTheme.typography.headlineMedium,
// modifier = Modifier.padding(bottom = dimensionResource(R.dimen.padding_medium))
// )
// options.forEach { (name, price) ->
// Row(
// modifier = Modifier
// .fillMaxWidth()
// .padding(vertical = dimensionResource(R.dimen.padding_small)),
// horizontalArrangement = Arrangement.SpaceBetween
// ) {
// Text(name)
// Button(onClick = { onAddItem(name, price) }) {
// Text("Add (${NumberFormat.getCurrencyInstance().format(price)})")
// }
// }
// }
// Button(
// onClick = onBack,
// modifier = Modifier.fillMaxWidth()
// ) {
// Text(stringResource(R.string.back_to_menu))
// }
// }
//}
//
... ...
package com.example.pizzaorder.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
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.graphics.Color
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.navigation.NavHostController
import com.example.pizzaorder.PizzaScreenPages
import com.example.pizzaorder.R
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
@Composable
fun SignUpScreen(
navController: NavHostController,
modifier: Modifier = Modifier
) {
var email by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var confirmPassword by remember { mutableStateOf("") }
var firstName by remember { mutableStateOf("") }
var lastName by remember { mutableStateOf("") }
var address by remember { mutableStateOf("") }
var errorMessage by remember { mutableStateOf("") }
val auth = FirebaseAuth.getInstance()
val database = FirebaseFirestore.getInstance()
Column(
modifier = modifier,
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
TextField(
value = firstName,
onValueChange = { firstName = it },
label = { Text("First Name") },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small)))
TextField(
value = lastName,
onValueChange = { lastName = it },
label = { Text("Last Name") },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small)))
TextField(
value = address,
onValueChange = { address = it },
label = { Text("Address") },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small)))
TextField(
value = email,
onValueChange = { email = it },
label = { Text(stringResource(R.string.signup_email_field)) },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small)))
TextField(
value = password,
onValueChange = { password = it },
label = { Text(stringResource(R.string.signup_password_field)) },
visualTransformation = PasswordVisualTransformation(),
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small)))
TextField(
value = confirmPassword,
onValueChange = { confirmPassword = it },
label = { Text(stringResource(R.string.signup_confirm_password_field)) },
visualTransformation = PasswordVisualTransformation(),
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_medium)))
Button(
onClick = {
if (!isValidEmail(email)) {
errorMessage = "Please enter a valid email address."
} else if (password.length < 6) {
errorMessage = "Password must be at least 6 characters long."
} else if (password != confirmPassword) {
errorMessage = "Passwords do not match."
} else {
FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, password)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
val userId = auth.currentUser?.uid ?: return@addOnCompleteListener
val user = hashMapOf(
"firstName" to firstName,
"lastName" to lastName,
"address" to address,
"email" to email
)
database.collection("users").document(userId).set(user)
.addOnCompleteListener {
navController.navigate(PizzaScreenPages.Login.name)
}
} else {
errorMessage = task.exception?.message ?: "Sign-Up failed."
}
}
}
},
modifier = Modifier.fillMaxWidth()
) {
Text(stringResource(R.string.signup_button))
}
if (errorMessage.isNotEmpty()) {
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small)))
Text(errorMessage, color = Color.Red)
}
}
}
private fun isValidEmail(email: String): Boolean {
return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()
}
\ No newline at end of file
... ...
package com.example.pizzaorder.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
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.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import com.example.pizzaorder.PizzaScreenPages
import com.example.pizzaorder.R
@Composable
fun StartOrderScreen(
viewModel: OrderViewModel = viewModel(),
navController: NavHostController,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.fillMaxSize()
.padding(dimensionResource(R.dimen.padding_medium)),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Button(
onClick = { navController.navigate(PizzaScreenPages.Pizza.name) },
modifier = Modifier
.fillMaxWidth()
.padding(vertical = dimensionResource(R.dimen.padding_small))
) {
Text(stringResource(R.string.order_pizza))
}
Button(
onClick = { navController.navigate(PizzaScreenPages.Burger.name) },
modifier = Modifier
.fillMaxWidth()
.padding(vertical = dimensionResource(R.dimen.padding_small))
) {
Text(stringResource(R.string.order_burgers))
}
Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_medium)))
Button(
onClick = { navController.navigate(PizzaScreenPages.Summary.name) },
modifier = Modifier.fillMaxWidth()
) {
Text(stringResource(R.string.view_order_summary))
}
}
}
... ...
package com.example.pizzaorder.ui
import android.content.Context
import android.content.Intent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Divider
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.pizzaorder.PizzaScreenPages
import com.example.pizzaorder.R
import com.example.pizzaorder.ui.theme.PizzaTheme
import java.text.NumberFormat
@Composable
fun OrderSummaryScreen(
viewModel: OrderViewModel,
onBack: () -> Unit,
onPlace: () -> Unit
) {
val selectedItems by viewModel.selectedItems.collectAsState()
val totalPrice = viewModel.totalPrice.collectAsState().value
var showDialog by remember { mutableStateOf(false) }
val context = LocalContext.current
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
Text("Order Summary", style = MaterialTheme.typography.headlineMedium)
selectedItems.filter { it.quantity > 0 }.forEach { item ->
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text("${item.name} x${item.quantity}")
Text(NumberFormat.getCurrencyInstance().format(item.price * item.quantity))
}
}
HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp))
Text("Total: $totalPrice", style = MaterialTheme.typography.headlineSmall)
Column (
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp) // ✅ Reduce button spacing
) {
Button(
onClick = { showDialog = true },
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.error)
) {
Text("Clear Order")
}
Button(
onClick = onBack,
modifier = Modifier.fillMaxWidth()
) {
Text("Back to Menu")
}
Button(
onClick = {
val orderDetails = selectedItems.joinToString("\n") { item ->
"${item.name} x${item.quantity} - ${
NumberFormat.getCurrencyInstance().format(item.price * item.quantity)
}"
}
val summary = "Order Summary:\n$orderDetails\n\nTotal: $totalPrice"
shareOrder(context, "Your Pizza Order", summary)
},
modifier = Modifier.fillMaxWidth()
) {
Text("Share Order")
}
Button(
onClick = onPlace,
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary)
) {
Text("Place Order")
}
}
if (showDialog) {
AlertDialog(
onDismissRequest = { showDialog = false },
title = { Text("Confirm Clear Order") },
text = { Text("Are you sure you want to clear your order? This action cannot be undone.") },
confirmButton = {
Button(
onClick = {
viewModel.clearOrder()
showDialog = false
}
) {
Text("Yes, Clear Order")
}
},
dismissButton = {
OutlinedButton(onClick = { showDialog = false }) {
Text("Cancel")
}
}
)
}
}
}
fun shareOrder(context: Context, subject: String, summary: String) {
val intent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(Intent.EXTRA_SUBJECT, subject)
putExtra(Intent.EXTRA_TEXT, summary)
}
context.startActivity(
Intent.createChooser(
intent,
context.getString(R.string.new_pizza_order)
)
)
}
... ...
package com.example.pizzaorder.ui.components
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.example.pizzaorder.R
@Composable
fun FormattedPriceLabel(subtotal: String, modifier: Modifier = Modifier) {
Text(
text = stringResource(R.string.subtotal_price, subtotal),
modifier = modifier,
style = MaterialTheme.typography.headlineSmall
)
}
... ...
package com.example.pizzaorder.ui.theme
import androidx.compose.ui.graphics.Color
val md_theme_light_primary = Color(0xFF984062)
val md_theme_light_onPrimary = Color(0xFFFFFFFF)
val md_theme_light_primaryContainer = Color(0xFFFFD9E2)
val md_theme_light_onPrimaryContainer = Color(0xFF3E001E)
val md_theme_light_secondary = Color(0xFF74565F)
val md_theme_light_onSecondary = Color(0xFFFFFFFF)
val md_theme_light_secondaryContainer = Color(0xFFFFD9E2)
val md_theme_light_onSecondaryContainer = Color(0xFF2B151C)
val md_theme_light_tertiary = Color(0xFF7C5635)
val md_theme_light_onTertiary = Color(0xFFFFFFFF)
val md_theme_light_tertiaryContainer = Color(0xFFFFDCC2)
val md_theme_light_onTertiaryContainer = Color(0xFF2E1500)
val md_theme_light_error = Color(0xFFBA1A1A)
val md_theme_light_errorContainer = Color(0xFFFFDAD6)
val md_theme_light_onError = Color(0xFFFFFFFF)
val md_theme_light_onErrorContainer = Color(0xFF410002)
val md_theme_light_background = Color(0xFFFFFBFF)
val md_theme_light_onBackground = Color(0xFF201A1B)
val md_theme_light_surface = Color(0xFFFFFBFF)
val md_theme_light_onSurface = Color(0xFF201A1B)
val md_theme_light_surfaceVariant = Color(0xFFF2DDE2)
val md_theme_light_onSurfaceVariant = Color(0xFF514347)
val md_theme_light_outline = Color(0xFF837377)
val md_theme_light_inverseOnSurface = Color(0xFFFAEEEF)
val md_theme_light_inverseSurface = Color(0xFF352F30)
val md_theme_light_inversePrimary = Color(0xFFFFB0C9)
val md_theme_light_surfaceTint = Color(0xFF984062)
val md_theme_light_outlineVariant = Color(0xFFD5C2C6)
val md_theme_light_scrim = Color(0xFF000000)
val md_theme_dark_primary = Color(0xFFFFB0C9)
val md_theme_dark_onPrimary = Color(0xFF5E1133)
val md_theme_dark_primaryContainer = Color(0xFF7B294A)
val md_theme_dark_onPrimaryContainer = Color(0xFFFFD9E2)
val md_theme_dark_secondary = Color(0xFFE2BDC7)
val md_theme_dark_onSecondary = Color(0xFF422931)
val md_theme_dark_secondaryContainer = Color(0xFF5A3F47)
val md_theme_dark_onSecondaryContainer = Color(0xFFFFD9E2)
val md_theme_dark_tertiary = Color(0xFFEFBD94)
val md_theme_dark_onTertiary = Color(0xFF48290C)
val md_theme_dark_tertiaryContainer = Color(0xFF623F20)
val md_theme_dark_onTertiaryContainer = Color(0xFFFFDCC2)
val md_theme_dark_error = Color(0xFFFFB4AB)
val md_theme_dark_errorContainer = Color(0xFF93000A)
val md_theme_dark_onError = Color(0xFF690005)
val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6)
val md_theme_dark_background = Color(0xFF201A1B)
val md_theme_dark_onBackground = Color(0xFFEBE0E1)
val md_theme_dark_surface = Color(0xFF201A1B)
val md_theme_dark_onSurface = Color(0xFFEBE0E1)
val md_theme_dark_surfaceVariant = Color(0xFF514347)
val md_theme_dark_onSurfaceVariant = Color(0xFFD5C2C6)
val md_theme_dark_outline = Color(0xFF9E8C90)
val md_theme_dark_inverseOnSurface = Color(0xFF201A1B)
val md_theme_dark_inverseSurface = Color(0xFFEBE0E1)
val md_theme_dark_inversePrimary = Color(0xFF984062)
val md_theme_dark_surfaceTint = Color(0xFFFFB0C9)
val md_theme_dark_outlineVariant = Color(0xFF514347)
val md_theme_dark_scrim = Color(0xFF000000)
... ...
package com.example.pizzaorder.ui.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
private val LightColors = lightColorScheme(
primary = md_theme_light_primary,
onPrimary = md_theme_light_onPrimary,
primaryContainer = md_theme_light_primaryContainer,
onPrimaryContainer = md_theme_light_onPrimaryContainer,
secondary = md_theme_light_secondary,
onSecondary = md_theme_light_onSecondary,
secondaryContainer = md_theme_light_secondaryContainer,
onSecondaryContainer = md_theme_light_onSecondaryContainer,
tertiary = md_theme_light_tertiary,
onTertiary = md_theme_light_onTertiary,
tertiaryContainer = md_theme_light_tertiaryContainer,
onTertiaryContainer = md_theme_light_onTertiaryContainer,
error = md_theme_light_error,
errorContainer = md_theme_light_errorContainer,
onError = md_theme_light_onError,
onErrorContainer = md_theme_light_onErrorContainer,
background = md_theme_light_background,
onBackground = md_theme_light_onBackground,
surface = md_theme_light_surface,
onSurface = md_theme_light_onSurface,
surfaceVariant = md_theme_light_surfaceVariant,
onSurfaceVariant = md_theme_light_onSurfaceVariant,
outline = md_theme_light_outline,
inverseOnSurface = md_theme_light_inverseOnSurface,
inverseSurface = md_theme_light_inverseSurface,
inversePrimary = md_theme_light_inversePrimary,
surfaceTint = md_theme_light_surfaceTint,
outlineVariant = md_theme_light_outlineVariant,
scrim = md_theme_light_scrim,
)
private val DarkColors = darkColorScheme(
primary = md_theme_dark_primary,
onPrimary = md_theme_dark_onPrimary,
primaryContainer = md_theme_dark_primaryContainer,
onPrimaryContainer = md_theme_dark_onPrimaryContainer,
secondary = md_theme_dark_secondary,
onSecondary = md_theme_dark_onSecondary,
secondaryContainer = md_theme_dark_secondaryContainer,
onSecondaryContainer = md_theme_dark_onSecondaryContainer,
tertiary = md_theme_dark_tertiary,
onTertiary = md_theme_dark_onTertiary,
tertiaryContainer = md_theme_dark_tertiaryContainer,
onTertiaryContainer = md_theme_dark_onTertiaryContainer,
error = md_theme_dark_error,
errorContainer = md_theme_dark_errorContainer,
onError = md_theme_dark_onError,
onErrorContainer = md_theme_dark_onErrorContainer,
background = md_theme_dark_background,
onBackground = md_theme_dark_onBackground,
surface = md_theme_dark_surface,
onSurface = md_theme_dark_onSurface,
surfaceVariant = md_theme_dark_surfaceVariant,
onSurfaceVariant = md_theme_dark_onSurfaceVariant,
outline = md_theme_dark_outline,
inverseOnSurface = md_theme_dark_inverseOnSurface,
inverseSurface = md_theme_dark_inverseSurface,
inversePrimary = md_theme_dark_inversePrimary,
surfaceTint = md_theme_dark_surfaceTint,
outlineVariant = md_theme_dark_outlineVariant,
scrim = md_theme_dark_scrim,
)
@Composable
fun PizzaTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+ but turned off for training purposes
dynamicColor: Boolean = false,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColors
else -> LightColors
}
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
window.statusBarColor = colorScheme.primary.toArgb()
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
}
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
... ...
package com.example.pizzaorder.ui.theme
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
val Typography = Typography(
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
)
)
... ...
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
... ...
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="utf-8"?>
<vector android:height="70dp" android:viewportHeight="183.71"
android:viewportWidth="208.15" android:width="138.96909dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ff8e00" android:pathData="M20.24 47.26s-5.48 3.45-6.11 6.89c-.63 3.45.63 7.52 2.35 10.18s3.76 4.86 6.27 5.8s4.7.78 4.7.78s5.8 6.58 16.13 15.51S67.08 106 81.96 114.3s20.21 10.34 24.28 10.34s3.92-6.11 3.45-7.99s-26.63-31.01-26.63-31.01L20.24 47.26z"/>
<path android:fillColor="#f5b03e" android:pathData="M31.21 62.46l-3.92-4.23s-4.07-7.68-7.83-7.68s-5.33 3.6-5.33 3.6s-.47-3.92 4.23-11.43s10.65-13.47 15.98-17.23s11.9-8.15 16.29-10.65S64.57 9.2 70.06 7.32c5.48-1.88 17.39-4.23 22.87-3.13c5.48 1.1 7.83 4.86 7.83 8.77s-.94 6.58-1.72 7.36s-5.95 5.17-5.95 5.17L31.21 62.46z"/>
<path android:fillColor="#ffcc8a" android:pathData="M42.2 45.95l-9.71 6.27l-4.07 7.99s.78 2.66 2.04 4.07c1.25 1.41 11.74 11.46 19.25 17.88c5.86 5.01 18.35 15.64 18.35 15.64s.51 5.34 1.1 9.09c.47 2.98.5 7.95 3.64 7.81c3.96-.18 1.68-8.2 4.82-8.12c6.27.16.05 17.12 6.79 17.03c5.37-.07 1.96-9.34 4.65-10.92c1.46-.86 4.36 2.79 9.09 4.86c5.84 2.55 9.4 4.48 11.28 3.6c3.97-1.86-4.4-45.23-5.34-52.59c-.94-7.36-5.62-45.16-5.94-46.41s-6.74-1.41-6.74-1.41l-9.87 3.45l-14.1 1.88l-16.6 9.87l-8.64 10.01z"/>
<path android:fillColor="#cb6c22" android:pathData="M39.75 44.38c-3.08 1.74-7.05 2.71-10.4 8.23c-2.79 4.6-3.53 9.31-1.54 9.67c1.99.36 3.5-6.58 6.15-9.22c4.25-4.25 7.69-4.7 10.13-6.96s5.11-8.4 15.28-13.83c11.85-6.33 18.93-4.66 21.7-5.7c3.62-1.36 4.6-3.58 9.13-4.52c4.79-.99 8.12.92 8.12.92s1.09-2.53-.36-3.71c-1.45-1.18-4.12-2.1-8.58-1.19c-4.88.99-8.5 4.25-9.49 4.34s-11.12-.45-23.15 6.42s-14.28 14.01-16.99 15.55z"/>
<path android:fillColor="#db0d27" android:pathData="M53.58 55.32L37.4 58.85s-.25 3.07-.09 3.98c.54 3.07 4.61 7.96 7.05 8.77s7.41.9 9.04.18c1.63-.72 6.51-4.25 7.14-6.15c.63-1.9.46-9.85-.8-11.12c-1.26-1.26-6.16.81-6.16.81z"/>
<path android:fillColor="#ed6d30" android:pathData="M42.19 50.26c-1.73 1.34-5.06 5.88-4.79 9.13c.27 3.26 5.88 8.95 7.41 9.49s6.51.63 7.78.27s6.15-3.98 6.87-5.24c.72-1.27 1.36-8.32.18-9.58s-4.7-4.97-7.5-5.79c-2.81-.81-8.32.45-9.95 1.72z"/>
<path android:fillColor="#db0d27" android:pathData="M83.6 65.45s-14.32-1.03-14.5-.13s-.51 4.38.4 7.18c.64 1.99 2.17 5.43 6.87 7.41s9.22-.18 10.4-1.09c2.21-1.7 3.62-3.8 3.98-5.06c.36-1.26-7.15-8.31-7.15-8.31z" />
<path android:fillColor="#ed6d30" android:pathData="M76.64 57.94c-2.21.8-7.5 4.07-7.6 7.69c-.09 3.62 2.53 8.05 3.89 9.04s5.88 3.62 9.22 3.44c3.35-.18 7.96-2.89 8.59-4.34c.63-1.45.9-5.7.63-7.87s-4.97-7.05-7.32-7.78c-2.35-.72-5.42-.9-7.41-.18z"/>
<path android:fillColor="#db0d27" android:pathData="M76.1 91.76s-13.11-3.62-13.29-3.35c-.18.27-1.99 2.53-1.54 3.62c.45 1.09 5.06 4.79 6.96 6.42c1.9 1.63 7.64 5 8.32 4.88c1.63-.27 2.89-2.89 2.89-2.89l-3.34-8.68z"/>
<path android:fillColor="#ed6d30" android:pathData="M77.27 86.24c-3.2-2.35-7.87-2.17-10.4-.99c-2.53 1.18-4.07 2.71-4.34 3.89c-.27 1.18 1.82 3.45 2.64 4.08c.81.63 3.27 2.49 3.27 2.49s3.65 2.86 5 3.9c1.88 1.45 4.24 2.27 4.87 2.36c.63.09 3.57-3.71 3.03-8.78c-.28-2.59-1.38-4.97-4.07-6.95z"/>
<path android:fillColor="#db0d27" android:pathData="M100.06 79.01l-4.88-.18s-1.99 3.71-.63 7.87c1.11 3.4 3.44 5.43 7.32 6.51c3.89 1.09 6.06.7 6.06.7l.06-2.73l-7.93-12.17z"/>
<path android:fillColor="#ed6d30" android:pathData="M104.76 72.77s-6.02-.71-9.13 4.88c-2.38 4.29-.72 7.87 1.18 9.95c1.9 2.08 4.79 3.44 6.96 3.62s4.27.01 4.27.01s-.84-5.55-1.66-10.19c-.5-2.78-1.62-8.27-1.62-8.27z"/>
<path android:fillColor="#db0d27" android:pathData="M87.22 33.62s-11.66.36-12.39 1.54s-.72 6.42-.36 8.5s3.53 7.14 9.86 7.23c6.33.09 8.56-1.49 11.02-6.27c2.46-4.78-.1-10.13-.1-10.13l-8.03-.87z"/>
<path android:fillColor="#ed6d30" android:pathData="M87.31 28.28c-2.53-.49-6.06.54-7.78 1.72c-1.72 1.18-4.52 3.62-4.7 5.43c-.18 1.81 1.45 7.05 2.08 8.05c.63.99 3.25 3.68 4.07 4.07c1.9.9 7.14.45 8.68-.09s5.79-3.98 6.24-5.79s.99-4.88-1.09-8.59s-5.15-4.34-7.5-4.8z"/>
<path android:fillColor="#db0d27" android:pathData="M103.78 104.17l-10.41-.45s-1.4 2.81-.98 5.27c.34 2.04 2.03 4.82 5.06 5.99c1.72.66 6.22.23 7.32-.52c2.22-1.52 2.93-4.28 2.86-5.7c-.03-.74-3.85-4.59-3.85-4.59z" />
<path android:fillColor="#ed6d30" android:pathData="M101.51 99.75c-2.7-.41-5.81 1.05-7.15 2.44c-1.34 1.39-1.61 3.13-1.1 5.23c.93 3.84 3.39 4.93 4.53 5.52c1.69.87 6.33.7 7.79-.41c1.45-1.1 2.55-2.98 2.21-5.87c-.35-2.9-1.63-6.21-6.28-6.91z"/>
<path android:fillColor="#fcc12b" android:pathData="M36 31.03c.09 2.16 3.87 1.79 5.36 1.64c1.19-.12 4.17-.37 4.17-2.31s-2.6-1.93-4.54-1.86c-1.87.07-5.07.82-4.99 2.53z"/>
<path android:fillColor="#fcc12b" android:pathData="M56.31 18.31c0 1.42 1.56 1.56 2.53 1.64c.97.07 2.23-.3 2.31-1.41c.07-1.12-.89-1.79-2.31-1.86c-1.49-.09-2.53.43-2.53 1.63z"/>
<path android:fillColor="#fcc12b" android:pathData="M65.61 21.73c1.43 1.55 3.57-.52 4.32-1.49c.74-.97.89-2.46.07-3.2c-.82-.74-2.38.07-3.42 1.04s-1.86 2.68-.97 3.65z"/>
<path android:fillColor="#fcc12b" android:pathData="M81.76 13.84c1.74 1.97 4.61-1.34 5.8-2.46c1.19-1.12 2.16-2.68 1.04-3.94c-1.12-1.26-3.65.52-4.61 1.64c-.97 1.11-3.35 3.5-2.23 4.76z"/>
<path android:fillColor="#fcc12b" android:pathData="M26.92 47.25c1.69.4 2.24-1.6 2.53-3.13c.3-1.56.3-3.05-.97-3.27c-1.44-.25-2.23 1.19-2.46 2.6c-.19 1.27-.66 3.43.9 3.8z"/>
</vector>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
... ...
No preview for this file type
No preview for this file type
No preview for this file type
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Cupcake</string>
<string name="order_pizza">Comandă Pizza</string>
<string name="one_pizza">O pizza</string>
<string name="two_pizzas">Două pizza</string>
<string name="three_pizzas">Trei pizza</string>
<string name="cancel">Anulare</string>
<string name="next">Următorul</string>
<string name="choose_pickup_date">Alege data livrării</string>
<string name="order_summary">Rezumatul comenzii</string>
<string name="send">Trimite</string>
<string name="quantity">Cantitate</string>
<string name="pizza_type">Tipul de pizza</string>
<string name="pickup_date">Data ridicării comenzii</string>
<string name="new_pizza_order">Plasează o nouă comandă</string>
<string name="order_details">Cantitate: %1$s Tip: %2$s Data ridicării comenzii: %3$s Total: %4$s Vă multumim!</string>
<string name="login_user_field">Nume de utilizator</string>
<string name="login_passwd_field">Parolă</string>
<string name="error_message">Nume de utilizator sau parola invalide!</string>
<string name="back_button">Inapoi</string>
</resources>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="padding_small">8dp</dimen>
<dimen name="padding_medium">16dp</dimen>
<dimen name="thickness_divider">1dp</dimen>
</resources>
... ...
<resources>
<string name="app_name">Pizza</string>
<string name="order_pizza">Pizza</string>
<string name="start_order" translatable="false">Start order</string>
<string name="login" translatable="false">Login</string>
<string name="signup" translatable="false"> Sign Up</string>
<string name="forgot_password" translatable="false"> I forgot my password</string>
<string name="forgot_email_field" translatable="false"> Email </string>
<string name="forgot_password_button" translatable="false"> Forgot Button </string>
<string name="signup_button" translatable="false"> Sign Up </string>
<string name="signup_email_field" translatable="false"> Email </string>
<string name="signup_password_field" translatable="false"> Password </string>
<string name="signup_confirm_password_field" translatable="false"> Confirm Password </string>
<string name="one_pizza">One Pizza</string>
<string name="two_pizzas">Two Pizzas</string>
<string name="three_pizzas">Three Pizzas</string>
<string name="choose_pizza_type" translatable="false">Choose Pizza</string>
<string name="choose_burger_type" translatable="false">Choose Burger</string>
<string name="pizza_marguerita" translatable="false">Marguerita</string>
<string name="pizza_quattro_formaggi" translatable="false">Quattro Formaggi</string>
<string name="pizza_quattro_stagioni" translatable="false">Quattro Stagioni</string>
<string name="pizza_diavola" translatable="false">Diavola</string>
<string name="pizza_capriciosa" translatable="false">Capriciosa</string>
<string name="cancel">Cancel</string>
<string name="next">Next</string>
<string name="choose_pickup_date">Choose Pickup Date</string>
<string name="order_summary">Order Summary</string>
<string name="order_placed" translatable="false">Order Placed</string>
<string name="send">Send</string>
<string name="quantity">Quantity</string>
<string name="pizza_type">Pizza Type</string>
<string name="pickup_date">Pickup date</string>
<string name="subtotal_price" translatable="false">Subtotal %s</string>
<string name="total_price" translatable="false">Total %s</string>
<string name="new_pizza_order">New Pizza Order</string>
<string name="order_details">Quantity: %1$s Type: %2$s Pickup date: %3$s Total: %4$s Thank you!</string>
<string name="login_user_field">Username</string>
<string name="login_passwd_field">Password</string>
<string name="error_message">Invalid username or password!</string>
<string name="back_button">Back</string>
<string name="login_button" translatable="false">Login</string>
<string name="menu_button" translatable="false">Menu</string>
<string name="home" translatable="false">Home</string>
<string name="orders" translatable="false">Orders</string>
<string name="logout" translatable="false">Logout</string>
<string name="classic_burger" translatable="false">Classic Burger</string>
<string name="cheeseburger" translatable="false">Cheeseburger</string>
<string name="veggie_burger" translatable="false">Veggie Burger</string>
<string name="bacon_burger" translatable="false">Bacon Burger</string>
<string name="double_burger" translatable="false">Double Burger</string>
<string name="order_burgers" translatable="false">Burgers</string>
<string name="back_to_menu" translatable="false">Back to menu</string>
<string name="view_order_summary" translatable="false">View Summary</string>
<plurals name="pizzas" translatable="false">
<item quantity="one">%d pizza</item>
<item quantity="other">%d pizzas</item>
</plurals>
</resources>
... ...
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.PizzaOrder" parent="android:Theme.Material.Light.NoActionBar" />
</resources>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>
\ No newline at end of file
... ...
package com.example.pizzaorder
import org.junit.Test
import org.junit.Assert.*
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
\ No newline at end of file
... ...
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.compose) apply false
// Add the dependency for the Google services Gradle plugin
id("com.google.gms.google-services") version "4.4.2" apply false
}
\ No newline at end of file
... ...
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. For more details, visit
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
\ No newline at end of file
... ...
[versions]
agp = "8.7.0"
credentials = "1.5.0-beta01"
credentialsPlayServicesAuth = "1.3.0"
credentialsPlayServicesAuthVersion = "1.5.0-beta01"
firebaseBom = "33.6.0"
firebaseBomVersion = "33.8.0"
kotlin = "2.0.0"
coreKtx = "1.15.0"
junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
lifecycleRuntimeKtx = "2.8.7"
activityCompose = "1.9.3"
composeBom = "2024.04.01"
navigationRuntimeKtx = "2.8.4"
navigationCompose = "2.8.4"
activityKtx = "1.9.3"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-credentials = { module = "androidx.credentials:credentials", version.ref = "credentials" }
androidx-credentials-play-services-auth = { module = "androidx.credentials:credentials-play-services-auth", version.ref = "credentialsPlayServicesAuth" }
androidx-credentials-play-services-auth-v150beta01 = { module = "androidx.credentials:credentials-play-services-auth", version.ref = "credentialsPlayServicesAuthVersion" }
firebase-analytics = { module = "com.google.firebase:firebase-analytics" }
firebase-auth = { module = "com.google.firebase:firebase-auth" }
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom" }
firebase-bom-v3380 = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBomVersion" }
firebase-firestore = { module = "com.google.firebase:firebase-firestore" }
google-firebase-analytics = { module = "com.google.firebase:firebase-analytics" }
google-firebase-firestore = { module = "com.google.firebase:firebase-firestore" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-navigation-runtime-ktx = { group = "androidx.navigation", name = "navigation-runtime-ktx", version.ref = "navigationRuntimeKtx" }
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
androidx-activity-ktx = { group = "androidx.activity", name = "activity-ktx", version.ref = "activityKtx" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
... ...
No preview for this file type
#Mon Dec 02 22:14:37 EET 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
... ...
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
... ...
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
... ...
pluginManagement {
repositories {
google {
content {
includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
}
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "CupcakeOrder"
include(":app")
\ No newline at end of file
... ...