Commit 63f2dfc2 authored by Ilham Maulana's avatar Ilham Maulana 💻

first commit

parents
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "761747bfc538b5af34aa0d3fac380f1bc331ec49"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: android
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: ios
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: linux
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: macos
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: web
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: windows
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
# library_app
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
analyzer:
errors:
library_private_types_in_public_api: ignore
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks
plugins {
id "com.android.application"
id "kotlin-android"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader("UTF-8") { reader ->
localProperties.load(reader)
}
}
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
if (flutterVersionCode == null) {
flutterVersionCode = "1"
}
def flutterVersionName = localProperties.getProperty("flutter.versionName")
if (flutterVersionName == null) {
flutterVersionName = "1.0"
}
android {
namespace = "com.example.library_app"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.library_app"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutterVersionCode.toInteger()
versionName = flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.debug
}
}
}
flutter {
source = "../.."
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="library_app"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>
package com.example.library_app
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity()
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = "../build"
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false
id "org.jetbrains.kotlin.android" version "1.7.10" apply false
}
include ":app"
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<svg xmlns="http://www.w3.org/2000/svg" width="731.67004" height="625.99672" viewBox="0 0 731.67004 625.99672" xmlns:xlink="http://www.w3.org/1999/xlink"><path id="uuid-5ef434d5-ec3b-4be2-96d4-c13c471d6de8-619" d="M376.76337,311.69684c2.62042,10.50058-.88501,20.35364-7.82874,22.00711-6.9437,1.6535-14.69479-5.51819-17.31467-16.02283-1.10635-4.18195-1.15591-8.56552-.14453-12.784l-10.51895-44.63046,21.86432-4.45937,8.04852,44.47118c2.88568,3.29129,4.90674,7.20667,5.89404,11.41837,0,0,0,.00003,0,0Z" fill="#fdadb0"/><g><polygon points="285.09476 566.89746 286.44183 596.14917 285.0928 604.24353 289.81448 613.68689 326.91345 617.73407 328.93704 600.19635 309.37576 590.07843 308.80716 573.55005 285.09476 566.89746" fill="#fdadb0"/><path d="M324.21533,610.98877l-2.02359,2.69812-38.85165-11.19604s1.75269,17.26678,1.75269,20.63947,64.08002,3.37262,73.72256,2.02356,6.54608-10.11792,6.54608-10.11792l-39.9877-18.92865-1.15842,14.88147h.00003Z" fill="#2f2e43"/></g><g><polygon points="188.43921 545.36505 180.3541 573.50946 176.48561 580.7464 177.93686 591.20416 211.78952 606.91113 219.31921 590.94342 204.0247 575.09747 213.6188 550.21924 188.43921 545.36505" fill="#fdadb0"/><path d="M211.39197,599.65723l-2.78062,1.90863-33.22536-23.04083s-3.86533,16.91962-4.94466,20.11487,59.63062,23.70258,69.19777,25.51038,9.43983-7.49084,9.43983-7.49084l-31.82701-30.73029-5.85995,13.72815h.00002l-.00002-.00006Z" fill="#2f2e43"/></g><polygon points="287.70996 83.9671 289.12659 106.97251 246.16866 109.15169 259.47134 78.84175 287.70996 83.9671" fill="#fdadb0"/><path d="M290.22263,103.53149c-11.5144,5.13574-29.93115,3.73068-50.80225,0l-3.26205,144.59672s65.2879,13.12622,87.73538-11.0934l-11.81445-118.14453-21.85663-15.3588s0,.00002,0,.00002Z" fill="#e0e1e2"/><polygon points="316.80505 240.57915 224.63489 249.689 179.1496 558.53558 214.00221 558.53558 273.68228 346.90921 278.40808 586.74255 310.3071 586.74255 337.48035 293.15347 316.80505 240.57915" fill="#2f2e43"/><path d="M252.52422,94.67065l-30.96834,18.32601c-11.73149,6.9423-17.26108,20.9566-13.43071,34.03909l23.9342,81.74651s-38.97484,66.95746-26.31018,72.86465c28.4593,13.27441,70.92659,10.04227,70.92659,10.04227l-9.49146-160.30917-14.66013-56.70937,.00002,.00002s0-.00002,0-.00002Z" fill="#3f3d58"/><path d="M288.87726,102.92358l35.01645,13.60382,8.27011,101.01359,23.16013,81.37585c-39.22784,14.31915-35.56531,7.64648-35.56531,7.64648l-6.49796-140.41524-24.38345-63.22452,.00003,.00002s0-.00002,0-.00002Z" fill="#3f3d58"/><path d="M340.03061,297.19608l-.11996-.5528-35.79376-165.55103c-1.00015-4.62562,.2789-9.2623,3.50848-12.72181,3.22968-3.46,7.76883-5.05348,12.453-4.37245,5.77716,.83993,10.4024,5.04821,11.7822,10.72128l39.31598,161.6061-31.1459,10.8707h-.00003Z" fill="#3f3d58"/><circle cx="269.06998" cy="55.22682" r="34.85209" fill="#fdadb0"/><path d="M285.65121,10.07328c7.67664,2.69811,12.06934,4.24203,16.09317,8.11845,6.7966,6.5479,7.9184,15.29825,8.96057,23.4287,.8154,6.36049,1.86963,14.5842-1.85501,23.97997-1.27109,3.20641-7.43674,17.49225-19.23843,19.29762-2.31772,.3545-7.75916,.44773-6.19073-.71022,14.51544-10.71641,20.71027-17.18593,20.20239-33.70173-.31549-10.26221-15.99649-21.34199-25.30756-23.33377-3.92233-.83893-9.14426-.07252-12.88876,3.00152-7.82565,6.42446-7.49179,32.99092-15.74361,38.5444-3.39352,2.2839-1.13228-13.79295-3.52356-11.18581-4.71809,5.14422-1.69165,13.02216-.84383,16.02233,4.02164,14.23081,11.60382,15.62369,15.53183,27.77607,4.24091,13.12018-1.09653,25.47273-2.3623,28.40192-2.20163,5.0956-5.98048,13.84068-14.61356,18.03613-10.95815,5.32527-19.59561-1.60928-24.69019,4.33572-2.84799,3.32346-1.30746,6.84323-6.45113,17.1805-1.67912,3.37442-2.51868,5.06184-3.26193,5.00195-3.51727-.2832-9.21196-28.43777-.00171-54.65797,3.86536-11.00368,7.65221-21.78448,17.80276-30.21467,5.36661-4.45687,9.86757-6.0607,11.14871-11.2654,1.83022-7.4356-5.76976-10.60925-7.29326-22.3414-1.04176-8.02364-1.77267-19.49902,1.06029-26.85414,2.67509-6.94578,4.99741-12.97519,11.076-18.44197,1.4599-1.31307,13.24496-10.23845,25.7406-10.49022,5.75281-.11574,9.97934,7.72783,16.64917,10.072h.00006Z" fill="#2f2e43"/><g><circle cx="359.29443" cy="229.27966" r="85.24289" fill="#6c63ff"/><g><path d="M337.72504,284.89374c5.17474-18.66635,10.34946-37.3327,15.52423-55.99905,1.10168-3.97395,1.95407-8.3876,4.47568-11.76016,1.94949-2.60733,5.01575-4.31322,8.26102-3.24098,7.7373,2.55643,7.61206,13.72102,7.47461,20.23466-.20746,9.83305-2.42706,19.64349-6.51288,28.59372-.56033,1.22742-.35031,2.69101,.89688,3.42047,1.07474,.6286,2.85709,.33725,3.42047-.89688,4.09116-8.96194,6.52292-18.55484,7.08868-28.39792,.48813-8.49306,.52472-19.69337-6.83652-25.48187-3.59787-2.82918-8.19009-3.66963-12.40845-1.71413-4.16846,1.93239-6.71384,5.93346-8.31454,10.0761-1.77991,4.60645-2.83997,9.54617-4.15762,14.29919l-4.24594,15.31598c-3.16235,11.40723-6.32468,22.81442-9.487,34.22165-.86093,3.10547,3.96158,4.43073,4.82141,1.32919h0v.00003h-.00003Z" fill="#fff"/><path d="M359.89587,258.89703c3.20197-12.01877,4.83801-24.44736,4.85159-36.88538,.00351-3.21741-4.99649-3.22243-5,0-.01312,12.01666-1.57947,23.94449-4.67297,35.55618-.82922,3.11255,3.99252,4.44043,4.82141,1.32919h-.00003Z" fill="#fff"/><path d="M308.49368,258.7525c3.35089-16.15695,6.97797-32.36552,11.62894-48.20441,3.77136-12.84329,10.27396-27.39745,23.99814-32.05405,6.81589-2.31264,14.20358-1.94012,21.17993-.59821,6.91779,1.33066,13.92474,3.31119,20.30063,6.34035,6.03555,2.86748,11.61917,6.81976,15.59235,12.26434,3.92212,5.37459,6.36456,11.61198,7.68094,18.10706,3.05499,15.07307-.54111,30.47136-4.56973,44.9991-.53616,1.93353-1.08441,3.86365-1.63303,5.79367-.88138,3.10052,3.94162,4.4241,4.82141,1.32919,4.45242-15.66275,9.07721-32.02472,7.00284-48.46307-.89713-7.10921-2.89136-14.09305-6.4451-20.35001-3.6416-6.41167-8.896-11.65268-15.19507-15.46211-6.35269-3.84186-13.5043-6.28763-20.66531-8.12315-7.60632-1.94968-15.52185-3.14977-23.35599-2.06024-7.3873,1.02737-14.04276,4.52979-19.2739,9.81796-5.35913,5.41759-8.98306,12.18707-11.65723,19.26202-2.94922,7.80266-4.87515,15.99947-6.90399,24.07716-2.14438,8.53775-4.14493,17.11163-6.0004,25.71681-.45087,2.09097-.89249,4.18393-1.32687,6.27838-.27393,1.32083,.38547,2.70145,1.74609,3.07529,1.23889,.34042,2.79984-.41788,3.07529-1.74609h.00006Z" fill="#fff"/><path d="M334.26349,207.06648c3.89905-11.83141,16.45471-19.15616,28.61121-18.34444,13.4747,.89973,25.15411,10.74054,29.88474,23.12387,2.811,7.35831,3.6362,15.45682,2.45441,23.24283-.20236,1.33325,.33603,2.68785,1.74609,3.0753,1.18198,.32478,2.87146-.40312,3.07529-1.74609,2.36209-15.56232-1.97873-32.51962-14.22617-43.04318-5.7431-4.93472-12.77701-8.35027-20.30704-9.37296-7.24118-.98344-14.5412,.35677-20.95197,3.8819-7.03223,3.86688-12.58749,10.20531-15.108,17.85359-1.00946,3.06313,3.81729,4.37608,4.82141,1.32919h0l.00003-.00002Z" fill="#fff"/><path d="M323.62473,229.9975c-1.07385,12.82616-4.30664,25.50906-9.53668,37.27271-.5481,1.23282-.35834,2.68628,.89688,3.42047,1.06537,.62314,2.8692,.34311,3.42047-.89688,5.61353-12.62622,9.06622-26.02362,10.2193-39.7963,.11279-1.34721-1.22977-2.5-2.5-2.5-1.44635,0-2.3869,1.14893-2.5,2.5h.00003Z" fill="#fff"/><path d="M384.02057,244.31487c-1.07385,12.82616-4.30664,25.50905-9.53668,37.27272-.5481,1.23282-.35834,2.68628,.89688,3.42047,1.06537,.62314,2.8692,.34311,3.42047-.89688,5.61353-12.62622,9.06622-26.02362,10.2193-39.7963,.11279-1.34721-1.22977-2.5-2.5-2.5-1.44635,0-2.3869,1.14893-2.5,2.5h0l.00003-.00002Z" fill="#fff"/><path d="M336.20508,234.36423c3.21506-12.74895,8.54202-24.83105,15.76917-35.81441,1.77386-2.6958-2.55405-5.20335-4.31735-2.52361-7.44406,11.313-12.96176,23.87781-16.27319,37.0088-.78705,3.12094,4.03378,4.45233,4.82141,1.32919h0v.00002h-.00003Z" fill="#fff"/></g></g><path d="M0,624.38336c0,.66003,.53003,1.19,1.19006,1.19H730.48004c.65997,0,1.19-.52997,1.19-1.19,0-.65997-.53003-1.19-1.19-1.19H1.19006c-.66003,0-1.19006,.53003-1.19006,1.19Z" fill="#3f3d58"/><path id="uuid-ed8d5917-2465-4251-8a73-24d647765b28-620" d="M287.3429,211.89523c10.76318-1.13242,20.03201,3.71107,20.70233,10.81741,.67032,7.10631-7.51099,13.78305-18.27817,14.91438-4.29523,.51312-8.64301-.04831-12.67953-1.63736l-45.66046,4.20064-1.37079-22.27231,45.15866-1.77646c3.66113-2.39919,7.81982-3.85522,12.12796-4.24631,0,0,.00003,0,0,0Z" fill="#fdadb0"/><path d="M231.71271,114.05334h-.00005c-11.05269-1.55672-21.42206,5.71055-23.71935,16.63335-8.01482,38.10753-22.39742,119.28123,.19211,120.63661,29.53613,1.77217,57.89081-5.3165,57.89081-5.3165l-7.08868-40.75986-23.03818-2.36288,13.55157-63.38637c2.5731-12.03547-5.60107-23.72783-17.78825-25.44434l.00002-.00002Z" fill="#3f3d58"/></svg>
\ No newline at end of file
<svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="951.23547" height="632.16225" viewBox="0 0 951.23547 632.16225" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M465.59076,496.88433c32.59906-57.34523,94.78224-101.37694,160.60838-97.13517a303.91886,303.91886,0,0,0-79.93135,192.74415c-1.08086,27.64353.5953,58.50234-17.75918,79.20149-11.42033,12.87974-28.87664,19.11743-46.04,20.426-17.16419,1.30818-34.32439-1.79287-51.25919-4.88078l-4.108,1.261C425.53748,622.55617,432.9917,554.22955,465.59076,496.88433Z" transform="translate(-124.38226 -133.06928)" fill="#f0f0f0"/><path d="M626.29714,401.1298C577.6195,424.56328,536.113,463.69962,510.63332,511.42944c-5.50863,10.31908-10.19864,21.26636-12.24449,32.84118-2.04677,11.58-.61712,22.60314,3.3381,33.60164,3.61588,10.05484,8.47891,19.92112,9.58764,30.67984,1.16866,11.34025-3.00384,21.94364-10.51467,30.359-9.18971,10.29644-21.531,16.67682-33.81667,22.49689-13.64084,6.46206-27.9118,12.958-37.57338,25.01857-1.17064,1.46131-3.36964-.44057-2.20077-1.89967,16.8095-20.9833,45.58314-24.92774,65.53614-41.8308,9.31043-7.88728,16.30035-18.62816,15.85922-31.21353-.38575-11.00537-5.39185-21.18385-9.141-31.33295-3.93666-10.65673-5.89983-21.37183-4.48809-32.73356,1.44413-11.62241,5.716-22.77612,10.93669-33.19077,11.77384-23.48755,27.88681-45.05091,46.345-63.69115a264.37529,264.37529,0,0,1,73.0986-52.15542c1.68149-.80947,2.612,1.94689.9415,2.75108Z" transform="translate(-124.38226 -133.06928)" fill="#fff"/><path d="M518.09691,495.47812a38.97361,38.97361,0,0,1-11.76083-49.07724c.85125-1.66563,3.47954-.42109,2.62716,1.24676a36.0887,36.0887,0,0,0,11.03334,45.62971c1.51533,1.097-.393,3.29149-1.89967,2.20077Z" transform="translate(-124.38226 -133.06928)" fill="#fff"/><path d="M499.22208,573.01552A75.11847,75.11847,0,0,0,546.7827,545.9063c1.17577-1.45711,3.37512.44432,2.20077,1.89967A78.13447,78.13447,0,0,1,499.435,575.915c-1.85547.26565-2.05831-2.63524-.21291-2.89944Z" transform="translate(-124.38226 -133.06928)" fill="#fff"/><path d="M574.90706,432.68514a22.06094,22.06094,0,0,0,19.71762,7.02965c1.85119-.289,2.05205,2.6123.21291,2.89945a24.7211,24.7211,0,0,1-21.8302-7.72833,1.50247,1.50247,0,0,1-.15055-2.05022,1.461,1.461,0,0,1,2.05022-.15055Z" transform="translate(-124.38226 -133.06928)" fill="#fff"/><path d="M757.17329,580.65231c-1.15078.21336-2.30157.42671-3.46287.66229a290.53033,290.53033,0,0,0-45.42472,12.55654c-1.14909.4-2.30759.82272-3.44279,1.25493a306.28393,306.28393,0,0,0-96.32923,58.62179,297.4401,297.4401,0,0,0-31.20006,32.695c-13.1961,16.12271-26.22121,34.65379-43.46521,45.16611a51.02756,51.02756,0,0,1-5.552,3.00981l-99.33786-41.204c-.17876-.20694-.368-.39178-.54786-.59918l-4.04148-1.46379c.45079-.63649.932-1.28694,1.38279-1.92343.26-.3703.542-.73142.802-1.10173.18032-.244.36179-.48759.51056-.718.05971-.08143.12054-.16239.1709-.22127.14877-.23046.31142-.42872.45078-.63649q4.01975-5.46492,8.13029-10.89234c.00941-.02268.00941-.02268.041-.03619,20.95061-27.51625,44.38244-53.52519,71.017-75.1508.80155-.65037,1.61141-1.32388,2.45834-1.95543a283.82353,283.82353,0,0,1,38.36428-25.95136,250.912,250.912,0,0,1,22.75777-11.25342A208.65167,208.65167,0,0,1,633.669,545.38918c43.43148-4.033,87.66932,5.869,120.97979,33.15354C755.50038,579.24131,756.33106,579.931,757.17329,580.65231Z" transform="translate(-124.38226 -133.06928)" fill="#f0f0f0"/><path d="M756.427,581.82048c-52.975-10.597-109.67838-4.3386-158.75909,18.43049-10.61113,4.92262-20.94686,10.83971-29.5492,18.84981-8.60619,8.01369-14.10139,17.67579-17.56522,28.83879-3.16664,10.20524-5.224,21.0108-10.81619,30.26856-5.89451,9.75817-15.61,15.71225-26.6736,17.90941-13.53663,2.6883-27.23193.35234-40.5454-2.39747-14.78206-3.05312-30.08763-6.45857-45.06315-2.64583-1.81449.462-2.42521-2.38053-.61346-2.8418,26.05484-6.63351,51.40382,7.5408,77.512,6.05773,12.18255-.692,24.23036-5.0596,31.45541-15.37391,6.318-9.01942,8.449-20.16039,11.566-30.52112,3.27289-10.87894,8.15663-20.61632,16.12437-28.838,8.15056-8.41037,18.27673-14.744,28.71548-19.91633,23.54187-11.66483,49.38981-19.18084,75.35035-22.95093a264.37547,264.37547,0,0,1,89.76631,2.36722c1.82993.36606.91338,3.1271-.9046,2.76343Z" transform="translate(-124.38226 -133.06928)" fill="#fff"/><path d="M613.231,592.00833a38.97358,38.97358,0,0,1,20.15752-46.26626c1.68249-.81741,3.03174,1.75871,1.347,2.5772a36.0887,36.0887,0,0,0-18.66273,43.0756c.54944,1.78822-2.2955,2.39145-2.84179.61346Z" transform="translate(-124.38226 -133.06928)" fill="#fff"/><path d="M551.4776,642.55365a75.11849,75.11849,0,0,0,54.29611,6.98958c1.81607-.45552,2.42734,2.38682.61346,2.8418a78.13454,78.13454,0,0,1-56.48524-7.38815c-1.64143-.905-.05685-3.34334,1.57567-2.44323Z" transform="translate(-124.38226 -133.06928)" fill="#fff"/><path d="M696.3964,576.07528a22.06092,22.06092,0,0,0,11.51107,17.48415c1.65209.88377.06567,3.32125-1.57567,2.44324a24.7211,24.7211,0,0,1-12.7772-19.31393,1.50248,1.50248,0,0,1,1.11417-1.72763,1.461,1.461,0,0,1,1.72763,1.11417Z" transform="translate(-124.38226 -133.06928)" fill="#fff"/><path d="M567.94141,648.63076c-13.912-67.2669-31.302-89.69385-31.302-89.69385l-6.64343-5.15185-7.98926-6.20581.03858-.79785-1.8949-.64411-.44513-.34576-.72943-.56006-.11731.126-.24768.25647-36.15234-12.2887-45.86536-15.57934L415.35455,490.14a36.7343,36.7343,0,0,0-29.38672-14.33386l-67.82916.50189a36.73449,36.73449,0,0,0-24.70972,9.80127l-44.58306,41.35412-69.469,33.17786-.11725-.11725-.72949.52106-10.73358,5.13232.44293,2.30561-6.64343,4.79376s-17.39,20.868-31.30206,83.459c-3.53907,15.926-5.28113,50.08979-5.90992,92.1883a16.06908,16.06908,0,0,0,16.06244,16.30737H511.49408v-.00006H557.8056a16.0717,16.0717,0,0,0,16.06262-16.29071C573.25409,703.131,571.51269,665.902,567.94141,648.63076Z" transform="translate(-124.38226 -133.06928)" fill="#3f3d56"/><path d="M615.54847,191.73153a54.43073,54.43073,0,1,0,0,108.86146H1021.187a54.43073,54.43073,0,0,0,0-108.86146Z" transform="translate(-124.38226 -133.06928)" fill="#e5e5e5"/><path d="M615.54847,202.74727a43.415,43.415,0,1,0,0,86.83H1021.187a43.415,43.415,0,0,0,0-86.83Z" transform="translate(-124.38226 -133.06928)" fill="#fff"/><circle id="e096411a-cdc3-4e6d-bbd4-4630e1fee17e" data-name="ab6171fa-7d69-4734-b81c-8dff60f9761b" cx="238.3229" cy="228.39206" r="88.86282" fill="#9e616a"/><path d="M339.97228,445.973q-.56945-1.25376-1.13574-2.51618c.14551.00466.28954.02559.435.0294Z" transform="translate(-124.38226 -133.06928)" fill="#2f2e41"/><path d="M271.37112,276.63954c4.49445-3.5853,9.74736-6.88419,15.49373-6.69877,5.74613.18519,11.57324,5.37507,10.38275,10.99974a91.31784,91.31784,0,0,1,109.89524-41.20778c14.28183,5.03874,28.28737,15.1192,31.56809,29.90415.8422,3.79533,1.023,7.95689,3.39274,11.03885,2.98786,3.88573,8.70455,4.76475,13.41179,3.3978q.07062-.0205.141-.04154a4.1986,4.1986,0,0,1,5.07324,5.92695l-4.041,7.5365a32.38317,32.38317,0,0,0,15.428-.3281,4.195,4.195,0,0,1,4.45469,6.52819c-13.32473,18.29415-35.58607,30.10755-58.30327,29.96873-16.14591-.09846-32.45814-5.66309-48.17179-1.95012a41.84383,41.84383,0,0,0-28.14382,58.74019c-4.82733-5.28005-14.159-4.03-19.097,1.147-4.93774,5.177-6.21612,12.90385-5.71853,20.04085.76077,10.91577,5.03759,21.20144,9.5463,31.21221-37.80123-1.19-73.555-27.707-85.58977-63.57189C229.00827,343.26738,241.674,300.32986,271.37112,276.63954Z" transform="translate(-124.38226 -133.06928)" fill="#2f2e41"/><polygon points="87.464 495.253 112.388 630.86 127.343 632.162 87.464 495.253" opacity="0.2"/><polygon points="362.007 485.026 337.083 630.762 322.128 632.162 362.007 485.026" opacity="0.2"/><path d="M292.62933,231.00135c-4.77882,1.99547-9.76532-.19144-11.85656-5.19961-2.12322-5.08476-.14017-10.24648,4.71525-12.27393,4.85588-2.02764,9.75359.1646,11.911,5.33137C299.52417,223.94845,297.5627,228.94135,292.62933,231.00135Zm-9.15419-27.482-3.79972,1.58663a4.09911,4.09911,0,0,1-5.20612-1.90948l-.1879-.36761c-4.08846-7.37337-4.5566-16.33467-1.384-26.62094,2.939-9.22731,4.1597-15.71683,1.70477-21.596-2.83836-6.79741-8.8993-8.92671-16.62838-5.84218-2.99769,1.25173-3.95159,1.23179-6.31064,3.572a5.4161,5.4161,0,0,1-3.92122,1.59344,5.2354,5.2354,0,0,1-3.74713-1.643,5.34757,5.34757,0,0,1-.03684-7.29733,41.53525,41.53525,0,0,1,14.04574-9.64413c16.60647-6.93429,24.96626,3.3032,28.79182,12.46479,3.74183,8.96108,1.637,17.27546-1.745,28.04341-2.83416,8.94752-2.66908,15.57751.55033,22.16977a4.08088,4.08088,0,0,1-2.12565,5.49059Z" transform="translate(-124.38226 -133.06928)" fill="#6c63ff"/><path d="M705.14883,272.122h-80.707a1.944,1.944,0,1,1,0-3.88791h80.707a1.944,1.944,0,0,1,0,3.88791Z" transform="translate(-124.38226 -133.06928)" fill="#6c63ff"/><path d="M807.53044,272.76994h-80.707a1.944,1.944,0,1,1,0-3.88791h80.707a1.944,1.944,0,1,1,0,3.88791Z" transform="translate(-124.38226 -133.06928)" fill="#6c63ff"/><path d="M909.91205,273.41793H829.205a1.944,1.944,0,0,1,0-3.88791h80.707a1.944,1.944,0,1,1,0,3.88791Z" transform="translate(-124.38226 -133.06928)" fill="#6c63ff"/><path d="M1012.29367,274.06591h-80.707a1.944,1.944,0,0,1,0-3.88791h80.707a1.944,1.944,0,0,1,0,3.88791Z" transform="translate(-124.38226 -133.06928)" fill="#6c63ff"/><circle cx="540.23547" cy="106.16225" r="15" fill="#6c63ff"/><circle cx="643.23547" cy="106.16225" r="15" fill="#6c63ff"/><circle cx="746.23547" cy="106.16225" r="15" fill="#6c63ff"/><circle cx="849.23547" cy="106.16225" r="15" fill="#6c63ff"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="550.59998" height="412.44495" viewBox="0 0 550.59998 412.44495"><path d="m550.59998,411.25495c0,.65997-.53003,1.19-1.19,1.19H1.19c-.66,0-1.19-.53003-1.19-1.19s.53-1.19,1.19-1.19h548.21997c.65997,0,1.19.53003,1.19,1.19Z" fill="#2e2e43" stroke-width="0"/><path d="m436.65881,84.78436H114.07564c-4.45853,0-8.08586-3.62733-8.08586-8.08586v-24.85271c0-4.45853,3.62733-8.08586,8.08586-8.08586h322.58317c4.45853,0,8.08586,3.62733,8.08586,8.08586v24.85271c0,4.45853-3.62733,8.08586-8.08586,8.08586Z" fill="#fff" stroke="#bab7c9" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/><path d="m436.65881,237.99009H114.07564c-4.45853,0-8.08586-3.62733-8.08586-8.08586v-24.85271c0-4.45853,3.62733-8.08586,8.08586-8.08586h322.58317c4.45853,0,8.08586,3.62733,8.08586,8.08586v24.85271c0,4.45853-3.62733,8.08586-8.08586,8.08586Z" fill="#fff" stroke="#bab7c9" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/><path d="m207.65881,347.99009h-94.58317c-4.45853,0-8.08586-3.62733-8.08586-8.08586v-24.85271c0-4.45853,3.62733-8.08586,8.08586-8.08586h94.58317c4.45853,0,8.08586,3.62733,8.08586,8.08586v24.85271c0,4.45853-3.62733,8.08586-8.08586,8.08586Z" fill="#6c63ff" stroke-width="0"/><line x1="106.69815" y1="1" x2="177.44809" y2="1" fill="none" stroke="#bab7c9" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/><line x1="106.69815" y1="154.20573" x2="238.12288" y2="154.20573" fill="none" stroke="#bab7c9" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/><rect x="390.51069" y="369.32254" width="13.20445" height="18.7301" transform="translate(-141.44328 273.52017) rotate(-32.59)" fill="#f1a1a4" stroke-width="0"/><polygon points="362.34782 155.10185 348.29375 159.90111 348.07325 139.60802 360.86264 139.46533 362.34782 155.10185" fill="#f1a1a4" stroke-width="0"/><circle cx="349.71408" cy="131.15741" r="14.05406" fill="#f1a1a4" stroke-width="0"/><path d="m353.55997,129.72413c-2.34774-.0454-3.92371-2.39963-4.86412-4.56578-.9404-2.15319-1.90674-4.64361-4.09234-5.51915-1.79-.71341-4.87708,4.26745-6.3039,2.97036-1.48518-1.35546-.12972-8.43762,1.42032-9.71526s3.67728-1.55003,5.6748-1.67326c4.89654-.27887,9.81904.05837,14.63126,1.01173,2.97035.58369,6.04448,1.48517,8.20414,3.60593,2.74337,2.69147,3.4827,6.79031,3.71619,10.62324.24645,3.92372.05837,8.03552-1.80946,11.49877-1.87432,3.45677-5.83694,6.03151-9.68283,5.20137-.40859-2.08185-.0454-4.21557.08431-6.34281.12972-2.11427-.05837-4.39716-1.36843-6.07042s-4.07289-2.30883-5.55807-.79771" fill="#2f2e43" stroke-width="0"/><path d="m370.90216,134.40016c1.39438-1.04416,3.06115-1.92619,4.79279-1.73162,1.87432.20105,3.46974,1.73162,3.96912,3.54756s-.01946,3.82644-1.15442,5.33107-2.84065,2.5034-4.65658,3.01575c-1.05065.29834-2.19859.42155-3.21033,0-1.48518-.62261-2.30234-2.49692-1.73811-4.00803" fill="#2f2e43" stroke-width="0"/><path id="uuid-31bdf68e-d938-48b7-86ad-7ba8e8b265d3-91-89-41-193" d="m318.60318,267.17111c-.88202,4.62416.87555,8.82674,3.9367,9.37801,3.05466.55127,6.25202-2.75633,7.14053-7.38049.38264-1.84188.29833-3.74861-.24645-5.55807l10.81132-72.48184-14.5664-2.56825-4.79279,73.51952c-1.17387,1.50464-1.95861,3.24924-2.28289,5.11057h0v-.01946h-.00002Z" fill="#f1a1a4" stroke-width="0"/><path d="m348.03434,150.58794l-9.92279.11025c-7.00432,1.13496-8.86567,4.90303-10.37678,11.82954-2.31532,10.56486-5.27271,24.64485-4.6501,24.83943.99228.32427,17.96481,8.08091,26.55809,6.16122l-1.60192-42.94042h-.00649Z" fill="#6c63ff" stroke-width="0"/><rect x="347.12191" y="381.03382" width="13.20445" height="18.7301" transform="translate(-4.33864 3.97541) rotate(-.64)" fill="#f1a1a4" stroke-width="0"/><path d="m334.46021,411.32408c-1.39438.01948-2.62014,0-3.55406-.07782-3.51514-.27887-6.8811-2.83416-8.58678-4.32581-.76528-.66802-1.01823-1.75758-.63559-2.69149h0c.2724-.66802.83014-1.18036,1.53057-1.3944l9.24182-2.74984,14.89717-10.29247.16863.29835c.06486.11024,1.5695,2.74984,2.08184,4.53984.19456.68097.15565,1.2452-.12972,1.68621-.19456.3048-.46696.48641-.68746.59665.2724.27887,1.12847.8496,3.76158,1.23871,3.82644.57073,4.59821-3.41137,4.62416-3.58l.02595-.13621.11026-.07782c1.80946-1.1998,2.91847-1.73811,3.3076-1.62786.24645.06484.64206.18806,1.84837,10.97993.11026.33726.90149,2.81472.40859,5.20138-.53181,2.5942-11.84898,1.82242-14.10594,1.6473-.06486.00649-8.52194.70694-14.31995.76528h.01946-.00649v.00008Z" fill="#2f2e43" stroke-width="0"/><path d="m383.21163,408.21105c-1.55004.01948-2.97684-.15565-3.99506-.32427-.99877-.16863-1.79-.95335-1.95861-1.95214h0c-.12972-.71988.08431-1.43976.55774-1.98456l6.38172-7.22485,7.18593-16.61582.3048.16214c.11024.05839,2.78226,1.50464,4.17017,2.74984.52532.47343.79121.97282.79121,1.50464,0,.36319-.13621.66153-.27238.86258.38266.09081,1.40734.11673,3.84589-.9404,3.54754-1.54355,2.0948-5.33105,2.02996-5.48025l-.0519-.12972.05839-.11673c.90149-1.97157,1.56299-3.02222,1.94565-3.13899.24645-.06484.64206-.18806,7.38049,8.33384.27238.22698,2.25694,1.90674,3.10008,4.18964.91444,2.48395-9.07969,7.81501-11.10316,8.85916-.05839.0519-10.5065,7.81501-14.79989,10.03953-1.70569.88202-3.73565,1.17387-5.584,1.18686l.01946.01948h-.00649v.00004Z" fill="#2f2e43" stroke-width="0"/><path d="m368.17827,224.18528l-36.96729.40859-2.97035,34.42499,16.0905,126.90806,18.87278-.21403-8.35981-73.30549,31.35086,65.925,16.64175-11.93332-24.59297-61.59919s7.94473-53.98521,1.08309-67.33236c-6.85517-13.34713-11.14207-13.30175-11.14207-13.30175v.01946h-.00649v.00004Z" fill="#2f2e43" stroke-width="0"/><polygon points="386.58409 226.07905 327.87095 226.73407 344.64242 150.63335 370.22768 150.34149 386.58409 226.07905" fill="#6c63ff" stroke-width="0"/><path id="uuid-0d1d7be6-7e67-43a2-9b15-a4bbed67d7bc-92-90-42-194" d="m392.31726,266.35395c.98581,4.61117-.68097,8.84622-3.72266,9.46233-3.04819.6226-6.31686-2.61365-7.29618-7.22485-.42155-1.83538-.38264-3.74212.11673-5.56454l-12.4262-72.2289,14.50157-2.89252,6.4271,73.40277c1.20629,1.47869,2.02996,3.21033,2.39964,5.05867h0v-.01296Z" fill="#f1a1a4" stroke-width="0"/><path d="m360.31137,150.45175l9.92279-.11025c7.02378.9858,8.96942,4.70846,10.64269,11.60254,2.54879,10.51297,5.81099,24.51514,5.20136,24.72918-.99228.33724-17.77673,8.47005-26.40892,6.74491l.65504-42.96637h-.01296Z" fill="#6c63ff" stroke-width="0"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="668.6" height="593.48" viewBox="0 0 668.6 593.48"><rect x="58.96" width="558.67" height="426.47" rx="21.76" ry="21.76" fill="#d7d7d8" stroke-width="0"/><path d="M80.72,5c-9.24,0-16.76,7.52-16.76,16.76v382.94c0,9.24,7.52,16.76,16.76,16.76h515.15c9.24,0,16.76-7.52,16.76-16.76V21.76c0-9.24-7.52-16.76-16.76-16.76H80.72Z" fill="#fff" stroke-width="0"/><rect x="336.29" y="2.55" width="3.99" height="421.84" fill="#d7d7d8" stroke-width="0"/><circle cx="314.57" cy="65.58" r="5.65" fill="#d7d7d8" stroke-width="0"/><circle cx="362.01" cy="65.58" r="5.65" fill="#d7d7d8" stroke-width="0"/><circle cx="314.57" cy="139.41" r="5.65" fill="#d7d7d8" stroke-width="0"/><circle cx="362.01" cy="139.41" r="5.65" fill="#d7d7d8" stroke-width="0"/><circle cx="314.57" cy="213.23" r="5.65" fill="#d7d7d8" stroke-width="0"/><circle cx="362.01" cy="213.23" r="5.65" fill="#d7d7d8" stroke-width="0"/><circle cx="314.57" cy="287.06" r="5.65" fill="#d7d7d8" stroke-width="0"/><circle cx="362.01" cy="287.06" r="5.65" fill="#d7d7d8" stroke-width="0"/><circle cx="314.57" cy="360.88" r="5.65" fill="#d7d7d8" stroke-width="0"/><circle cx="362.01" cy="360.88" r="5.65" fill="#d7d7d8" stroke-width="0"/><path d="M315.09,62.97l-1.05-1.7c.26-.16,26.1-15.77,48.54.03l-1.15,1.64c-21.36-15.04-46.1-.12-46.34.03Z" fill="#d7d7d8" stroke-width="0"/><path d="M315.09,69.9l-1.05-1.7c.26-.16,26.1-15.77,48.54.03l-1.15,1.64c-21.36-15.04-46.1-.12-46.34.03Z" fill="#d7d7d8" stroke-width="0"/><path d="M315.09,137.12l-1.05-1.7c.26-.16,26.1-15.77,48.54.03l-1.15,1.64c-21.36-15.04-46.1-.12-46.34.03Z" fill="#d7d7d8" stroke-width="0"/><path d="M315.09,144.06l-1.05-1.7c.26-.16,26.1-15.77,48.54.03l-1.15,1.64c-21.36-15.04-46.1-.12-46.34.03Z" fill="#d7d7d8" stroke-width="0"/><path d="M315.09,211.27l-1.05-1.7c.26-.16,26.1-15.77,48.54.03l-1.15,1.64c-21.36-15.04-46.1-.12-46.34.03Z" fill="#d7d7d8" stroke-width="0"/><path d="M315.09,218.21l-1.05-1.7c.26-.16,26.09-15.77,48.54.03l-1.15,1.64c-21.36-15.04-46.1-.12-46.34.03Z" fill="#d7d7d8" stroke-width="0"/><path d="M315.09,285.42l-1.05-1.7c.26-.16,26.1-15.77,48.54.03l-1.15,1.64c-21.36-15.03-46.1-.12-46.34.03Z" fill="#d7d7d8" stroke-width="0"/><path d="M315.09,292.36l-1.05-1.7c.26-.16,26.09-15.77,48.54.03l-1.15,1.64c-21.36-15.04-46.1-.12-46.34.03Z" fill="#d7d7d8" stroke-width="0"/><path d="M315.09,359.57l-1.05-1.7c.26-.16,26.1-15.77,48.54.03l-1.15,1.63c-21.36-15.04-46.1-.12-46.34.03Z" fill="#d7d7d8" stroke-width="0"/><path d="M315.09,366.51l-1.05-1.7c.26-.16,26.1-15.77,48.54.03l-1.15,1.63c-21.36-15.04-46.1-.12-46.34.03Z" fill="#d7d7d8" stroke-width="0"/><path d="M464.85,111.77s-20.58,2.32-21.91,34.19c-1.11,26.56-3.37,41.36,7.44,46.9,3.86,1.98,8.4,2.15,12.53.8l44.1-14.5s.66-47.8-14.61-59.42c-15.27-11.62-27.55-7.97-27.55-7.97Z" fill="#2f2e43" stroke-width="0"/><polygon points="489.16 185.03 466.84 192.37 466.84 160.24 487.09 160.24 489.16 185.03" fill="#f3a3a6" stroke-width="0"/><path id="uuid-89c22d20-9486-4802-b91b-ddf2a7c7ca0a-46-44-51-53-617" d="M420.93,367.41c-1.21,7.36-6.12,12.64-10.96,11.79-4.85-.85-7.79-7.51-6.58-14.87.44-2.95,1.61-5.74,3.4-8.13l5.53-31.12,15.05,3.15-7.05,30.34c.93,2.87,1.14,5.9.61,8.84,0,0,0,0,0,0Z" fill="#f3a3a6" stroke-width="0"/><polygon points="472.03 574.33 451.13 574.33 439.01 462.64 471.32 462.64 472.03 574.33" fill="#f3a3a6" stroke-width="0"/><path d="M430.77,592.29c-2.2,0-4.16-.05-5.63-.19-5.55-.51-10.85-4.61-13.51-7-1.19-1.07-1.58-2.79-.96-4.27h0c.45-1.06,1.34-1.85,2.45-2.17l14.67-4.19,23.76-16.03.27.48c.1.18,2.43,4.38,3.21,7.22.3,1.08.22,1.98-.23,2.68-.31.48-.75.76-1.1.92.43.45,1.78,1.36,5.93,2.02,6.07.96,7.33-5.32,7.39-5.58l.04-.21.18-.12c2.88-1.86,4.66-2.7,5.27-2.52.38.11,1.02.31,2.74,17.41.17.54,1.38,4.47.56,8.24-.89,4.1-18.78,2.69-22.36,2.36-.1.01-13.49.96-22.67.96Z" fill="#2f2e43" stroke-width="0"/><polygon points="519.26 574.33 498.35 574.33 486.23 462.64 518.54 462.64 519.26 574.33" fill="#f3a3a6" stroke-width="0"/><path d="M478,592.29c-2.2,0-4.16-.05-5.63-.19-5.55-.51-10.85-4.61-13.51-7-1.19-1.07-1.58-2.79-.96-4.27h0c.45-1.06,1.34-1.85,2.45-2.17l14.67-4.19,23.76-16.03.27.48c.1.18,2.43,4.38,3.21,7.22.3,1.08.22,1.98-.23,2.68-.31.48-.75.76-1.1.92.43.45,1.78,1.36,5.93,2.02,6.07.96,7.33-5.32,7.39-5.58l.04-.21.18-.12c2.89-1.86,4.66-2.7,5.27-2.52.38.11,1.02.31,2.74,17.41.17.54,1.38,4.47.56,8.24-.89,4.1-18.78,2.69-22.36,2.36-.1.01-13.49.96-22.67.96Z" fill="#2f2e43" stroke-width="0"/><polygon points="525.27 299.99 423.7 299.99 460.21 179.82 500.71 179.82 525.27 299.99" fill="#6c63ff" stroke-width="0"/><path d="M466.6,179.84s-25.23-.66-27.88,5.98c-2.66,6.64-33.86,164.65-33.86,164.65h20.58l41.16-170.62Z" fill="#6c63ff" stroke-width="0"/><circle cx="469.6" cy="146.89" r="22.24" fill="#f3a3a6" stroke-width="0"/><path d="M463.52,120.07s-12.24,49.7,1.37,72.93l-19.17-4.07s-7.43-54.39,7.51-64.28l10.29-4.58Z" fill="#2f2e43" stroke-width="0"/><path d="M504.16,299.99h-66.66l-36.47,149.69c-.67,6.32,3.34,12.22,9.48,13.87,20.01,5.36,68.03,12.95,140.7-8.2,6.99-2.03,10.96-9.41,8.77-16.36l-55.82-139Z" fill="#2f2e43" stroke-width="0"/><path d="M668.6,592.29c0,.66-.53,1.19-1.19,1.19H1.19c-.66,0-1.19-.53-1.19-1.19s.53-1.19,1.19-1.19h666.22c.66,0,1.19.53,1.19,1.19Z" fill="#2f2e43" stroke-width="0"/><path d="M477.21,179.82l20.73-.91c8.98.68,17.1,5.56,21.91,13.17,14.65,23.16,42.06,71.97,17.59,78.66-32.26,8.81-47.89-40.24-47.89-40.24l-12.34-50.68Z" fill="#6c63ff" stroke-width="0"/><path d="M458.1,197.46l50.76-36.96c.6-.44,1.44-.3,1.88.3l1.23,1.69c.44.6.3,1.44-.3,1.88l-50.75,36.96h-.01s-6.73,2.9-6.73,2.9l-.51-.7,4.43-6.07Z" fill="#2f2e43" stroke-width="0"/><path id="uuid-98bb229b-1f5d-4c6c-926b-55ef96e77de9-47-45-52-54-618" d="M470.1,194.37c-4.26-6.12-4.41-13.33-.35-16.1,4.07-2.77,10.82-.04,15.08,6.08,1.74,2.42,2.84,5.24,3.22,8.2l17.71,26.18-12.99,8.23-16.08-26.68c-2.67-1.41-4.93-3.44-6.59-5.91,0,0,0,0,0,0Z" fill="#f3a3a6" stroke-width="0"/><polygon points="480.58 215.54 495.21 202.07 524.14 229.01 497.24 247.4 480.58 215.54" fill="#6c63ff" stroke-width="0"/><path d="M110.83,75.9c20.55-.79,41.12-1.13,61.69-1.01s40.8.69,61.17,1.72c11.6.58,23.18,1.31,34.76,2.19,1.93.15,1.92-2.86,0-3-20.51-1.55-41.05-2.64-61.61-3.28s-40.8-.8-61.2-.53c-11.61.16-23.22.46-34.82.91-1.92.07-1.93,3.07,0,3h0Z" fill="#6c63ff" stroke-width="0"/><path d="M110.83,109.84c20.55-.79,41.12-1.13,61.69-1.01s40.8.69,61.17,1.72c11.6.58,23.18,1.31,34.76,2.19,1.93.15,1.92-2.86,0-3-20.51-1.55-41.05-2.64-61.61-3.28s-40.8-.8-61.2-.53c-11.61.16-23.22.46-34.82.91-1.92.07-1.93,3.07,0,3h0Z" fill="#2f2e43" stroke-width="0"/><path d="M110.83,143.78c16.68-.65,33.37-1.39,50.07-1.68,14.28-.25,28.56-.02,42.82.67,10.17.49,20.33,1.18,30.49,1.94,1.93.15,1.92-2.86,0-3-16.64-1.26-33.3-2.29-49.99-2.61-14.28-.27-28.57.04-42.84.52-10.18.35-20.36.76-30.55,1.16-1.92.07-1.93,3.07,0,3h0Z" fill="#2f2e43" stroke-width="0"/><path d="M110.83,177.72c17.66-.68,35.33-1.4,53-1.66,15.82-.24,31.65-.03,47.46.69,10.53.48,21.05,1.15,31.57,1.95,1.93.15,1.92-2.86,0-3-17.62-1.33-35.26-2.32-52.92-2.62-15.83-.28-31.66,0-47.48.5-10.54.33-21.08.74-31.62,1.15-1.92.07-1.93,3.07,0,3h0Z" fill="#2f2e43" stroke-width="0"/><path d="M110.83,211.65c16.06-.62,32.1-1.6,48.15-2.35,13.26-.62,26.52-.83,39.79-.39,9.94.33,19.87.95,29.78,1.7,1.93.15,1.92-2.86,0-3-16-1.21-32.02-2.06-48.07-1.94-13.29.1-26.55.87-39.81,1.58-9.94.53-19.89,1.01-29.84,1.4-1.92.07-1.93,3.08,0,3h0Z" fill="#2f2e43" stroke-width="0"/><path d="M110.83,245.59c20.55-.79,41.12-1.13,61.69-1.01s40.8.69,61.17,1.72c11.6.58,23.18,1.31,34.76,2.19,1.93.15,1.92-2.86,0-3-20.51-1.55-41.05-2.64-61.61-3.28s-40.8-.8-61.2-.53c-11.61.16-23.22.46-34.82.91-1.92.07-1.93,3.07,0,3h0Z" fill="#2f2e43" stroke-width="0"/></svg>
\ No newline at end of file
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
</dict>
</plist>
#include "Generated.xcconfig"
#include "Generated.xcconfig"
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C8080294A63A400263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
import Flutter
import UIKit
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Library App</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>library_app</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
#import "GeneratedPluginRegistrant.h"
import Flutter
import UIKit
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import 'package:library_app/src/providers/book_provider.dart';
import 'package:library_app/src/screens/form_screen.dart';
import 'package:provider/provider.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:library_app/src/providers/auth_provider.dart';
import 'package:library_app/src/providers/navigations_provider.dart';
import 'package:library_app/src/screens/list_screen.dart';
void main() {
runApp(const LibraryApp());
}
class LibraryApp extends StatelessWidget {
const LibraryApp({super.key});
@override
Widget build(BuildContext context) {
const title = 'Library App';
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => AuthProvider()),
ChangeNotifierProvider(create: (context) => NavigationsProvider()),
ChangeNotifierProvider(create: (context) => BookProvider()),
],
child: MaterialApp(
title: title,
theme: ThemeData(
textTheme: GoogleFonts.poppinsTextTheme(),
colorScheme: ColorScheme.fromSeed(
seedColor: const Color.fromRGBO(108, 99, 255, 1.000),
),
useMaterial3: true,
),
home: Consumer<AuthProvider>(
builder: (context, authProvider, child) {
return authProvider.isLoggedIn
? const ListScreen()
: const LoginScreen();
},
),
scrollBehavior: AdaptiveScrollBehavior(),
),
);
}
}
class AdaptiveScrollBehavior extends MaterialScrollBehavior {
@override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
};
}
class Book {
String title;
String author;
String description;
String? coverUrl;
String? category;
Book(this.title, this.author, this.description, this.coverUrl, this.category);
factory Book.fromJson(Map<String, dynamic> data) {
return Book(
data['title'] as String,
data['author'] as String,
data['description'] as String,
data['coverUrl'] as String?,
data['category'] as String?,
);
}
}
final initialBooks = [
Book(
'The Doe in the Forest',
'Laurel Toven',
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed id mauris ligula. Mauris nec elit ultrices, gravida tortor ac, faucibus velit.',
'https://dummyjson.com/image/260x400',
'Children',
),
Book(
'Norse Mythology',
'Neil Gaiman',
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed id mauris ligula. Mauris nec elit ultrices, gravida tortor ac, faucibus velit.',
'https://dummyjson.com/image/260x400',
'Religion',
),
Book(
'The Sun, the Moon, the Stars',
'Junot Diaz',
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed id mauris ligula. Mauris nec elit ultrices, gravida tortor ac, faucibus velit.',
'https://dummyjson.com/image/260x400',
'Drama',
),
Book(
'Harry Potter',
'JK Rowling',
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed id mauris ligula. Mauris nec elit ultrices, gravida tortor ac, faucibus velit.',
'https://dummyjson.com/image/260x400',
'Fantasy',
),
];
class Category {
String name;
Category(this.name);
}
final initialCategories = [
Category('Children'),
Category('Religion'),
Category('Fantasy'),
Category('Horror'),
Category('Romance'),
Category('Mistery'),
Category('Adventure'),
Category('Science Fiction'),
];
import 'package:library_app/src/models/book.dart';
class Loan {
Book book;
String loanDate;
String dueDate;
String remainingDays;
bool isOverdue;
Loan(
this.book,
this.loanDate,
this.dueDate,
this.remainingDays,
this.isOverdue,
);
}
class Token {
String key;
Token(this.key);
static Token? fromJson(data) {
return Token(data['token']);
}
}
class User {
int id;
String username;
String email;
String? firstName;
String? lastName;
bool isStaff;
User(this.id, this.username, this.email, this.firstName, this.lastName,
this.isStaff);
factory User.fromJson(Map<String, dynamic> data) {
return User(
data['id'] as int,
data['username'] as String,
data['email'] as String,
data['first_name'] as String?,
data['last_name'] as String?,
data['is_staff'] as bool,
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['email'] = email;
data['first_name'] = firstName;
data['last_name'] = lastName;
data['is_staff'] = isStaff;
return data;
}
}
final User initialUser = User(
1,
"test_user",
"test@email.com",
"Test",
"User",
false,
);
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'package:library_app/src/models/token.dart';
import 'package:library_app/src/models/user.dart';
class AuthProvider with ChangeNotifier {
String baseUrl = 'http://localhost:8000/api/v1';
Token? token;
User? user;
bool get isLoggedIn => token != null;
bool invalidUsernameOrPassword = false;
List<dynamic>? memberLoans;
Future<void> signIn(String username, String password) async {
try {
final response = await http.post(
Uri.parse('$baseUrl/members/auth/login'),
body: jsonEncode({'username': username, 'password': password}),
headers: {'Content-Type': 'application/json'},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
token = Token.fromJson(data);
debugPrint("Login successful $token");
} else if (response.statusCode == 401) {
invalidUsernameOrPassword = true;
debugPrint("Login failed: ${response.statusCode} ${response.body}");
} else {
final code = response.statusCode;
debugPrint("Login failed $code");
}
notifyListeners();
} catch (error) {
debugPrint("Login failed $error");
}
}
Future<void> signOut() async {
try {
final response = await http.get(
Uri.parse('$baseUrl/auth/logout'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ${token?.key}'
},
);
if (response.statusCode == 200) {
token = null;
} else {
debugPrint("Logout failed: ${response.statusCode} ${response.body}");
}
notifyListeners();
} catch (error) {
debugPrint("Logout failed $error");
}
}
Future<void> signUp(String username, String email, String password) async {
try {
final body = {
"username": username,
"email": email,
"password": password,
};
final response = await http.post(
Uri.parse('$baseUrl/members/auth/register'),
body: jsonEncode(body),
headers: {'Content-Type': 'application/json'},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
token = Token.fromJson(data);
debugPrint(response.body);
} else {
debugPrint(
"Error: sign up failed, ${response.statusCode}: ${response.body}");
}
notifyListeners();
} catch (error) {
debugPrint("Error: sign up failed, $error");
}
}
Future<void> getUserDetail() async {
if (token != null) {
try {
final response = await http.get(
Uri.parse('$baseUrl/user'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ${token?.key}'
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
user = User.fromJson(data);
} else {
debugPrint('Error fetching user details: ${response.statusCode}');
}
notifyListeners();
} catch (error) {
debugPrint('Error user details: $error');
}
}
}
Future<void> updateUserDetail(
int id,
String username,
String email,
String? firstName,
String? lastName,
bool isStaff,
) async {
if (token != null) {
try {
final body = jsonEncode({
"username": username,
"email": email,
"first_name": firstName,
"last_name": lastName,
});
final response = await http.put(
Uri.parse('$baseUrl/user/$id/'),
body: body,
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ${token?.key}'
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
user = User.fromJson(data);
} else {
debugPrint(
'Error update user details: ${response.statusCode}, ${response.body}');
}
notifyListeners();
} catch (error) {
debugPrint("Error update user details: $error");
}
}
}
Future<void> getMemberLoan(int id) async {
try {
final response = await http.get(
Uri.parse('$baseUrl/members/2/loans/'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ${token?.key}'
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
memberLoans = data["results"];
} else {
debugPrint(
"Failed to get member loan. ${response.statusCode}: ${response.body}");
}
notifyListeners();
} catch (error) {
debugPrint("Failed to get member loan. $error");
}
}
Future<void> createMemberLoan(int memberId, int bookId, int loanDay) async {
final loanDate = DateTime.now();
final dueDay = loanDate.day + loanDay;
final dueDate = loanDate.add(Duration(days: dueDay));
final body = {
"book": bookId,
"member": memberId,
"loan_date": loanDate,
"due_date": dueDate,
};
try {
final response = await http.post(
Uri.parse('$baseUrl/members/$memberId/loans/'),
body: jsonEncode(body),
headers: {'Content-Type': 'application/json'},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
memberLoans = data["results"];
} else {
debugPrint(
"Failed to get member loan. ${response.statusCode}: ${response.body}");
}
notifyListeners();
} catch (error) {
debugPrint("Failed to get member loan. $error");
}
}
}
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
class BookProvider with ChangeNotifier {
String baseUrl = 'http://localhost:8000/api/v1';
List<dynamic>? books;
BookProvider({this.books});
Future<void> getBooks() async {
try {
final response = await http.get(
Uri.parse('$baseUrl/books'),
headers: {'Content-Type': 'application/json'},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
books = data["results"];
} else {
final code = response.statusCode;
debugPrint("Error: Fetch books failed, $code");
}
notifyListeners();
} catch (error) {
debugPrint("Error: Fetch books failed, $error");
}
}
Future<void> searchBook(String? keyword) async {
try {
final response = await http.get(
Uri.parse('$baseUrl/books?search=$keyword'),
headers: {'Content-Type': 'application/json'},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
books = data["results"];
} else {
final code = response.statusCode;
debugPrint("Error: Fetch books failed, $code");
}
notifyListeners();
} catch (error) {
debugPrint("Error: Fetch books failed, $error");
}
}
}
import 'package:flutter/foundation.dart';
class NavigationsProvider with ChangeNotifier {
int currentPageIndex = 0;
void navigate(int page) {
currentPageIndex = page;
notifyListeners();
}
}
import 'package:flutter/material.dart';
import 'package:library_app/src/widgets/forms/book_loan_form.dart';
class DetailScreen extends StatefulWidget {
final String? textSubmitButton;
final String title;
final String confirmMessage;
final Widget body;
const DetailScreen({
super.key,
required this.title,
required this.body,
required this.confirmMessage,
this.textSubmitButton,
});
@override
_DetailScreen createState() => _DetailScreen();
}
class _DetailScreen extends State<DetailScreen> {
@override
Widget build(BuildContext context) {
final String title = widget.title;
final Widget body = widget.body;
return Scaffold(
appBar: AppBar(
title: Text(
title,
style: const TextStyle(fontSize: 18.0),
),
leading: const BackButton(),
),
body: ListView(
children: [
Container(
padding:
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 40.0),
child: body,
)
],
),
bottomNavigationBar: const LoanBookForm(),
);
}
}
import 'package:flutter/material.dart';
import 'package:library_app/src/providers/auth_provider.dart';
import 'package:library_app/src/widgets/forms/login_form.dart';
import 'package:library_app/src/widgets/forms/profile_edit_form.dart';
import 'package:library_app/src/widgets/forms/reset_password_form.dart';
import 'package:library_app/src/widgets/forms/sign_up_form.dart';
import 'package:provider/provider.dart';
class FormScreen extends StatelessWidget {
final String title;
final Widget body;
const FormScreen({super.key, required this.title, required this.body});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
leading: const BackButton(),
),
body: ListView(
children: [
Container(
width: double.infinity,
padding:
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 40.0),
child: body,
),
],
),
);
}
}
class LoginScreen extends StatelessWidget {
const LoginScreen({super.key});
@override
Widget build(BuildContext context) {
String title = "Login";
return FormScreen(
title: title,
body: const LoginForm(),
);
}
}
class SignUpScreen extends StatelessWidget {
const SignUpScreen({super.key});
@override
Widget build(BuildContext context) {
String title = "Sign Up";
return FormScreen(
title: title,
body: const SignUpForm(),
);
}
}
class ResetPasswordScreen extends StatelessWidget {
const ResetPasswordScreen({super.key});
@override
Widget build(BuildContext context) {
String title = "Reset Password";
return FormScreen(
title: title,
body: const ResetPasswordForm(),
);
}
}
class ProfileEditScreen extends StatelessWidget {
const ProfileEditScreen({
super.key,
});
@override
Widget build(BuildContext context) {
String title = "Edit Profile";
return Consumer<AuthProvider>(builder: (context, authProvider, child) {
return FormScreen(
title: title,
body: ProfileEditForm(user: authProvider.user),
);
});
}
}
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:library_app/src/screens/form_screen.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
final screenSize = MediaQuery.of(context).size;
return Scaffold(
body: ListView(
children: [
Container(
height: screenSize.height,
padding: const EdgeInsets.symmetric(horizontal: 40.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const ListTile(
title: Text("Library App",
textAlign: TextAlign.center,
style:
TextStyle(fontSize: 30.0, fontWeight: FontWeight.bold)),
subtitle: Text(
"Discover many amazing book and manage loans very easy.",
textAlign: TextAlign.center),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 30.0),
child: SvgPicture.asset(
"assets/images/splash_image.svg",
semanticsLabel: 'Home Image',
width: 200,
),
),
SizedBox(
width: double.infinity,
child: FilledButton(
child: const Text("Login"),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const LoginScreen(),
),
);
},
),
),
const SizedBox(height: 10.0),
SizedBox(
width: double.infinity,
child: ElevatedButton(
child: const Text("Sign Up"),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const SignUpScreen(),
),
);
},
),
),
],
),
),
],
));
}
}
import 'package:flutter/material.dart';
import 'package:library_app/src/providers/auth_provider.dart';
import 'package:library_app/src/providers/navigations_provider.dart';
import 'package:library_app/src/widgets/books/book_list.dart';
import 'package:library_app/src/widgets/home.dart';
import 'package:library_app/src/widgets/loans/loan_list.dart';
import 'package:library_app/src/widgets/profile.dart';
import 'package:provider/provider.dart';
class ListScreen extends StatelessWidget {
const ListScreen({super.key});
@override
Widget build(BuildContext context) {
return Consumer2<NavigationsProvider, AuthProvider>(
builder: (context, navProvider, authProvider, child) {
return Scaffold(
bottomNavigationBar: NavigationBar(
onDestinationSelected: (int index) {
navProvider.navigate(index);
},
selectedIndex: navProvider.currentPageIndex,
destinations: const <Widget>[
NavigationDestination(
icon: Icon(Icons.home_outlined),
label: 'Home',
tooltip: 'Home Page',
),
NavigationDestination(
icon: Icon(Icons.book_sharp),
label: 'Books',
tooltip: 'Book List',
),
NavigationDestination(
icon: Icon(Icons.date_range_sharp),
label: 'Loans',
tooltip: 'Loan List',
),
NavigationDestination(
icon: Icon(Icons.person_2_sharp),
label: 'Profile',
tooltip: 'Profile',
),
],
),
body: <Widget>[
// Home
const HomePage(),
// Books
const BookList(),
// Loans
LoanList(
memberId: authProvider.user!.id,
),
// Profile
const Profile(),
][navProvider.currentPageIndex],
);
},
);
}
}
import 'package:flutter/material.dart';
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
final String title;
final double sizeAppBar = 70.00;
const CustomAppBar({super.key, required this.title});
@override
Size get preferredSize => Size.fromHeight(sizeAppBar);
@override
Widget build(BuildContext context) {
return AppBar(
title: Text(title),
leading: IconButton(onPressed: () {}, icon: const Icon(Icons.menu)),
actions: [IconButton(onPressed: () {}, icon: const Icon(Icons.settings))],
);
}
}
import 'package:flutter/material.dart';
import 'package:library_app/src/models/book.dart';
import 'package:library_app/src/screens/detail_screen.dart';
import 'package:library_app/src/widgets/books/book_item.dart';
class BookDetail extends StatefulWidget {
final Book book;
const BookDetail({super.key, required this.book});
@override
_BookDetail createState() => _BookDetail();
}
class _BookDetail extends State<BookDetail> {
Book get book => widget.book;
@override
Widget build(BuildContext context) {
return DetailScreen(
title: book.title,
confirmMessage: "Loans for how many days?",
textSubmitButton: "Borrow",
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BookItem(book),
Text(book.description),
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:library_app/src/models/book.dart';
import 'package:library_app/src/widgets/books/book_detail.dart';
class BookItem extends StatelessWidget {
final Book _book;
const BookItem(this._book, {super.key});
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => BookDetail(book: _book),
),
);
},
child: Container(
margin: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 20.0),
height: 260.0,
child: Row(
children: [
Flexible(
fit: FlexFit.tight,
flex: 4,
child: ClipRRect(
borderRadius: BorderRadius.circular(13),
child: Image.network(_book.coverUrl ?? ""),
),
),
Flexible(
flex: 6,
child: Container(
padding: const EdgeInsets.fromLTRB(20.0, 18.0, 0.0, 18.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
_book.title,
style: Theme.of(context).textTheme.titleMedium,
),
Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Text(
'By ${_book.author}',
style: Theme.of(context).textTheme.labelMedium,
),
),
Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Text(
_book.description,
style: Theme.of(context).textTheme.labelMedium,
),
),
],
),
Text(
_book.category ?? "",
style: Theme.of(context).textTheme.labelMedium,
),
],
),
),
),
],
),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:library_app/src/providers/book_provider.dart';
import 'package:library_app/src/widgets/books/book_item.dart';
import 'package:library_app/src/models/book.dart';
import 'package:library_app/src/widgets/forms/search_form.dart';
import 'package:provider/provider.dart';
class BookList extends StatefulWidget {
const BookList({super.key});
@override
State<BookList> createState() => _BookList();
}
class _BookList extends State<BookList> {
@override
void initState() {
super.initState();
Provider.of<BookProvider>(context, listen: false).getBooks();
}
@override
Widget build(BuildContext context) {
return Consumer<BookProvider>(
builder: (context, bookProvider, child) {
if (bookProvider.books != null) {
final Iterable<Book> books = bookProvider.books!.map(
(book) => Book(
book["title"],
book["author"],
book["description"],
book["cover_image"],
book["category"],
),
);
return NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return [const TopAppBar(title: "Books")];
},
body: ListView(
children: List.generate(books.length, (index) {
return BookItem(
books.elementAt(index),
);
}),
),
);
} else {
return NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return [const TopAppBar(title: "Books")];
},
body: const Center(
child: CircularProgressIndicator(),
),
);
}
},
);
}
}
class TopAppBar extends StatefulWidget {
final String title;
const TopAppBar({super.key, required this.title});
@override
_TopAppBar createState() => _TopAppBar();
}
class _TopAppBar extends State<TopAppBar> {
String get title => widget.title;
bool showWidget = false;
@override
Widget build(BuildContext context) {
return SliverAppBar(
title: Text(showWidget ? "" : title),
actions: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
onPressed: () {
setState(() {
showWidget = !showWidget;
});
},
icon: Icon(showWidget ? Icons.close : Icons.search),
),
Offstage(
offstage: !showWidget,
child: const SearchForm(),
),
],
),
],
elevation: 10.0,
automaticallyImplyLeading: false,
expandedHeight: 50,
floating: true,
snap: true,
);
}
}
import 'package:flutter/material.dart';
import 'package:library_app/src/models/category.dart';
class CategoryItem extends StatelessWidget {
final String name;
const CategoryItem({super.key, required this.name});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 3.0),
child: SizedBox(
height: 24.0,
child: ElevatedButton(
onPressed: () {},
child: Text(name),
),
),
);
}
}
class CategoryList extends StatelessWidget {
CategoryList({super.key});
final List<Category> _category = initialCategories;
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 10.0),
child: Row(
children: List.generate(_category.length, (index) {
return CategoryItem(name: _category.elementAt(index).name);
}),
),
),
);
}
}
import 'package:flutter/material.dart';
class Shortcut extends StatelessWidget {
final String title;
final String subtitle;
final IconData? icon;
final Function()? onTap;
const Shortcut(
{super.key,
required this.title,
required this.subtitle,
this.icon,
this.onTap});
@override
Widget build(BuildContext context) {
final screenSize = MediaQuery.of(context).size;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
child: Card(
child: InkWell(
splashColor: Theme.of(context).splashColor,
onTap: onTap,
child: Container(
padding:
const EdgeInsets.symmetric(vertical: 20.0, horizontal: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
width: screenSize.width * 0.4,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: Theme.of(context).textTheme.labelLarge,
),
Text(
subtitle,
style: Theme.of(context).textTheme.labelMedium,
),
],
),
),
Icon(
icon,
size: screenSize.width * 0.2,
),
],
),
),
)));
}
}
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class LoanBookForm extends StatelessWidget {
const LoanBookForm({super.key});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
child: FilledButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Loans for how many days?'),
content: Form(
child: TextFormField(
decoration: const InputDecoration(
hintText: "Input number",
labelText: "Days",
suffixIcon: Icon(Icons.date_range),
),
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
),
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () {
// Submit form data
Navigator.of(context).pop();
},
child: const Text('Submit'),
),
],
);
},
);
},
child: const Text('borrow'),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:library_app/src/providers/auth_provider.dart';
import 'package:library_app/src/screens/form_screen.dart';
import 'package:provider/provider.dart';
class LoginForm extends StatefulWidget {
const LoginForm({super.key});
@override
State<LoginForm> createState() => _LoginForm();
}
class _LoginForm extends State<LoginForm> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final usernameController = TextEditingController();
final passwordController = TextEditingController();
bool passwordVisible = false;
@override
void initState() {
super.initState();
passwordVisible = true;
}
@override
void dispose() {
usernameController.dispose();
passwordController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
const String title = "Log In";
const String formText = "Log In to continue";
return Consumer<AuthProvider>(builder: (context, authProvider, child) {
final isInvalid = authProvider.invalidUsernameOrPassword;
return Column(
children: [
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
child: SvgPicture.asset(
"assets/images/login_image.svg",
semanticsLabel: title,
height: screenSize.height * 0.2,
),
),
const Text(
formText,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
Container(
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFormField(
controller: usernameController,
decoration: const InputDecoration(
hintText: "Enter your Username",
labelText: "Username",
suffixIcon: Icon(Icons.supervised_user_circle),
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return "Please enter your username";
} else {
return null;
}
},
),
TextFormField(
controller: passwordController,
obscureText: passwordVisible,
decoration: InputDecoration(
hintText: "Enter your Password",
labelText: "Password",
suffixIcon: IconButton(
icon: Icon(passwordVisible
? Icons.visibility
: Icons.visibility_off),
onPressed: () {
setState(
() {
passwordVisible = !passwordVisible;
},
);
},
),
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return "Please enter your password";
} else {
return null;
}
},
keyboardType: TextInputType.visiblePassword,
),
Visibility(
visible: isInvalid,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Theme.of(context).highlightColor,
),
margin: const EdgeInsets.symmetric(vertical: 20.0),
padding: const EdgeInsets.symmetric(
horizontal: 10.0, vertical: 8.0),
child: const Text("Invalid username or password"),
),
),
const SizedBox(
height: 20.0,
),
Column(
children: [
SizedBox(
width: double.infinity,
child: FilledButton(
onPressed: () {
if (_formKey.currentState!.validate()) {}
authProvider.signIn(
usernameController.text,
passwordController.text,
);
},
child: const Text("Submit"),
),
),
SizedBox(
width: double.infinity,
child: TextButton(
child: const Text("Sign Up"),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const SignUpScreen(),
),
);
},
),
),
SizedBox(
width: double.infinity,
child: TextButton(
child: const Text("Forgot Password"),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const ResetPasswordScreen(),
));
},
),
),
],
),
],
),
),
)
],
);
});
}
}
import 'package:flutter/material.dart';
import 'package:library_app/src/providers/auth_provider.dart';
import 'package:library_app/src/models/user.dart';
import 'package:library_app/src/screens/form_screen.dart';
import 'package:provider/provider.dart';
class ProfileEditForm extends StatefulWidget {
final User? user;
const ProfileEditForm({super.key, this.user});
@override
_ProfileEditForm createState() => _ProfileEditForm();
}
class _ProfileEditForm extends State<ProfileEditForm> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final usernameControler = TextEditingController();
final emailControler = TextEditingController();
final firstNameControler = TextEditingController();
final lastNameControler = TextEditingController();
@override
void initState() {
super.initState();
}
@override
void dispose() {
usernameControler.dispose();
emailControler.dispose();
firstNameControler.dispose();
lastNameControler.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final User? user = widget.user;
usernameControler.text = user?.username ?? "";
emailControler.text = user?.email ?? "";
firstNameControler.text = user?.firstName ?? "";
lastNameControler.text = user?.lastName ?? "";
return Consumer<AuthProvider>(builder: (context, authProvider, child) {
return Column(
children: [
Form(
key: _formKey,
child: Container(
padding: const EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFormField(
controller: usernameControler,
decoration: const InputDecoration(
hintText: "Enter your Username",
labelText: "Username",
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return "Please enter your username";
}
return null;
},
),
TextFormField(
controller: emailControler,
decoration: const InputDecoration(
hintText: "Enter your Email",
labelText: "Email",
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return "Please enter your email";
}
return null;
},
),
TextFormField(
controller: firstNameControler,
decoration: const InputDecoration(
hintText: "Enter your First Name",
labelText: "First Name",
),
),
TextFormField(
controller: lastNameControler,
decoration: const InputDecoration(
hintText: "Enter your Last Name",
labelText: "Last Name",
),
),
Padding(
padding: const EdgeInsets.only(top: 40.0),
child: SizedBox(
width: double.infinity,
child: FilledButton(
onPressed: () {
if (_formKey.currentState!.validate()) {}
authProvider.updateUserDetail(
authProvider.user!.id,
usernameControler.text,
emailControler.text,
firstNameControler.text,
lastNameControler.text,
authProvider.user!.isStaff,
);
},
child: const Text("Submit"),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 10.0),
child: SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const ResetPasswordScreen(),
),
);
},
child: const Text("Change Password"),
),
),
)
],
),
),
)
],
);
});
}
}
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
class ResetPasswordForm extends StatefulWidget {
const ResetPasswordForm({super.key});
@override
State<ResetPasswordForm> createState() => _ResetPasswordForm();
}
class _ResetPasswordForm extends State<ResetPasswordForm> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
bool passwordVisible = false;
@override
void initState() {
super.initState();
passwordVisible = true;
}
@override
Widget build(BuildContext context) {
const String title = "Reset Password";
const String formText = "Confirm your email to continue reset password";
return Column(
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0),
child: Column(
children: [
SvgPicture.asset(
"assets/images/reset_password_image.svg",
semanticsLabel: title,
width: 200,
),
const SizedBox(
height: 10.0,
),
const Text(
formText,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
],
),
),
Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30.0,
vertical: 30.0,
),
child: Container(
padding: const EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFormField(
decoration: const InputDecoration(
hintText: "Enter your Email",
labelText: "Email",
suffixIcon: Icon(Icons.email_rounded),
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return "Please enter your email";
} else if (!value.contains("@")) {
return "Email should include '@'";
}
return null;
},
),
Container(
padding: const EdgeInsets.symmetric(
vertical: 20.0,
),
child: Column(
children: [
SizedBox(
width: double.infinity,
child: FilledButton(
onPressed: () {
if (_formKey.currentState!.validate()) {}
},
child: const Text("Submit"),
),
),
],
),
)
],
),
),
),
)
],
);
}
}
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:library_app/src/providers/book_provider.dart';
class SearchForm extends StatefulWidget implements PreferredSizeWidget {
final double sizeAppBar = 60.0;
const SearchForm({super.key});
@override
Size get preferredSize => Size.fromHeight(sizeAppBar);
@override
_SearchForm createState() => _SearchForm();
}
class _SearchForm extends State<SearchForm> {
@override
Widget build(BuildContext context) {
MediaQueryData queryData;
queryData = MediaQuery.of(context);
return Container(
width: queryData.size.width * 0.8,
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: SearchBar(
elevation: WidgetStateProperty.all(0),
onChanged: (value) =>
Provider.of<BookProvider>(context, listen: false).searchBook(value),
leading: const Icon(Icons.search),
),
);
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment