13 KiB
13 KiB
📂 PROJECT STRUCTURE & FILE OVERVIEW
Complete Project Structure
Starter-EAS-2025-2026/
│
├── 📄 README.md (Project description)
├── 📄 Mockup.png (UI mockup image)
├── 📄 n8n-workflow-EAS.json (Webhook configuration)
│
├── 📋 DEVELOPMENT_GUIDE.md ✨ (User & developer guide)
├── 📋 CHANGELOG.md ✨ (Version history & changes)
├── 📋 IMPLEMENTATION_NOTES.md ✨ (Technical config)
├── 📋 IMPLEMENTATION_SUMMARY.md ✨ (Project summary)
├── 📋 QUICK_REFERENCE.md ✨ (Quick lookup)
│
├── 🔧 build.gradle.kts (Project-level build config)
├── 🔧 settings.gradle.kts (Project settings)
├── 🔧 gradle.properties (Gradle properties)
├── 📜 gradlew & gradlew.bat (Gradle wrappers)
├── 📄 local.properties (Local SDK configuration)
│
├── gradle/
│ ├── wrapper/
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
│ └── libs.versions.toml (Dependency versions)
│
└── app/
├── 🔧 build.gradle.kts ✨ (App-level build config)
├── 📄 proguard-rules.pro (Proguard configuration)
│
├── src/
│ ├── main/
│ │ ├── 📄 AndroidManifest.xml ✨ (App manifest & permissions)
│ │ │
│ │ ├── java/
│ │ │ └── id/ac/ubharajaya/sistemakademik/
│ │ │ ├── 📄 MainActivity.kt ✨ (Main app file)
│ │ │ │ ├── Util Functions
│ │ │ │ │ ├── bitmapToBase64()
│ │ │ │ │ ├── obfuscateCoordinates()
│ │ │ │ │ ├── calculateDistance()
│ │ │ │ │ └── isWithinAbsensiRadius()
│ │ │ │ │
│ │ │ │ ├── MainActivity Class
│ │ │ │ │ ├── onCreate()
│ │ │ │ │ └── Navigation Logic
│ │ │ │ │
│ │ │ │ ├── kirimKeN8n() ✨ (Webhook function)
│ │ │ │ │
│ │ │ │ ├── @Composables
│ │ │ │ │ ├── LoginScreen()
│ │ │ │ │ ├── RegisterScreen()
│ │ │ │ │ ├── AbsensiScreen() ✨
│ │ │ │ │ ├── HistoryScreen() ✨
│ │ │ │ │ └── AttendanceCard() ✨
│ │ │ │
│ │ │ └── 📄 DatabaseHelper.kt ✨ (Database management)
│ │ │ ├── onCreate() - Create tables
│ │ │ ├── onUpgrade() - DB migration
│ │ │ │
│ │ │ ├── User Functions
│ │ │ │ ├── addUser()
│ │ │ │ ├── checkUser()
│ │ │ │ └── getUserName()
│ │ │ │
│ │ │ ├── Attendance Functions ✨
│ │ │ │ ├── addAttendanceRecord()
│ │ │ │ └── getAttendanceHistory()
│ │ │ │
│ │ │ ├── Database Schema
│ │ │ │ ├── TABLE_USERS
│ │ │ │ └── TABLE_ATTENDANCE ✨
│ │ │ │
│ │ │ └── AttendanceRecord Data Class ✨
│ │ │
│ │ ├── res/
│ │ │ ├── drawable/ (App icons & images)
│ │ │ ├── layout/ (XML layouts)
│ │ │ ├── values/
│ │ │ │ ├── colors.xml (App color scheme)
│ │ │ │ ├── strings.xml (String resources)
│ │ │ │ ├── themes.xml (App theme)
│ │ │ │ └── other configurations
│ │ │ ├── xml/
│ │ │ │ ├── backup_rules.xml
│ │ │ │ └── data_extraction_rules.xml
│ │ │ └── ...other resources
│ │ │
│ │ └── ui/
│ │ └── theme/
│ │ ├── Color.kt
│ │ ├── Theme.kt
│ │ └── Type.kt
│ │
│ ├── androidTest/ (UI/Integration tests - empty)
│ └── test/ (Unit tests - empty)
│
└── build/ (Generated - ignore)
├── generated/
├── intermediates/
└── outputs/
Legend:
✨ = Modified or new in v1.1.0
📄 = Source code file
🔧 = Configuration file
📋 = Documentation file
📜 = Build script file
📊 Code Statistics
Modified Files Summary
MainActivity.kt
Total Lines: 611
Added: ~350 lines (57%)
Components:
- 4 Utility functions (new)
- 5 @Composable screens (1 new + 1 enhanced)
- 1 Data class reference
- 50+ state management vars
- 3 activity lifecycle methods
DatabaseHelper.kt
Total Lines: 133
Added: ~65 lines (49%)
Components:
- 2 Database tables (1 new)
- 6 Database functions (2 new)
- 1 Data class (new)
- 2 Database migration handlers
build.gradle.kts
Total Lines: 66
Added: 1 dependency line (2%)
Components:
- 14 total dependencies
- 1 new: material-icons-extended
🗂️ File Categories
Core Application Files
MainActivity.kt- Main app logic & UIDatabaseHelper.kt- Database operationsAndroidManifest.xml- App configuration & permissions
Build & Configuration Files
build.gradle.kts(app & project level)settings.gradle.ktsgradle.propertieslocal.propertiesgradle/libs.versions.toml
Resource Files
res/values/*.xml- Colors, strings, themesres/drawable/- Icons & imagesres/layout/- XML layouts (if any)res/xml/- Backup & data extraction rules
Documentation Files (NEW)
DEVELOPMENT_GUIDE.md- 650+ linesCHANGELOG.md- 400+ linesIMPLEMENTATION_NOTES.md- 500+ linesIMPLEMENTATION_SUMMARY.md- 400+ linesQUICK_REFERENCE.md- 300+ linesPROJECT_STRUCTURE.md- This file
📦 Dependency Tree
App Dependencies:
├── Kotlin & Android Core
│ ├── androidx.core:core-ktx
│ ├── androidx.lifecycle:lifecycle-runtime-ktx
│ └── androidx.activity:activity-compose
│
├── Compose Framework
│ ├── androidx.compose.ui:ui
│ ├── androidx.compose.ui:ui-graphics
│ ├── androidx.compose.ui:ui-tooling-preview
│ ├── androidx.compose.material3:material3
│ ├── androidx.compose.material:material-icons-extended ✨
│ └── platform(androidx.compose.bom)
│
├── Google Services
│ └── com.google.android.gms:play-services-location
│
└── Testing (included but not used)
├── junit
├── androidx.test.ext:junit
└── androidx.test.espresso:espresso-core
🔄 Data Flow Through Files
USER INPUT
↓
MainActivity.kt
├─ LoginScreen() / RegisterScreen() → DatabaseHelper.addUser(), checkUser()
└─ AbsensiScreen()
├─ Location API → calculateDistance(), isWithinAbsensiRadius()
├─ Camera Intent → bitmapToBase64()
├─ kirimKeN8n()
│ ├─ DatabaseHelper.addAttendanceRecord()
│ └─ Webhook POST
└─ HistoryScreen()
└─ DatabaseHelper.getAttendanceHistory()
└─ AttendanceCard() display
💾 Database Schema Location
DatabaseHelper.kt:
Tables Definition (onCreate):
├── users
│ ├── id (INT PRIMARY KEY AUTOINCREMENT)
│ ├── username (TEXT)
│ ├── npm (TEXT UNIQUE)
│ └── password (TEXT)
│
└── attendance ✨
├── id (INT PRIMARY KEY AUTOINCREMENT)
├── npm (TEXT FOREIGN KEY)
├── timestamp (INT)
├── latitude (REAL)
├── longitude (REAL)
└── status (TEXT)
Query Methods:
├── addAttendanceRecord() - INSERT
└── getAttendanceHistory() - SELECT with ORDER BY
🎯 Code Organization Principles
Separation of Concerns
UI Layer (Composables)
↓
Business Logic Layer (Functions)
↓
Data Access Layer (DatabaseHelper)
↓
Data Layer (SQLite Database)
Module Organization
MainActivity.kt:
├── UTIL SECTION (Helper functions)
├── ACTIVITY SECTION (Main activity)
├── SCREEN SECTIONS (UI composables)
└── COMPONENT SECTIONS (Reusable components)
DatabaseHelper.kt:
├── COMPANION CONSTANTS
├── DATABASE SCHEMA (onCreate)
├── MIGRATION LOGIC (onUpgrade)
├── USER OPERATIONS
├── ATTENDANCE OPERATIONS ✨
└── DATA CLASSES
🔐 Permissions Configuration
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" android:required="false" />
Runtime Request (in MainActivity.kt)
rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission())
├── ACCESS_FINE_LOCATION
└── CAMERA
📱 Screen Navigation Structure
Navigation State Machine
MainActivity.onCreate()
├─ setContent {
│ ├─ currentScreen: String
│ │ ├── "login" → LoginScreen()
│ │ ├── "register" → RegisterScreen()
│ │ ├── "home" → AbsensiScreen()
│ │ └── "history" → HistoryScreen()
│ │
│ └─ Navigation Callbacks
│ ├─ onLoginSuccess()
│ ├─ onNavigateToRegister()
│ ├─ onLogout()
│ └─ onNavigateToHistory() ✨
✨ New Features by File
MainActivity.kt Additions
UTIL FUNCTIONS:
├── obfuscateCoordinates() ✨
├── calculateDistance() ✨
└── isWithinAbsensiRadius() ✨
UPDATED FUNCTIONS:
├── kirimKeN8n() - with validation ✨
├── AbsensiScreen() - new params ✨
└── onCreate() - new navigation ✨
NEW SCREENS:
├── HistoryScreen() ✨
└── AttendanceCard() ✨
DatabaseHelper.kt Additions
DATABASE:
├── TABLE_ATTENDANCE ✨
├── DATABASE_VERSION → 2 ✨
└── onUpgrade() migration ✨
FUNCTIONS:
├── addAttendanceRecord() ✨
└── getAttendanceHistory() ✨
DATA CLASSES:
└── AttendanceRecord ✨
build.gradle.kts Additions
DEPENDENCIES:
└── material-icons-extended:1.6.0 ✨
📊 Lines of Code Summary
| Component | Lines | Status |
|---|---|---|
| MainActivity.kt | 611 | Modified |
| DatabaseHelper.kt | 133 | Modified |
| build.gradle.kts | 66 | Modified |
| AndroidManifest.xml | 35 | Unchanged |
| Total Code | 845 | - |
| Documentation | 2,200+ | New |
🔍 File Cross-References
Key Relationships
MainActivity.kt
├─ imports DatabaseHelper
├─ imports Material Design 3
├─ uses Compose Foundation
└─ calls Google Location Services
DatabaseHelper.kt
├─ extends SQLiteOpenHelper
├─ defines AttendanceRecord
└─ no external dependencies
build.gradle.kts
├─ imports from gradle/libs.versions.toml
├─ configures app namespace
└─ defines all dependencies
AndroidManifest.xml
├─ declares MainActivity
├─ lists all permissions
└─ sets app theme & icon
🎬 Execution Flow
APP STARTUP
└─ MainActivity.onCreate()
├─ DatabaseHelper initialized
├─ UI composed with Jetpack Compose
├─ Navigation state set to "login"
└─ User sees LoginScreen()
USER LOGIN
└─ LoginScreen() button click
├─ DatabaseHelper.checkUser()
├─ If valid:
│ ├─ Set navigationState = "home"
│ └─ Show AbsensiScreen()
└─ If invalid:
└─ Show Toast error
USER ABSENSI
└─ AbsensiScreen() "Kirim Absensi" button
├─ Validate inputs (location, photo)
├─ kirimKeN8n() called
│ ├─ Validate radius: isWithinAbsensiRadius()
│ ├─ Save locally: DatabaseHelper.addAttendanceRecord()
│ ├─ Send to webhook via HTTPS POST
│ └─ Show feedback Toast
└─ Data now in database
USER HISTORY
└─ AbsensiScreen() "Lihat Riwayat" button
├─ Set navigationState = "history"
├─ HistoryScreen() loads
│ ├─ Call DatabaseHelper.getAttendanceHistory()
│ ├─ Map to List<AttendanceRecord>
│ └─ Render AttendanceCard() items
└─ User sees list with status
Last Updated: 14 January 2026 Version: 1.1.0 Status: ✅ Complete & Documented