commit b04aa33737702eebb8f3493e36eda43b0dc7205c Author: Nucha Date: Wed Jun 11 22:58:54 2025 +0700 update diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.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 diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..61d5ece --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +Attendance Manager \ No newline at end of file diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml new file mode 100644 index 0000000..4a53bee --- /dev/null +++ b/.idea/AndroidProjectSystem.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b86273d --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..b268ef3 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..639c779 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..f0c6ad0 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,50 @@ + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..74dd639 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..16660f1 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..bdbcbf8 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,73 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.kotlin.compose) +} + +android { + namespace = "com.yourcompany.attendancemanager" + compileSdk = 35 + + defaultConfig { + applicationId = "com.yourcompany.attendancemanager" + minSdk = 26 + targetSdk = 34 + 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 + viewBinding = 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.compose) + implementation(libs.retrofit) + implementation(libs.converter.gson) + implementation(libs.play.services.location) + implementation(libs.androidx.core.ktx.v1110) + implementation(libs.androidx.work.runtime.ktx) + implementation(libs.material) + implementation(libs.androidx.appcompat) + implementation(libs.androidx.constraintlayout) + implementation(libs.androidx.navigation.fragment.ktx) + implementation(libs.androidx.navigation.ui.ktx) + implementation(libs.ads.mobile.sdk) + 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) + +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# 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 \ No newline at end of file diff --git a/app/src/androidTest/java/com/yourcompany/attendancemanager/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/yourcompany/attendancemanager/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..74a778c --- /dev/null +++ b/app/src/androidTest/java/com/yourcompany/attendancemanager/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.yourcompany.attendancemanager + +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.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.yourcompany.attendancemanager", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..192eb4d --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/ApiClient.kt b/app/src/main/java/com/yourcompany/attendancemanager/ApiClient.kt new file mode 100644 index 0000000..cb76bb7 --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/ApiClient.kt @@ -0,0 +1,14 @@ +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +object ApiClient { + private const val BASE_URL = "http://10.0.2.2:8000" // ใช้ 10.0.2.2 แทน localhost สำหรับ emulator + + val authApi: AuthApiService by lazy { + Retrofit.Builder() + .baseUrl(BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + .build() + .create(AuthApiService::class.java) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/AttendanceSummaryScreen.kt b/app/src/main/java/com/yourcompany/attendancemanager/AttendanceSummaryScreen.kt new file mode 100644 index 0000000..4d032c5 --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/AttendanceSummaryScreen.kt @@ -0,0 +1,14 @@ +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun AttendanceSummaryScreen() { + Column(modifier = Modifier.fillMaxSize().padding(16.dp)) { + Text("Attendance Summary Screen") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/AuthApiService.kt b/app/src/main/java/com/yourcompany/attendancemanager/AuthApiService.kt new file mode 100644 index 0000000..513a045 --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/AuthApiService.kt @@ -0,0 +1,8 @@ +import retrofit2.http.Body +import retrofit2.http.POST +import retrofit2.Response + +interface AuthApiService { + @POST("/auth/login") + suspend fun login(@Body request: LoginRequest): Response +} \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/AuthViewModel.kt b/app/src/main/java/com/yourcompany/attendancemanager/AuthViewModel.kt new file mode 100644 index 0000000..34f6941 --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/AuthViewModel.kt @@ -0,0 +1,51 @@ +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.launch +data class LoginRequest( + val email: String, + val password: String +) + +data class LoginResponse( + val token: String +) +class AuthViewModel : ViewModel() { + + fun login(email: String, password: String, callback: (Boolean, String?) -> Unit) { + viewModelScope.launch { + if (email.isBlank() || password.isBlank()) { + callback(false, "Email หรือ Password ว่าง") + return@launch + } +// +// // จำลองการเรียก API ที่ใช้เวลาประมาณ 2 วินาที +// delay(2000) +// +// +// +// // ตัวอย่าง login จำลอง: email = admin@example.com, password = 1234 +// if (email == "admin@example.com" && password == "1234") { +// callback(true, null) +// } else { +// callback(false, "อีเมลหรือรหัสผ่านไม่ถูกต้อง") +// } +// } + try { + val response = ApiClient.authApi.login(LoginRequest(email, password)) + if (response.isSuccessful) { + val token = response.body()?.token + if (!token.isNullOrBlank()) { + // ✅ login สำเร็จ + callback(true, null) + } else { + callback(false, "ไม่พบ token") + } + } else { + callback(false, "อีเมลหรือรหัสผ่านไม่ถูกต้อง") + } + } catch (e: Exception) { + callback(false, "เกิดข้อผิดพลาดในการเชื่อมต่อ: ${e.localizedMessage}") + } + } +} +} diff --git a/app/src/main/java/com/yourcompany/attendancemanager/CheckInOutScreen.kt b/app/src/main/java/com/yourcompany/attendancemanager/CheckInOutScreen.kt new file mode 100644 index 0000000..0f4a2a1 --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/CheckInOutScreen.kt @@ -0,0 +1,14 @@ +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun CheckInOutScreen() { + Column(modifier = Modifier.fillMaxSize().padding(16.dp)) { + Text("Check In / Out Screen") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/CustomButton.kt b/app/src/main/java/com/yourcompany/attendancemanager/CustomButton.kt new file mode 100644 index 0000000..56a9616 --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/CustomButton.kt @@ -0,0 +1,15 @@ +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +@Composable +fun CustomButton(text: String, onClick: () -> Unit) { + Button( + onClick = onClick, + modifier = Modifier.fillMaxWidth() + ) { + Text(text) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/FirstFragment.kt b/app/src/main/java/com/yourcompany/attendancemanager/FirstFragment.kt new file mode 100644 index 0000000..ed893dc --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/FirstFragment.kt @@ -0,0 +1,44 @@ +package com.yourcompany.attendancemanager + +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.navigation.fragment.findNavController +import com.yourcompany.attendancemanager.databinding.FragmentFirstBinding + +/** + * A simple [Fragment] subclass as the default destination in the navigation. + */ +class FirstFragment : Fragment() { + + private var _binding: FragmentFirstBinding? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + + _binding = FragmentFirstBinding.inflate(inflater, container, false) + return binding.root + + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.buttonFirst.setOnClickListener { + findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment) + } + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/InputField.kt b/app/src/main/java/com/yourcompany/attendancemanager/InputField.kt new file mode 100644 index 0000000..27b7baa --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/InputField.kt @@ -0,0 +1,18 @@ +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation + +@Composable +fun InputField(label: String, text: String, isPassword: Boolean = false, onTextChanged: (String) -> Unit) { + OutlinedTextField( + value = text, + onValueChange = onTextChanged, + label = { Text(label) }, + modifier = Modifier.fillMaxWidth(), + visualTransformation = if (isPassword) PasswordVisualTransformation() else VisualTransformation.None + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/LeaveRequestScreen.kt b/app/src/main/java/com/yourcompany/attendancemanager/LeaveRequestScreen.kt new file mode 100644 index 0000000..8dea86a --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/LeaveRequestScreen.kt @@ -0,0 +1,14 @@ +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun LeaveRequestScreen() { + Column(modifier = Modifier.fillMaxSize().padding(16.dp)) { + Text("Leave Request Screen") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/LeaveSummaryScreen.kt b/app/src/main/java/com/yourcompany/attendancemanager/LeaveSummaryScreen.kt new file mode 100644 index 0000000..0457d13 --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/LeaveSummaryScreen.kt @@ -0,0 +1,14 @@ +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun LeaveSummaryScreen() { + Column(modifier = Modifier.fillMaxSize().padding(16.dp)) { + Text("Leave Summary Screen") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/LoginScreen.kt b/app/src/main/java/com/yourcompany/attendancemanager/LoginScreen.kt new file mode 100644 index 0000000..7318a68 --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/LoginScreen.kt @@ -0,0 +1,54 @@ +import ads_mobile_sdk.h5 +import android.widget.Toast +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.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.yourcompany.attendancemanager.R + +@Composable +fun LoginScreen(onLoginSuccess: () -> Unit) { + val viewModel: AuthViewModel = viewModel() + val email = remember { mutableStateOf("") } + val password = remember { mutableStateOf("") } + val ctx = LocalContext.current + val loginText = stringResource(R.string.login) + val loginFailedText = stringResource(R.string.login_failed) + val isLoading = remember { mutableStateOf(false) } + + Column(modifier = Modifier.fillMaxSize().padding(16.dp)) { + Text(text = loginText, style = MaterialTheme.typography.headlineMedium) + InputField(label = stringResource(R.string.email), text = email.value) { email.value = it } + Spacer(modifier = Modifier.height(8.dp)) + InputField( + label = stringResource(R.string.password), + text = password.value, + isPassword = true + ) { password.value = it } + Spacer(modifier = Modifier.height(16.dp)) + CustomButton(text = if (isLoading.value) "กำลังเข้าสู่ระบบ..." else loginText) { + isLoading.value = true + viewModel.login(email.value, password.value) { success, errorMsg -> + isLoading.value = false + if (success) { + onLoginSuccess() + } else { + Toast.makeText(ctx, errorMsg ?: loginFailedText, Toast.LENGTH_SHORT).show() + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/MainActivity.kt b/app/src/main/java/com/yourcompany/attendancemanager/MainActivity.kt new file mode 100644 index 0000000..768e6f8 --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/MainActivity.kt @@ -0,0 +1,35 @@ +package com.yourcompany.attendancemanager + +import AttendanceSummaryScreen +import CheckInOutScreen +import LeaveRequestScreen +import LeaveSummaryScreen +import LoginScreen +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import com.yourcompany.attendancemanager.ui.theme.AttendanceManagerTheme + + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + AttendanceManagerTheme { + val navController = rememberNavController() + NavHost(navController, startDestination = "login") { + composable("login") { + LoginScreen(onLoginSuccess = { navController.navigate("check") }) + } + composable("check") { CheckInOutScreen() } + composable("leave") { LeaveRequestScreen() } + composable("leaveSummary"){ LeaveSummaryScreen() } + composable("attendanceSummary"){ AttendanceSummaryScreen() } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/SecondFragment.kt b/app/src/main/java/com/yourcompany/attendancemanager/SecondFragment.kt new file mode 100644 index 0000000..1cc54ed --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/SecondFragment.kt @@ -0,0 +1,44 @@ +package com.yourcompany.attendancemanager + +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.navigation.fragment.findNavController +import com.yourcompany.attendancemanager.databinding.FragmentSecondBinding + +/** + * A simple [Fragment] subclass as the second destination in the navigation. + */ +class SecondFragment : Fragment() { + + private var _binding: FragmentSecondBinding? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + + _binding = FragmentSecondBinding.inflate(inflater, container, false) + return binding.root + + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.buttonSecond.setOnClickListener { + findNavController().navigate(R.id.action_SecondFragment_to_FirstFragment) + } + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/theme/Theme.kt b/app/src/main/java/com/yourcompany/attendancemanager/theme/Theme.kt new file mode 100644 index 0000000..567a824 --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/theme/Theme.kt @@ -0,0 +1,21 @@ +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.material3.Typography +import androidx.compose.material3.Shapes +import androidx.compose.runtime.Composable + +@Composable +fun AttendanceManagerTheme(content: @Composable () -> Unit) { + val colorScheme = lightColorScheme( + // กำหนดสีเพิ่มเติมถ้าต้องการ + // primary = Color(0xFF6200EE), + // secondary = Color(0xFF03DAC6), + ) + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography(), + shapes = Shapes(), + content = content + ) +} diff --git a/app/src/main/java/com/yourcompany/attendancemanager/ui/theme/Color.kt b/app/src/main/java/com/yourcompany/attendancemanager/ui/theme/Color.kt new file mode 100644 index 0000000..47cbd86 --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.yourcompany.attendancemanager.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/ui/theme/Theme.kt b/app/src/main/java/com/yourcompany/attendancemanager/ui/theme/Theme.kt new file mode 100644 index 0000000..aefe251 --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/ui/theme/Theme.kt @@ -0,0 +1,58 @@ +package com.yourcompany.attendancemanager.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.ui.platform.LocalContext + +private val DarkColorScheme = darkColorScheme( + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 +) + +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ +) + +@Composable +fun AttendanceManagerTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + 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 -> DarkColorScheme + else -> LightColorScheme + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/yourcompany/attendancemanager/ui/theme/Type.kt b/app/src/main/java/com/yourcompany/attendancemanager/ui/theme/Type.kt new file mode 100644 index 0000000..853b82a --- /dev/null +++ b/app/src/main/java/com/yourcompany/attendancemanager/ui/theme/Type.kt @@ -0,0 +1,34 @@ +package com.yourcompany.attendancemanager.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 + +// Set of Material typography styles to start with +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ +) \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml new file mode 100644 index 0000000..e416e1c --- /dev/null +++ b/app/src/main/res/layout/content_main.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_first.xml b/app/src/main/res/layout/fragment_first.xml new file mode 100644 index 0000000..44baecd --- /dev/null +++ b/app/src/main/res/layout/fragment_first.xml @@ -0,0 +1,35 @@ + + + + + +