add frontend and put backend in seperate folder

This commit is contained in:
lukas-heiligenbrunner 2023-12-27 16:45:55 +01:00
parent d409d08572
commit 6faa995b19
88 changed files with 2993 additions and 12 deletions

View File

@ -1,4 +1,9 @@
# Stage 1: Build the Rust binary FROM ghcr.io/cirruslabs/flutter:latest AS frontend_builder
WORKDIR /app
COPY frontend /app
RUN flutter build web --release
FROM rust AS builder FROM rust AS builder
# Install necessary tools and dependencies # Install necessary tools and dependencies
@ -6,13 +11,15 @@ FROM rust AS builder
WORKDIR /app WORKDIR /app
# Copy the Rust project files # Copy the Rust project files
COPY ./src /app/src COPY backend/src /app/src
COPY ./scripts /app/scripts COPY backend/scripts /app/scripts
COPY Cargo.lock /app COPY backend/Cargo.lock /app
COPY Cargo.toml /app COPY backend/Cargo.toml /app
COPY --from=frontend_builder /app/build/web /app/web
# Build the Rust binary # Build the Rust binary
RUN cargo build --release RUN cargo build --release --features static
# Stage 2: Create the final image # Stage 2: Create the final image
FROM archlinux FROM archlinux
@ -20,6 +27,7 @@ FROM archlinux
# Copy the built binary from the previous stage # Copy the built binary from the previous stage
COPY --from=builder /app/target/release/untitled /usr/local/bin/untitled COPY --from=builder /app/target/release/untitled /usr/local/bin/untitled
RUN pacman -Syyu --noconfirm RUN pacman -Syyu --noconfirm
RUN pacman -S --noconfirm base-devel git RUN pacman -S --noconfirm base-devel git
RUN pacman -Sc RUN pacman -Sc

View File

@ -2156,6 +2156,40 @@ dependencies = [
"zeroize", "zeroize",
] ]
[[package]]
name = "rust-embed"
version = "8.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "810294a8a4a0853d4118e3b94bb079905f2107c7fe979d8f0faae98765eb6378"
dependencies = [
"rust-embed-impl",
"rust-embed-utils",
"walkdir",
]
[[package]]
name = "rust-embed-impl"
version = "8.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfc144a1273124a67b8c1d7cd19f5695d1878b31569c0512f6086f0f4676604e"
dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
"syn 2.0.42",
"walkdir",
]
[[package]]
name = "rust-embed-utils"
version = "8.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "816ccd4875431253d6bb54b804bcff4369cbde9bae33defde25fdf6c2ef91d40"
dependencies = [
"sha2",
"walkdir",
]
[[package]] [[package]]
name = "rust_decimal" name = "rust_decimal"
version = "1.33.1" version = "1.33.1"
@ -2233,6 +2267,15 @@ version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "schannel" name = "schannel"
version = "0.1.22" version = "0.1.22"
@ -3346,6 +3389,7 @@ dependencies = [
"reqwest", "reqwest",
"rocket", "rocket",
"rocket_okapi", "rocket_okapi",
"rust-embed",
"sea-orm", "sea-orm",
"sea-orm-migration", "sea-orm-migration",
"serde", "serde",
@ -3409,6 +3453,16 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
dependencies = [
"same-file",
"winapi-util",
]
[[package]] [[package]]
name = "want" name = "want"
version = "0.3.1" version = "0.3.1"
@ -3528,6 +3582,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "winapi-x86_64-pc-windows-gnu" name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"

View File

@ -20,9 +20,12 @@ rocket_okapi = { version = "0.8.0-rc.3", features = ["swagger"] }
sea-orm = { version = "0.12", features = [ "sqlx-sqlite", "runtime-tokio-rustls", "macros" ] } sea-orm = { version = "0.12", features = [ "sqlx-sqlite", "runtime-tokio-rustls", "macros" ] }
sea-orm-migration = {version = "0.12", features = ["sqlx-sqlite", "runtime-tokio-rustls"]} sea-orm-migration = {version = "0.12", features = ["sqlx-sqlite", "runtime-tokio-rustls"]}
serde = "1.0.193" serde = "1.0.193"
rust-embed = "8.1.0"
[[bin]] [[bin]]
name = "untitled" name = "untitled"
path = "src/main.rs" path = "src/main.rs"
[features]
default = []
static = []

View File

@ -20,5 +20,6 @@ pub fn build_api() -> Vec<Route> {
version_del, version_del,
build_output, build_output,
list_builds, list_builds,
] ]
} }

51
backend/src/api/embed.rs Normal file
View File

@ -0,0 +1,51 @@
use rocket::http::uri::fmt::Path;
use rocket::http::uri::Segments;
use rocket::http::{ContentType, Method, Status};
use rocket::route::{Handler, Outcome};
use rocket::{Data, Request, Response, Route};
use rust_embed::{RustEmbed};
use std::io::Cursor;
#[derive(RustEmbed)]
#[folder = "web"]
struct Asset;
#[derive(Clone)]
pub struct CustomHandler {}
impl Into<Vec<Route>> for CustomHandler {
fn into(self) -> Vec<Route> {
vec![Route::ranked(-2, Method::Get, "/<path..>", self)]
}
}
#[rocket::async_trait]
impl Handler for CustomHandler {
async fn handle<'r>(&self, request: &'r Request<'_>, _: Data<'r>) -> Outcome<'r> {
let mut path = request
.segments::<Segments<'_, Path>>(0..)
.ok()
.and_then(|segments| segments.to_path_buf(true).ok())
.unwrap();
if path.is_dir() || path.to_str() == Some("") {
path = path.join("index.html")
}
match <Asset as RustEmbed>::get(path.to_string_lossy().as_ref()) {
None => Outcome::Failure(Status::NotFound),
Some(file_content) => {
let content_type: ContentType = path
.extension()
.map(|x| x.to_string_lossy())
.and_then(|x| ContentType::from_extension(&x))
.unwrap_or(ContentType::Plain);
let rsp = Response::build()
.header(content_type)
.sized_body(file_content.data.len(), Cursor::new(file_content.data))
.finalize();
Outcome::Success(rsp)
}
}
}
}

View File

@ -2,3 +2,5 @@ mod add;
pub mod backend; pub mod backend;
mod list; mod list;
mod remove; mod remove;
#[cfg(feature = "static")]
pub mod embed;

View File

@ -16,6 +16,8 @@ use sea_orm::{Database, DatabaseConnection};
use sea_orm_migration::MigratorTrait; use sea_orm_migration::MigratorTrait;
use std::fs; use std::fs;
use tokio::sync::broadcast; use tokio::sync::broadcast;
#[cfg(feature = "static")]
use crate::api::embed::CustomHandler;
fn main() { fn main() {
let t = tokio::runtime::Runtime::new().unwrap(); let t = tokio::runtime::Runtime::new().unwrap();
@ -50,20 +52,25 @@ fn main() {
config.address = "0.0.0.0".parse().unwrap(); config.address = "0.0.0.0".parse().unwrap();
config.port = 8081; config.port = 8081;
let launch_result = rocket::custom(config) let rock = rocket::custom(config)
.manage(db) .manage(db)
.manage(tx) .manage(tx)
.mount("/", backend::build_api()) .mount("/", backend::build_api())
.mount( .mount(
"/docs/", "/docs/",
make_swagger_ui(&SwaggerUIConfig { make_swagger_ui(&SwaggerUIConfig {
url: "../openapi.json".to_owned(), url: "../openapi.json".to_owned(),
..Default::default() ..Default::default()
}), }),
) );
#[cfg(feature = "static")]
let rock = rock.mount("/", CustomHandler {});
let rock = rock
.launch() .launch()
.await; .await;
match launch_result { match rock {
Ok(_) => println!("Rocket shut down gracefully."), Ok(_) => println!("Rocket shut down gracefully."),
Err(err) => println!("Rocket had an error: {}", err), Err(err) => println!("Rocket had an error: {}", err),
}; };

43
frontend/.gitignore vendored Normal file
View File

@ -0,0 +1,43 @@
# 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

45
frontend/.metadata Normal file
View File

@ -0,0 +1,45 @@
# 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: "b0366e0a3f089e15fd89c97604ab402fe26b724c"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
- platform: android
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
- platform: ios
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
- platform: linux
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
- platform: macos
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
- platform: web
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
- platform: windows
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
# 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'

16
frontend/README.md Normal file
View File

@ -0,0 +1,16 @@
# aurcache
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.

View File

@ -0,0 +1,28 @@
# 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.
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

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="15.429" viewBox="0 0 12 15.429">
<g id="Group_785" data-name="Group 785" transform="translate(-279 -215)">
<path id="Vector" d="M11.864,6.612H7.091a1.628,1.628,0,0,1-1.157-.484,1.662,1.662,0,0,1-.479-1.169V.138a.138.138,0,0,0-.04-.1.136.136,0,0,0-.1-.04H2.182A2.171,2.171,0,0,0,.639.646,2.216,2.216,0,0,0,0,2.2v11.02a2.216,2.216,0,0,0,.639,1.559,2.171,2.171,0,0,0,1.543.646H9.818a2.171,2.171,0,0,0,1.543-.646A2.216,2.216,0,0,0,12,13.224V6.75a.138.138,0,0,0-.04-.1A.136.136,0,0,0,11.864,6.612Z" transform="translate(279 215)" fill="#2697ff"/>
<path id="Vector-2" data-name="Vector" d="M5.019,4.973.116.02a.068.068,0,0,0-.1.01A.069.069,0,0,0,0,.069v4.47a.554.554,0,0,0,.16.39.543.543,0,0,0,.386.161H4.971a.068.068,0,0,0,.038-.012.069.069,0,0,0,.025-.031.069.069,0,0,0-.015-.075Z" transform="translate(285.545 215.42)" fill="#2697ff"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 916 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="13.811" height="13.572" viewBox="0 0 13.811 13.572">
<g id="Search" transform="translate(-1165.25 -48.25)" opacity="0.8">
<path id="Vector" d="M10.286,5.041a5.093,5.093,0,0,1-5.143,5.041A5.093,5.093,0,0,1,0,5.041,5.093,5.093,0,0,1,5.143,0,5.093,5.093,0,0,1,10.286,5.041Z" transform="translate(1166 49)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-2" data-name="Vector" d="M2.571,2.52,0,0" transform="translate(1175.429 58.241)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 660 B

View File

@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14.655" height="14.88" viewBox="0 0 14.655 14.88">
<g id="Group" transform="translate(-918 -214)">
<path id="Vector" d="M3.837,2.249a.346.346,0,0,1-.178-.05L0,0V3.914L4.87,6.842V.966L4.127,2.093A.347.347,0,0,1,3.837,2.249Z" transform="translate(920.102 222.038)" fill="#007ee5"/>
<path id="Vector-2" data-name="Vector" d="M6.654,1.092,4.9,0,0,2.943,1.758,4.036Z" transform="translate(918 214.061)" fill="#007ee5"/>
<path id="Vector-3" data-name="Vector" d="M5.965,2.987,1,0,0,1.513,4.968,4.5Z" transform="translate(918.864 218.972)" fill="#007ee5"/>
<path id="Vector-4" data-name="Vector" d="M4.89,0,0,2.94,4.89,5.88,9.78,2.94Z" transform="translate(920.429 215.563)" fill="#007ee5"/>
<path id="Vector-5" data-name="Vector" d="M3.114,1.115,0,2.987,1.007,4.5,5.975,1.514,4.968,0Z" transform="translate(925.808 218.971)" fill="#007ee5"/>
<path id="Vector-6" data-name="Vector" d="M0,1.147,4.9,4.094,6.679,2.947,1.778,0Z" transform="translate(925.976 214)" fill="#007ee5"/>
<path id="Vector-7" data-name="Vector" d="M1.045,2.242a.347.347,0,0,1-.289-.155L0,.951V6.834L4.87,3.907V0L1.223,2.192A.346.346,0,0,1,1.045,2.242Z" transform="translate(925.666 222.046)" fill="#007ee5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="19" viewBox="0 0 25 19">
<path id="Vector" d="M25,4.354a2.7,2.7,0,0,0-.854-1.959,3,3,0,0,0-2.062-.812H10.631a1.292,1.292,0,0,1-.693-.2L8.49.466A3.015,3.015,0,0,0,6.869,0H2.917A3,3,0,0,0,.854.812,2.7,2.7,0,0,0,0,2.771V5.146a.386.386,0,0,0,.122.28.428.428,0,0,0,.295.116H24.583a.428.428,0,0,0,.295-.116A.386.386,0,0,0,25,5.146ZM0,16.229a2.7,2.7,0,0,0,.854,1.959A3,3,0,0,0,2.917,19H22.083a3,3,0,0,0,2.062-.812A2.7,2.7,0,0,0,25,16.229V7.521a.386.386,0,0,0-.122-.28.428.428,0,0,0-.295-.116H.417a.428.428,0,0,0-.295.116A.386.386,0,0,0,0,7.521Z" fill="#ffcf26"/>
</svg>

After

Width:  |  Height:  |  Size: 624 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 84 KiB

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="26" height="22" viewBox="0 0 26 22">
<path id="Vector" d="M23.231,0H2.769A2.755,2.755,0,0,0,.811.819,2.81,2.81,0,0,0,0,2.8V19.2a2.81,2.81,0,0,0,.811,1.977A2.755,2.755,0,0,0,2.769,22H23.231a2.755,2.755,0,0,0,1.958-.819A2.81,2.81,0,0,0,26,19.2V2.8A2.81,2.81,0,0,0,25.189.819,2.755,2.755,0,0,0,23.231,0ZM9.177,15.475V6.525L16.837,11Z" fill="#26e5ff"/>
</svg>

After

Width:  |  Height:  |  Size: 405 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="14" viewBox="0 0 13 14">
<path id="Vector" d="M12.994,2.169V4.278a2.281,2.281,0,0,1-.559,1.537,1.886,1.886,0,0,1-1.384.652h-.8a.592.592,0,0,1,0-1.161h.772a.878.878,0,0,0,.649-.3,1.063,1.063,0,0,0,.262-.719V2.169a.972.972,0,0,0-.911-1H9.1a.959.959,0,0,0-.911,1V5.332a.563.563,0,0,1-.543.57.5.5,0,0,1-.37-.181.61.61,0,0,1-.143-.416V2.169A2.276,2.276,0,0,1,7.71.636,1.881,1.881,0,0,1,9.1,0h1.924A2.123,2.123,0,0,1,12.994,2.169ZM3.9,0H1.973A2.09,2.09,0,0,0,0,2.169V4.284A2.083,2.083,0,0,0,1.973,6.446H3.9a1.88,1.88,0,0,0,1.394-.631A2.276,2.276,0,0,0,5.87,4.284V2.169A2.084,2.084,0,0,0,3.9,0Zm.911,4.284A1.063,1.063,0,0,1,4.546,5a.879.879,0,0,1-.649.3H1.973a.87.87,0,0,1-.662-.293,1.056,1.056,0,0,1-.267-.728V2.169a1.053,1.053,0,0,1,.273-.715.869.869,0,0,1,.656-.286H3.9a.966.966,0,0,1,.911,1Zm4.3,3.27h1.924A2.083,2.083,0,0,1,13,9.716v2.116A2.09,2.09,0,0,1,11.027,14H9.1a2.085,2.085,0,0,1-1.967-2.169V9.716A2.071,2.071,0,0,1,9.1,7.554Zm2.57,4.988a1.048,1.048,0,0,0,.265-.71V9.716a1.054,1.054,0,0,0-.267-.708.871.871,0,0,0-.644-.293H9.1a.959.959,0,0,0-.911,1v2.116a1.048,1.048,0,0,0,.265.71.865.865,0,0,0,.646.291h1.924A.865.865,0,0,0,11.673,12.541ZM0,11.825V9.716A2.275,2.275,0,0,1,.578,8.185a1.88,1.88,0,0,1,1.394-.631h.79a.516.516,0,0,1,.507.271.633.633,0,0,1,0,.619.516.516,0,0,1-.507.271h-.79a.965.965,0,0,0-.917,1V11.8a.984.984,0,0,0,.917,1H3.909a.87.87,0,0,0,.648-.291,1.054,1.054,0,0,0,.269-.71V8.668a.608.608,0,0,1,.238-.6.492.492,0,0,1,.594.019.614.614,0,0,1,.206.613v3.124a2.078,2.078,0,0,1-1.973,2.169H1.973A2.122,2.122,0,0,1,0,11.825Z" fill="#00162a" opacity="0.6"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="15" viewBox="0 0 13 15">
<path id="Vector" d="M12.841,4.167,8.979.183A.574.574,0,0,0,8.567.009H8.41L8.39,0a.082.082,0,0,0-.024,0,.087.087,0,0,0-.025,0l-.019,0H3.495A3.486,3.486,0,0,0,0,3.391V6.51a.572.572,0,0,0,1.144,0V3.391A2.333,2.333,0,0,1,3.495,1.142h4.3V2.764a2.526,2.526,0,0,0,2.529,2.511h0a.566.566,0,1,0,0-1.133A1.386,1.386,0,0,1,8.938,2.764V1.777l2.918,3.011v6.694a2.392,2.392,0,0,1-2.271,2.386H3.495a2.344,2.344,0,0,1-2.351-2.386V9.589A.572.572,0,0,0,0,9.589v1.892A3.47,3.47,0,0,0,3.495,15H9.585A3.514,3.514,0,0,0,13,11.481V4.56A.565.565,0,0,0,12.841,4.167ZM4.107,10.8H8.222a.566.566,0,1,0,0-1.133H4.107a.566.566,0,1,0,0,1.133ZM6.665,7.065H4.107a.566.566,0,1,1,0-1.133H6.665a.566.566,0,1,1,0,1.133Z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 792 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16">
<path id="Vector" d="M13.445,7.447A3.185,3.185,0,0,1,14,9.088l-.022.148a3.252,3.252,0,0,1-.774,2.2,4.069,4.069,0,0,1-2.572,1.232,34.465,34.465,0,0,1-7.306,0A4.022,4.022,0,0,1,.8,11.439,3.207,3.207,0,0,1,0,9.249v-.1A3.3,3.3,0,0,1,.6,7.469L.659,7.4A3.035,3.035,0,0,0,1.389,5.99V4.54a.631.631,0,0,1,.653-.381.619.619,0,0,1,.553.507v1.45a.353.353,0,0,1,0,.077A4.166,4.166,0,0,1,1.586,8.151a1.982,1.982,0,0,0-.321,1v.155a2.022,2.022,0,0,0,.482,1.373,2.768,2.768,0,0,0,1.71.788,33.927,33.927,0,0,0,7.073,0,2.773,2.773,0,0,0,1.746-.824,2,2,0,0,0,.46-1.33V9.151a2.056,2.056,0,0,0-.314-1.007,4.175,4.175,0,0,1-1.067-1.957.358.358,0,0,1,0-.077V4.653C11.143,2.527,8.944,1.211,7.03,1.211a4.853,4.853,0,0,0-2.323.584.649.649,0,0,1-.639,0A.595.595,0,0,1,4.093.739,6.108,6.108,0,0,1,6.971,0C9.5,0,12.334,1.732,12.656,4.512v1.45a2.973,2.973,0,0,0,.731,1.408A.538.538,0,0,1,13.445,7.447Zm-6.238,7.3a1.641,1.641,0,0,0,1.072-.624h.007a.647.647,0,0,1,.888-.081.592.592,0,0,1,.084.855,2.926,2.926,0,0,1-4.581,0,.592.592,0,0,1,.084-.855.647.647,0,0,1,.888.081,1.661,1.661,0,0,0,1.558.624Z" fill="#00162a" opacity="0.6"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="15" viewBox="0 0 10 15">
<path id="Vector" d="M2.536,4.015A2.735,2.735,0,0,1,5,1.078,2.735,2.735,0,0,1,7.464,4.015,2.735,2.735,0,0,1,5,6.952,2.735,2.735,0,0,1,2.536,4.015Zm-.9,0C1.633,6.229,3.143,8.03,5,8.03s3.367-1.8,3.367-4.015S6.857,0,5,0,1.633,1.8,1.633,4.015ZM4.361,14.989Q4.675,15,5,15c2.147,0,5-.286,5-2.752,0-2.768-3.764-2.768-5-2.768-2.147,0-5,.286-5,2.753a2.362,2.362,0,0,0,1.66,2.29.438.438,0,0,0,.573-.338A.567.567,0,0,0,1.95,13.5C1.011,13.124.9,12.6.9,12.233c0-1.112,1.379-1.676,4.1-1.676s4.1.569,4.1,1.691S7.718,13.922,5,13.922q-.311,0-.613-.01a.547.547,0,0,0-.026,1.076Z" fill="#00162a" opacity="0.6"/>
</svg>

After

Width:  |  Height:  |  Size: 686 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="15" viewBox="0 0 13 15">
<path id="Vector" d="M4.408,3.656a1.713,1.713,0,0,1-1.813-.013L2.57,3.617A.6.6,0,0,1,2.4,2.826a.516.516,0,0,1,.739-.184.732.732,0,0,0,.369.112.723.723,0,0,0,.54-.212.829.829,0,0,0,.241-.559A1.92,1.92,0,0,1,6.078,0h.843A1.915,1.915,0,0,1,8.767,1.976a.8.8,0,0,0,.1.4.755.755,0,0,0,.453.376.7.7,0,0,0,.569-.08,1.78,1.78,0,0,1,2.462.711.61.61,0,0,1-.2.784.522.522,0,0,1-.732-.2.724.724,0,0,0-1.022-.29,1.741,1.741,0,0,1-1.809-.021,2,2,0,0,1-.924-1.665A.829.829,0,0,0,7.456,1.4a.722.722,0,0,0-.535-.243H6.078A.727.727,0,0,0,5.54,1.4a.835.835,0,0,0-.213.581A1.97,1.97,0,0,1,4.408,3.656Zm.919,9.388a.778.778,0,0,0,.751.8l-.006.013a.53.53,0,0,1,.464.287.608.608,0,0,1,0,.573A.53.53,0,0,1,6.071,15a1.915,1.915,0,0,1-1.846-1.976.8.8,0,0,0-.1-.4.725.725,0,0,0-1.022-.3,1.78,1.78,0,0,1-2.462-.711l-.418-.784A2.056,2.056,0,0,1,.89,8.2a.792.792,0,0,0,.271-.29.842.842,0,0,0,.122-.637A.794.794,0,0,0,.92,6.752,2.056,2.056,0,0,1,.256,4.117.535.535,0,0,1,.6,3.873a.507.507,0,0,1,.4.087.592.592,0,0,1,.154.764A.828.828,0,0,0,1.431,5.81a1.887,1.887,0,0,1,.64.718,2.055,2.055,0,0,1-.665,2.635A.828.828,0,0,0,1.13,10.25l.425.784a.742.742,0,0,0,.453.378.691.691,0,0,0,.569-.088,1.689,1.689,0,0,1,.9-.257A1.915,1.915,0,0,1,5.327,13.043ZM12.1,8.2a.793.793,0,0,1-.348-.486.847.847,0,0,1,.077-.607.793.793,0,0,1,.271-.29.6.6,0,0,0,.185-.784.529.529,0,0,0-.726-.217A2.055,2.055,0,0,0,10.9,8.445a1.868,1.868,0,0,0,.671.784.785.785,0,0,1,.348.483.839.839,0,0,1-.077.6l-.418.784a.779.779,0,0,1-.455.375.691.691,0,0,1-.566-.086,1.741,1.741,0,0,0-1.812.023,2,2,0,0,0-.921,1.67.539.539,0,0,0,1.077,0,.8.8,0,0,1,.369-.7.7.7,0,0,1,.751.008,1.78,1.78,0,0,0,2.462-.711l.419-.784A2.056,2.056,0,0,0,12.1,8.2ZM6.5,5.026A2.318,2.318,0,0,0,4.358,6.557a2.606,2.606,0,0,0,.5,2.7,2.2,2.2,0,0,0,2.524.533A2.486,2.486,0,0,0,8.81,7.5a2.561,2.561,0,0,0-.678-1.749A2.233,2.233,0,0,0,6.5,5.026Zm0,3.794A1.276,1.276,0,0,1,5.265,7.5,1.276,1.276,0,0,1,6.5,6.186,1.276,1.276,0,0,1,7.727,7.5,1.276,1.276,0,0,1,6.5,8.821Z" fill="#00162a" opacity="0.6"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="15" viewBox="0 0 13 15">
<path id="Vector" d="M12.934,10.31l-.517-4.4c-.331-1.978-1.527-2.637-2.537-2.637A3.628,3.628,0,0,0,7.559.174,3.176,3.176,0,0,0,4.032,1.226a.622.622,0,0,0-.118.566.552.552,0,0,0,.388.4.5.5,0,0,0,.506-.17V1.951a2.168,2.168,0,0,1,3.258-.2,2.66,2.66,0,0,1,.745,1.516H3.173c-.968,0-2.14.659-2.537,2.67l-.15.989a.574.574,0,0,0,.436.631.531.531,0,0,0,.6-.433l.144-.969c.222-1.1.781-1.76,1.5-1.76H9.881c.757,0,1.316.659,1.5,1.714l.511,4.358a3.567,3.567,0,0,1-.391,2.578,2.657,2.657,0,0,1-2.23.771H3.786a2.728,2.728,0,0,1-2.17-.857,3.285,3.285,0,0,1-.451-2.492A.57.57,0,0,0,.72,9.816a.535.535,0,0,0-.6.488,3.971,3.971,0,0,0,.692,3.412,3.222,3.222,0,0,0,2.974,1.256H9.268A3.528,3.528,0,0,0,12.273,13.8,4.671,4.671,0,0,0,12.934,10.31ZM8.216,7.522a.684.684,0,0,0,.234.053.577.577,0,0,0,.421-.2.527.527,0,0,0,.144-.218.6.6,0,0,0,.048-.251.468.468,0,0,0,0-.132.421.421,0,0,0-.036-.125.273.273,0,0,0-.054-.112.917.917,0,0,0-.162-.185.729.729,0,0,0-.222-.1.473.473,0,0,0-.234,0,.4.4,0,0,0-.114.04.441.441,0,0,0-.108.059l-.09.086a.288.288,0,0,0-.072.1l-.06.112v.125a.478.478,0,0,0,0,.132.593.593,0,0,0,.042.251A.652.652,0,0,0,8.216,7.522ZM5.228,6.915a.632.632,0,0,1-.6.659.578.578,0,0,1-.409-.2.667.667,0,0,1-.132-.218.716.716,0,0,1-.042-.251.47.47,0,0,1,0-.132.423.423,0,0,1,.036-.125.383.383,0,0,1,.054-.112.286.286,0,0,1,.072-.1.4.4,0,0,1,.09-.079A.327.327,0,0,1,4.4,6.3a.339.339,0,0,1,.114-.04.473.473,0,0,1,.234,0,.339.339,0,0,1,.114.04.327.327,0,0,1,.1.059.4.4,0,0,1,.1.086.287.287,0,0,1,.072.1.674.674,0,0,1,.06.112l.036.125A.9.9,0,0,1,5.228,6.915Z" fill="#00162a" opacity="0.6"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
<path id="Vector" d="M13.992,5.48A6.347,6.347,0,0,0,8.009,0a1.056,1.056,0,0,0-.8.34,1.114,1.114,0,0,0-.288.821L7.23,5.981A1.144,1.144,0,0,0,8.347,7.059H8.42l4.6-.321a1.02,1.02,0,0,0,.718-.365A1.116,1.116,0,0,0,14,5.583v-.1ZM8.347,5.9,8.04,1.168a5.217,5.217,0,0,1,4.847,4.421Zm2.013,3.3a.562.562,0,0,1,.687-.4.555.555,0,0,1,.346.267.6.6,0,0,1,.059.446,6.045,6.045,0,0,1-2.816,3.728,5.587,5.587,0,0,1-5.477.087A6.081,6.081,0,0,1,.045,8.612,3.969,3.969,0,0,1,0,7.9,6.038,6.038,0,0,1,4.64,1.925a.565.565,0,0,1,.663.462.589.589,0,0,1-.442.693A4.889,4.889,0,0,0,1.125,7.919a3.251,3.251,0,0,0,.031.545,4.806,4.806,0,0,0,4.312,4.317A4.724,4.724,0,0,0,10.359,9.2Z" fill="#001b34" opacity="0.6"/>
</svg>

After

Width:  |  Height:  |  Size: 780 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="14" viewBox="0 0 13 14">
<path id="Vector" d="M13,6a.518.518,0,0,1-.5.536H12.5a.475.475,0,0,1-.352-.159A.552.552,0,0,1,12.005,6V4.377c0-2.13-1.092-3.306-3.07-3.306H4.065c-1.984,0-3.07,1.176-3.07,3.306V9.629c0,2.13,1.092,3.3,3.07,3.3H8.935c1.984,0,3.07-1.176,3.07-3.3a.5.5,0,1,1,.995,0C13,12.325,11.445,14,8.941,14H4.065C1.555,14,0,12.325,0,9.629V4.377C0,1.675,1.555,0,4.065,0H8.935C11.434,0,13,1.675,13,4.377ZM3.224,10.281V5.8a.548.548,0,0,1,.158-.371.471.471,0,0,1,.356-.14.483.483,0,0,1,.347.17.56.56,0,0,1,.133.384v4.476a.515.515,0,0,1-.515.517A.521.521,0,0,1,3.224,10.281Zm2.8-6.557v6.563a.5.5,0,1,0,.995,0V3.725a.5.5,0,1,0-.995,0Zm2.755,6.557V8.188a.5.5,0,1,1,.995,0v2.093a.5.5,0,1,1-.995,0Z" fill="#00162a" opacity="0.6"/>
</svg>

After

Width:  |  Height:  |  Size: 797 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="25" viewBox="0 0 18 25">
<path id="Vector" d="M17.473,5.357H12.6V.523ZM18,7.143V22.321a2.671,2.671,0,0,1-.792,1.893A2.714,2.714,0,0,1,15.3,25H2.7a2.714,2.714,0,0,1-1.908-.785A2.671,2.671,0,0,1,0,22.321V2.679A2.671,2.671,0,0,1,.792.785,2.714,2.714,0,0,1,2.7,0h8.1V6.25a.889.889,0,0,0,.264.631.9.9,0,0,0,.636.262Zm-8.1,12.5a.889.889,0,0,0-.264-.631.905.905,0,0,0-1.273,0,.888.888,0,0,0,0,1.263.905.905,0,0,0,1.273,0A.889.889,0,0,0,9.9,19.643Zm2.644-8.676A3.559,3.559,0,0,0,11.75,9.3a3.613,3.613,0,0,0-6.014.8,3.542,3.542,0,0,0-.337,1.51.889.889,0,0,0,.264.631.905.905,0,0,0,1.273,0,.889.889,0,0,0,.264-.631,1.782,1.782,0,0,1,.652-1.375,1.809,1.809,0,0,1,2.475.165,1.781,1.781,0,0,1-.64,2.861,2.621,2.621,0,0,0-1.167.98A2.59,2.59,0,0,0,8.1,15.7v1.268a.889.889,0,0,0,.264.631.905.905,0,0,0,1.273,0,.889.889,0,0,0,.264-.631V15.7a.834.834,0,0,1,.119-.464.844.844,0,0,1,.356-.324,3.584,3.584,0,0,0,1.789-1.589,3.54,3.54,0,0,0,.38-2.352Z" fill="#ee2727"/>
</svg>

After

Width:  |  Height:  |  Size: 1016 B

View File

@ -0,0 +1,22 @@
import 'package:flutter/material.dart';
const primaryColor = Color(0xFF2697FF);
//const secondaryColor = Color(0xFF2A2D3E);
//const bgColor = Color(0xFF212132);
const secondaryColor = Color(0xFF292929);
const bgColor = Color(0xFF212121);
const darkgreenColor = Color(0xFF2c614f);
const greenColor = Color(0xFF6bab58);
const defaultPadding = 16.0;
const double defaultBorderRadius = 15;
class ColorConstants {
static Color blue = Color(0xFF0D46BB);
}
class Palette {
static const Color background = Color(0xFFEDEEF2);
static const Color wrapperBg = Color(0xFF212121);
}

View File

@ -0,0 +1,22 @@
import 'dart:ui';
import 'package:flutter/material.dart';
Color getRoleColor(String? role) {
if (role == "Doctor") {
return Colors.green;
} else if (role == "Software Architect") {
return Colors.red;
} else if (role == "Software Engineer") {
return Colors.blueAccent;
} else if (role == "Solution Architect") {
return Colors.amberAccent;
} else if (role == "Project Manager") {
return Colors.cyanAccent;
} else if (role == "Business Analyst") {
return Colors.deepPurpleAccent;
} else if (role == "UI/UX Designer") {
return Colors.indigoAccent;
}
return Colors.black38;
}

View File

@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
enum ButtonType { PRIMARY, PLAIN }
class AppButton extends StatelessWidget {
final ButtonType? type;
final VoidCallback? onPressed;
final String? text;
AppButton({this.type, this.onPressed, this.text});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: this.onPressed,
child: Container(
width: double.infinity,
height: 45,
decoration: BoxDecoration(
color: getButtonColor(context, type!),
borderRadius: BorderRadius.circular(4.0),
boxShadow: [
BoxShadow(
//color: Color.fromRGBO(169, 176, 185, 0.42),
//spreadRadius: 0,
//blurRadius: 3.0,
//offset: Offset(0, 2),
)
],
),
child: Center(
child: Text(this.text!,
style: Theme.of(context)
.textTheme
.subtitle1!
.copyWith(color: getTextColor(context, type!))),
),
),
);
}
}
Color getButtonColor(context, ButtonType type) {
switch (type) {
case ButtonType.PRIMARY:
return Theme.of(context).buttonTheme.colorScheme!.background;
case ButtonType.PLAIN:
return Colors.white;
default:
return Theme.of(context).primaryColor;
}
}
Color getTextColor(context, ButtonType type) {
switch (type) {
case ButtonType.PLAIN:
return Theme.of(context).primaryColor;
case ButtonType.PRIMARY:
return Colors.white;
default:
return Theme.of(context).buttonTheme.colorScheme!.background;
}
}

View File

@ -0,0 +1,94 @@
import 'package:flutter/material.dart';
import '../constants/color_constants.dart';
class InputWidget extends StatelessWidget {
final String? hintText;
final String? errorText;
final Widget? prefixIcon;
final double? height;
final String? topLabel;
final bool? obscureText;
final FormFieldSetter<String>? onSaved;
final ValueChanged<String>? onChanged;
final FormFieldValidator<String>? validator;
final TextInputType? keyboardType;
final Key? kKey;
final TextEditingController? kController;
final String? kInitialValue;
InputWidget({
this.hintText,
this.prefixIcon,
this.height = 48.0,
this.topLabel = "",
this.obscureText = false,
required this.onSaved,
this.keyboardType,
this.errorText,
this.onChanged,
this.validator,
this.kKey,
this.kController,
this.kInitialValue,
});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(this.topLabel!),
SizedBox(height: 4.0),
Container(
height: 50,
decoration: BoxDecoration(
color: secondaryColor,
//color: Theme.of(context).buttonColor,
borderRadius: BorderRadius.circular(4.0),
),
child: TextFormField(
initialValue: this.kInitialValue,
controller: this.kController,
key: this.kKey,
keyboardType: this.keyboardType,
onSaved: this.onSaved,
onChanged: this.onChanged,
validator: this.validator,
obscureText: this.obscureText!,
decoration: InputDecoration(
prefixIcon: this.prefixIcon,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Color.fromRGBO(74, 77, 84, 0.2),
),
),
focusedBorder: OutlineInputBorder(
//gapPadding: 16,
borderSide: BorderSide(
color: Theme.of(context).primaryColor,
),
),
errorStyle: TextStyle(height: 0, color: Colors.transparent),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).errorColor,
),
),
focusedErrorBorder: OutlineInputBorder(
//gapPaddings: 16,
borderSide: BorderSide(
color: Theme.of(context).errorColor,
),
),
hintText: this.hintText,
hintStyle: Theme.of(context)
.textTheme
.bodyText1!
.copyWith(color: Colors.white54),
errorText: this.errorText),
),
)
],
);
}
}

View File

@ -0,0 +1,34 @@
import 'package:flutter/material.dart';
import '../constants/color_constants.dart';
class Wrapper extends StatelessWidget {
final Widget? title;
final Widget child;
const Wrapper({Key? key, this.title, required this.child}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(defaultPadding),
decoration: BoxDecoration(
color: Palette.wrapperBg,
borderRadius: BorderRadius.circular(defaultBorderRadius),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (title != null)
Column(
children: [
title!,
const SizedBox(height: defaultPadding),
],
),
child
],
),
);
}
}

31
frontend/lib/main.dart Normal file
View File

@ -0,0 +1,31 @@
import 'package:aurcache/screens/home/home_screen.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'core/constants/color_constants.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Smart Dashboard - Admin Panel v0.1 ',
theme: ThemeData.dark().copyWith(
appBarTheme: const AppBarTheme(backgroundColor: bgColor, elevation: 0),
scaffoldBackgroundColor: bgColor,
primaryColor: greenColor,
dialogBackgroundColor: secondaryColor,
textTheme: GoogleFonts.openSansTextTheme(Theme.of(context).textTheme)
.apply(bodyColor: Colors.white),
canvasColor: secondaryColor,
),
home: const HomeScreen(),
);
}
}

View File

@ -0,0 +1,289 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import '../core/constants/color_constants.dart';
class DailyInfoModel {
IconData? icon;
String? title;
String? totalStorage;
int? volumeData;
int? percentage;
Color? color;
List<Color>? colors;
List<FlSpot>? spots;
DailyInfoModel({
this.icon,
this.title,
this.totalStorage,
this.volumeData,
this.percentage,
this.color,
this.colors,
this.spots,
});
DailyInfoModel.fromJson(Map<String, dynamic> json) {
title = json['title'];
volumeData = json['volumeData'];
icon = json['icon'];
totalStorage = json['totalStorage'];
color = json['color'];
percentage = json['percentage'];
colors = json['colors'];
spots = json['spots'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['title'] = this.title;
data['volumeData'] = this.volumeData;
data['icon'] = this.icon;
data['totalStorage'] = this.totalStorage;
data['color'] = this.color;
data['percentage'] = this.percentage;
data['colors'] = this.colors;
data['spots'] = this.spots;
return data;
}
}
List<DailyInfoModel> dailyDatas =
dailyData.map((item) => DailyInfoModel.fromJson(item)).toList();
//List<FlSpot> spots = yValues.asMap().entries.map((e) {
// return FlSpot(e.key.toDouble(), e.value);
//}).toList();
var dailyData = [
{
"title": "Employee",
"volumeData": 1328,
"icon": Icons.ac_unit,
"totalStorage": "+ %20",
"color": primaryColor,
"percentage": 35,
"colors": [
Color(0xff23b6e6),
Color(0xff02d39a),
],
"spots": [
FlSpot(
1,
2,
),
FlSpot(
2,
1.0,
),
FlSpot(
3,
1.8,
),
FlSpot(
4,
1.5,
),
FlSpot(
5,
1.0,
),
FlSpot(
6,
2.2,
),
FlSpot(
7,
1.8,
),
FlSpot(
8,
1.5,
)
]
},
{
"title": "On Leave",
"volumeData": 1328,
"icon": Icons.ac_unit,
"totalStorage": "+ %5",
"color": Color(0xFFFFA113),
"percentage": 35,
"colors": [Color(0xfff12711), Color(0xfff5af19)],
"spots": [
FlSpot(
1,
1.3,
),
FlSpot(
2,
1.0,
),
FlSpot(
3,
4,
),
FlSpot(
4,
1.5,
),
FlSpot(
5,
1.0,
),
FlSpot(
6,
3,
),
FlSpot(
7,
1.8,
),
FlSpot(
8,
1.5,
)
]
},
{
"title": "Onboarding",
"volumeData": 1328,
"icon": Icons.ac_unit,
"totalStorage": "+ %8",
"color": Color(0xFFA4CDFF),
"percentage": 10,
"colors": [Color(0xff2980B9), Color(0xff6DD5FA)],
"spots": [
FlSpot(
1,
1.3,
),
FlSpot(
2,
5,
),
FlSpot(
3,
1.8,
),
FlSpot(
4,
6,
),
FlSpot(
5,
1.0,
),
FlSpot(
6,
2.2,
),
FlSpot(
7,
1.8,
),
FlSpot(
8,
1,
)
]
},
{
"title": "Open Position",
"volumeData": 1328,
"icon": Icons.ac_unit,
"totalStorage": "+ %8",
"color": Color(0xFFd50000),
"percentage": 10,
"colors": [Color(0xff93291E), Color(0xffED213A)],
"spots": [
FlSpot(
1,
3,
),
FlSpot(
2,
4,
),
FlSpot(
3,
1.8,
),
FlSpot(
4,
1.5,
),
FlSpot(
5,
1.0,
),
FlSpot(
6,
2.2,
),
FlSpot(
7,
1.8,
),
FlSpot(
8,
1.5,
)
]
},
{
"title": "Efficiency",
"volumeData": 5328,
"icon": Icons.ac_unit,
"totalStorage": "- %5",
"color": Color(0xFF00F260),
"percentage": 78,
"colors": [Color(0xff0575E6), Color(0xff00F260)],
"spots": [
FlSpot(
1,
1.3,
),
FlSpot(
2,
1.0,
),
FlSpot(
3,
1.8,
),
FlSpot(
4,
1.5,
),
FlSpot(
5,
1.0,
),
FlSpot(
6,
2.2,
),
FlSpot(
7,
1.8,
),
FlSpot(
8,
1.5,
)
]
}
];
//final List<double> yValues = [
// 2.3,
// 1.8,
// 1.9,
// 1.5,
// 1.0,
// 2.2,
// 1.8,
// 1.5,
//];

View File

@ -0,0 +1,64 @@
class SliderModel {
String? image;
String? text;
String? altText;
String? bAltText;
String? productImage;
int? kBackgroundColor;
SliderModel(this.image, this.text, this.altText, this.bAltText,
this.productImage, this.kBackgroundColor);
SliderModel.fromJson(Map<String, dynamic> json) {
image = json['image'];
kBackgroundColor = json['kBackgroundColor'];
text = json['text'];
altText = json['altText'];
bAltText = json['bAltText'];
productImage = json['productImage'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['image'] = this.image;
data['kBackgroundColor'] = this.kBackgroundColor;
data['text'] = this.text;
data['altText'] = this.altText;
data['bAltText'] = this.bAltText;
data['productImage'] = this.productImage;
return data;
}
}
List<SliderModel> slides =
slideData.map((item) => SliderModel.fromJson(item)).toList();
var slideData = [
{
"image": "assets/slides/background-1.jpeg",
"kBackgroundColor": 0xFF2c614f,
"text": "Welcome to the Smart Smart Admin Dashboard!",
"altText": "You can access & track your services in real-time.",
"bAltText": "Are you ready for the next generation AI supported Dashboard?",
"productImage": "assets/images/mockup.png"
},
{
"image": "assets/slides/background-2.jpeg",
"kBackgroundColor": 0xFF8a1a4c,
"text": "¡Bienvenido al tablero Smart Admin Dashboard!",
"altText": "Puede acceder y rastrear sus servicios en tiempo real.",
"bAltText":
"¿Estás listo para el panel de control impulsado por IA de próxima generación?",
"productImage": "assets/images/mockup-2.png"
},
{
"image": "assets/slides/background-3.jpeg",
"kBackgroundColor": 0xFF0ab3ec,
"text": "Willkommen im Smart Admin Dashboard!",
"altText":
"Sie können in Echtzeit auf Ihre Dienste zugreifen und diese verfolgen.",
"bAltText":
"Sind Sie bereit für das AI-unterstützte Dashboard der nächsten Generation?",
"productImage": "assets/images/mockup-3.png"
}
];

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
class Responsive extends StatelessWidget {
final Widget mobile;
final Widget tablet;
final Widget desktop;
const Responsive({
Key? key,
required this.mobile,
required this.tablet,
required this.desktop,
}) : super(key: key);
// This size work fine on my design, maybe you need some customization depends on your design
// This isMobile, isTablet, isDesktop helep us later
static bool isMobile(BuildContext context) =>
MediaQuery.of(context).size.width < 850;
static bool isTablet(BuildContext context) =>
MediaQuery.of(context).size.width < 1100 &&
MediaQuery.of(context).size.width >= 850;
static bool isDesktop(BuildContext context) =>
MediaQuery.of(context).size.width >= 1100;
@override
Widget build(BuildContext context) {
final Size _size = MediaQuery.of(context).size;
// If our width is more than 1100 then we consider it a desktop
if (_size.width >= 1100) {
return desktop;
}
// If width it less then 1100 and more then 850 we consider it as tablet
else if (_size.width >= 850) {
return tablet;
}
// Or less then that we called it mobile
else {
return mobile;
}
}
}

View File

@ -0,0 +1,95 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
class Chart extends StatefulWidget {
const Chart({
Key? key,
}) : super(key: key);
@override
_ChartState createState() => _ChartState();
}
class _ChartState extends State<Chart> {
int touchedIndex = -1;
@override
Widget build(BuildContext context) {
return SizedBox(
height: 300,
child: AspectRatio(
aspectRatio: 1.3,
child: Row(
children: <Widget>[
const SizedBox(
height: 18,
),
Expanded(
child: AspectRatio(
aspectRatio: 1,
child: PieChart(
PieChartData(
pieTouchData:
PieTouchData(touchCallback: (pieTouchResponse, touchresponse) {
setState(() {
// final desiredTouch = pieTouchResponse.touchInput
// is! PointerExitEvent &&
// pieTouchResponse.touchInput is! PointerUpEvent;
if ( touchresponse?.touchedSection != null) {
touchedIndex = touchresponse!.touchedSection!.touchedSectionIndex;
} else {
touchedIndex = -1;
}
});
}),
borderData: FlBorderData(
show: false,
),
sectionsSpace: 0,
centerSpaceRadius: 40,
sections: showingSections()),
),
),
),
const SizedBox(
width: 28,
),
],
),
),
);
}
List<PieChartSectionData> showingSections() {
return List.generate(2, (i) {
final isTouched = i == touchedIndex;
final fontSize = isTouched ? 25.0 : 16.0;
final radius = isTouched ? 60.0 : 50.0;
switch (i) {
case 0:
return PieChartSectionData(
color: const Color(0xff760707),
value: 40,
title: '28.3%',
radius: radius,
titleStyle: TextStyle(
fontSize: fontSize,
fontWeight: FontWeight.bold,
color: const Color(0xffffffff)),
);
case 1:
return PieChartSectionData(
color: const Color(0xff0a7005),
value: 30,
title: '16.7%',
radius: radius,
titleStyle: TextStyle(
fontSize: fontSize,
fontWeight: FontWeight.bold,
color: const Color(0xffffffff)),
);
default:
throw Error();
}
});
}
}

View File

@ -0,0 +1,117 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import '../../../core/constants/color_constants.dart';
import '../../../responsive.dart';
class Header extends StatelessWidget {
const Header({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
children: [
if (!Responsive.isDesktop(context))
IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
),
if (!Responsive.isMobile(context))
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Hello, Arch User 👋",
style: Theme.of(context).textTheme.headline6,
),
SizedBox(
height: 8,
),
Text(
"Welcome to AURCentral",
style: Theme.of(context).textTheme.subtitle2,
),
],
),
if (!Responsive.isMobile(context))
Spacer(flex: Responsive.isDesktop(context) ? 2 : 1),
Expanded(child: SearchField()),
//ProfileCard()
],
);
}
}
class ProfileCard extends StatelessWidget {
const ProfileCard({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(left: defaultPadding),
padding: EdgeInsets.symmetric(
horizontal: defaultPadding,
vertical: defaultPadding / 2,
),
decoration: BoxDecoration(
color: secondaryColor,
borderRadius: const BorderRadius.all(Radius.circular(10)),
border: Border.all(color: Colors.white10),
),
child: Row(
children: [
CircleAvatar(
backgroundImage: AssetImage("assets/images/profile_pic.png"),
),
if (!Responsive.isMobile(context))
Padding(
padding:
const EdgeInsets.symmetric(horizontal: defaultPadding / 2),
child: Text("Deniz Çolak"),
),
Icon(Icons.keyboard_arrow_down),
],
),
);
}
}
class SearchField extends StatelessWidget {
const SearchField({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return TextField(
decoration: InputDecoration(
hintText: "Search",
fillColor: secondaryColor,
filled: true,
border: OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: const BorderRadius.all(Radius.circular(10)),
),
suffixIcon: InkWell(
onTap: () {},
child: Container(
padding: EdgeInsets.all(defaultPadding * 0.75),
margin: EdgeInsets.symmetric(horizontal: defaultPadding / 2),
decoration: BoxDecoration(
color: greenColor,
borderRadius: const BorderRadius.all(Radius.circular(10)),
),
child: SvgPicture.asset(
"assets/icons/Search.svg",
),
),
),
),
);
}
}

View File

@ -0,0 +1,84 @@
import 'package:flutter/material.dart';
import '../../../core/constants/color_constants.dart';
import '../../../models/daily_info_model.dart';
import '../../../responsive.dart';
import 'mini_information_widget.dart';
class MiniInformation extends StatelessWidget {
const MiniInformation({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final Size _size = MediaQuery.of(context).size;
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: 10,
),
ElevatedButton.icon(
style: TextButton.styleFrom(
backgroundColor: Colors.green,
padding: EdgeInsets.symmetric(
horizontal: defaultPadding * 1.5,
vertical:
defaultPadding / (Responsive.isMobile(context) ? 2 : 1),
),
),
onPressed: () {
},
icon: Icon(Icons.add),
label: Text(
"Add New",
),
),
],
),
SizedBox(height: defaultPadding),
Responsive(
mobile: InformationCard(
crossAxisCount: _size.width < 650 ? 2 : 4,
childAspectRatio: _size.width < 650 ? 1.2 : 1,
),
tablet: InformationCard(),
desktop: InformationCard(
childAspectRatio: _size.width < 1400 ? 1.2 : 1.4,
),
),
],
);
}
}
class InformationCard extends StatelessWidget {
const InformationCard({
Key? key,
this.crossAxisCount = 5,
this.childAspectRatio = 1,
}) : super(key: key);
final int crossAxisCount;
final double childAspectRatio;
@override
Widget build(BuildContext context) {
return GridView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: dailyDatas.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
crossAxisSpacing: defaultPadding,
mainAxisSpacing: defaultPadding,
childAspectRatio: childAspectRatio,
),
itemBuilder: (context, index) =>
MiniInformationWidget(dailyData: dailyDatas[index]),
);
}
}

View File

@ -0,0 +1,206 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import '../../../core/constants/color_constants.dart';
import '../../../models/daily_info_model.dart';
class MiniInformationWidget extends StatefulWidget {
const MiniInformationWidget({
Key? key,
required this.dailyData,
}) : super(key: key);
final DailyInfoModel dailyData;
@override
_MiniInformationWidgetState createState() => _MiniInformationWidgetState();
}
int _value = 1;
class _MiniInformationWidgetState extends State<MiniInformationWidget> {
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(defaultPadding),
decoration: BoxDecoration(
color: secondaryColor,
borderRadius: const BorderRadius.all(Radius.circular(10)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
padding: EdgeInsets.all(defaultPadding * 0.75),
height: 40,
width: 40,
decoration: BoxDecoration(
color: widget.dailyData.color!.withOpacity(0.1),
borderRadius: const BorderRadius.all(Radius.circular(10)),
),
child: Icon(
widget.dailyData.icon,
color: widget.dailyData.color,
size: 18,
),
),
Padding(
padding: EdgeInsets.only(right: 12.0),
child: DropdownButton(
icon: Icon(Icons.more_vert, size: 18),
underline: SizedBox(),
style: Theme.of(context).textTheme.button,
value: _value,
items: [
DropdownMenuItem(
child: Text("Daily"),
value: 1,
),
DropdownMenuItem(
child: Text("Weekly"),
value: 2,
),
DropdownMenuItem(
child: Text("Monthly"),
value: 3,
),
],
onChanged: (int? value) {
setState(() {
_value = value!;
});
},
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
widget.dailyData.title!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
SizedBox(
height: 8,
),
Container(
child: LineChartWidget(
colors: widget.dailyData.colors,
spotsData: widget.dailyData.spots,
),
)
],
),
SizedBox(
height: 8,
),
ProgressLine(
color: widget.dailyData.color!,
percentage: widget.dailyData.percentage!,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"${widget.dailyData.volumeData}",
style: Theme.of(context)
.textTheme
.caption!
.copyWith(color: Colors.white70),
),
Text(
widget.dailyData.totalStorage!,
style: Theme.of(context)
.textTheme
.caption!
.copyWith(color: Colors.white),
),
],
)
],
),
);
}
}
class LineChartWidget extends StatelessWidget {
const LineChartWidget({
Key? key,
required this.colors,
required this.spotsData,
}) : super(key: key);
final List<Color>? colors;
final List<FlSpot>? spotsData;
@override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
width: 80,
height: 30,
child: LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
spots: spotsData!,
belowBarData: BarAreaData(show: false),
aboveBarData: BarAreaData(show: false),
isCurved: true,
dotData: FlDotData(show: false),
//colors: colors,
barWidth: 3),
],
lineTouchData: LineTouchData(enabled: false),
titlesData: FlTitlesData(show: false),
//axisTitleData: FlAxisTitleData(show: false),
gridData: FlGridData(show: false),
borderData: FlBorderData(show: false)),
),
),
],
);
}
}
class ProgressLine extends StatelessWidget {
const ProgressLine({
Key? key,
this.color = primaryColor,
required this.percentage,
}) : super(key: key);
final Color color;
final int percentage;
@override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
width: double.infinity,
height: 5,
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.all(Radius.circular(10)),
),
),
LayoutBuilder(
builder: (context, constraints) => Container(
width: constraints.maxWidth * (percentage / 100),
height: 5,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
),
),
],
);
}
}

View File

@ -0,0 +1,65 @@
import 'package:flutter/material.dart';
import '../../../core/constants/color_constants.dart';
class RecentBuilds extends StatelessWidget {
const RecentBuilds({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(defaultPadding),
decoration: BoxDecoration(
color: secondaryColor,
borderRadius: const BorderRadius.all(Radius.circular(10)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Recent Builds",
style: Theme.of(context).textTheme.subtitle1,
),
SizedBox(
width: double.infinity,
child: DataTable(
horizontalMargin: 0,
columnSpacing: defaultPadding,
columns: [
DataColumn(
label: Text("Build ID"),
),
DataColumn(
label: Text("Package Name"),
),
DataColumn(
label: Text("Version"),
),
DataColumn(
label: Text("Status"),
),
],
rows: List.generate(
7,
(index) => recentUserDataRow(),
),
),
),
],
),
);
}
DataRow recentUserDataRow() {
return DataRow(
cells: [
DataCell(Text("1")),
DataCell(Text("Resources")),
DataCell(Text("v1.2.3")),
DataCell(Icon(Icons.watch_later_outlined, color: Color(0xFF9D8D00),)),
],
);
}
}

View File

@ -0,0 +1,91 @@
import 'package:flutter/material.dart';
import '../../../core/constants/color_constants.dart';
class RecentUsers extends StatelessWidget {
const RecentUsers({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(defaultPadding),
decoration: BoxDecoration(
color: secondaryColor,
borderRadius: const BorderRadius.all(Radius.circular(10)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Your Packages",
style: Theme.of(context).textTheme.subtitle1,
),
SingleChildScrollView(
//scrollDirection: Axis.horizontal,
child: SizedBox(
width: double.infinity,
child: DataTable(
horizontalMargin: 0,
columnSpacing: defaultPadding,
columns: [
DataColumn(
label: Text("Package ID"),
),
DataColumn(
label: Text("Package Name"),
),
DataColumn(
label: Text("Number of versions"),
),
DataColumn(
label: Text("Status"),
),
DataColumn(
label: Text("Action"),
),
],
rows: List.generate(
7,
(index) => recentUserDataRow(context),
),
),
),
),
],
),
);
}
}
DataRow recentUserDataRow(BuildContext context) {
return DataRow(
cells: [
DataCell(Text("1")),
DataCell(Text("Resources")),
DataCell(Text("2")),
DataCell(Icon(Icons.watch_later_outlined, color: Color(0xFF9D8D00),)),
DataCell(
Row(
children: [
TextButton(
child: Text('View', style: TextStyle(color: greenColor)),
onPressed: () {},
),
SizedBox(
width: 6,
),
TextButton(
child: Text("Delete", style: TextStyle(color: Colors.redAccent)),
onPressed: () {
},
// Delete
),
],
),
),
],
);
}

View File

@ -0,0 +1,64 @@
import 'package:flutter/material.dart';
import '../../../core/constants/color_constants.dart';
class UserDetailsMiniCard extends StatelessWidget {
const UserDetailsMiniCard({
Key? key,
required this.title,
required this.color,
required this.amountOfFiles,
required this.numberOfIncrease,
}) : super(key: key);
final Color color;
final String title, amountOfFiles;
final int numberOfIncrease;
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(top: defaultPadding),
padding: EdgeInsets.all(defaultPadding),
decoration: BoxDecoration(
border: Border.all(width: 2, color: primaryColor.withOpacity(0.15)),
borderRadius: const BorderRadius.all(
Radius.circular(defaultPadding),
),
),
child: Row(
children: [
SizedBox(
height: 20,
width: 20,
child: Container(
color: color,
)),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: defaultPadding),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
Text(
"$numberOfIncrease",
style: Theme.of(context)
.textTheme
.caption!
.copyWith(color: Colors.white70),
),
],
),
),
),
Text(amountOfFiles)
],
),
);
}
}

View File

@ -0,0 +1,48 @@
import 'package:aurcache/screens/dashboard/components/user_details_mini_card.dart';
import 'package:flutter/material.dart';
import '../../../core/constants/color_constants.dart';
import 'charts.dart';
class UserDetailsWidget extends StatelessWidget {
const UserDetailsWidget({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(defaultPadding),
decoration: BoxDecoration(
color: secondaryColor,
borderRadius: const BorderRadius.all(Radius.circular(10)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Package build success",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
),
),
SizedBox(height: defaultPadding),
Chart(),
UserDetailsMiniCard(
color: const Color(0xff0a7005),
title: "Successful Builds",
amountOfFiles: "%16.7",
numberOfIncrease: 1328,
),
UserDetailsMiniCard(
color: const Color(0xff760707),
title: "Failed Builds",
amountOfFiles: "%28.3",
numberOfIncrease: 1328,
),
],
),
);
}
}

View File

@ -0,0 +1,57 @@
import 'package:flutter/material.dart';
import '../../core/constants/color_constants.dart';
import '../../responsive.dart';
import 'components/header.dart';
import 'components/mini_information_card.dart';
import 'components/recent_builds.dart';
import 'components/recent_users.dart';
import 'components/user_details_widget.dart';
class DashboardScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SafeArea(
child: SingleChildScrollView(
//padding: EdgeInsets.all(defaultPadding),
child: Container(
padding: EdgeInsets.all(defaultPadding),
child: Column(
children: [
Header(),
SizedBox(height: defaultPadding),
MiniInformation(),
SizedBox(height: defaultPadding),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 5,
child: Column(
children: [
RecentUsers(),
SizedBox(height: defaultPadding),
RecentBuilds(),
if (Responsive.isMobile(context))
SizedBox(height: defaultPadding),
if (Responsive.isMobile(context)) UserDetailsWidget(),
],
),
),
if (!Responsive.isMobile(context))
SizedBox(width: defaultPadding),
// On Mobile means if the screen is less than 850 we dont want to show it
if (!Responsive.isMobile(context))
Expanded(
flex: 2,
child: UserDetailsWidget(),
),
],
)
],
),
),
),
);
}
}

View File

@ -0,0 +1,90 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import '../../../core/constants/color_constants.dart';
class SideMenu extends StatelessWidget {
const SideMenu({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Drawer(
child: SingleChildScrollView(
// it enables scrolling
child: Column(
children: [
DrawerHeader(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// SizedBox(
// height: defaultPadding * 3,
// ),
// Image.asset(
// "assets/logo/logo_icon.png",
// scale: 5,
// ),
SizedBox(
height: defaultPadding,
),
Text("AUR Build Server")
],
)),
DrawerListTile(
title: "Dashboard",
svgSrc: "assets/icons/menu_dashbord.svg",
press: () {},
),
DrawerListTile(
title: "Builds",
svgSrc: "assets/icons/menu_tran.svg",
press: () {},
),
DrawerListTile(
title: "AUR",
svgSrc: "assets/icons/menu_task.svg",
press: () {},
),
DrawerListTile(
title: "Settings",
svgSrc: "assets/icons/menu_setting.svg",
press: () {},
),
],
),
),
);
}
}
class DrawerListTile extends StatelessWidget {
const DrawerListTile({
Key? key,
// For selecting those three line once press "Command+D"
required this.title,
required this.svgSrc,
required this.press,
}) : super(key: key);
final String title, svgSrc;
final VoidCallback press;
@override
Widget build(BuildContext context) {
return ListTile(
onTap: press,
horizontalTitleGap: 0.0,
leading: SvgPicture.asset(
svgSrc,
color: Colors.white54,
height: 16,
),
title: Text(
title,
style: TextStyle(color: Colors.white54),
),
);
}
}

View File

@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
import '../../responsive.dart';
import '../dashboard/dashboard_screen.dart';
import 'components/side_menu.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: const SideMenu(),
body: SafeArea(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// We want this side menu only for large screen
if (Responsive.isDesktop(context))
const Expanded(
// default flex = 1
// and it takes 1/6 part of the screen
child: SideMenu(),
),
Expanded(
// It takes 5/6 part of the screen
flex: 5,
child: DashboardScreen(),
),
],
),
),
);
}
}

1
frontend/linux/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
flutter/ephemeral

View File

@ -0,0 +1,145 @@
# Project-level configuration.
cmake_minimum_required(VERSION 3.10)
project(runner LANGUAGES CXX)
# The name of the executable created for the application. Change this to change
# the on-disk name of your application.
set(BINARY_NAME "aurcache")
# The unique GTK application identifier for this application. See:
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
set(APPLICATION_ID "eu.heili.aurcentral.aurcache")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake.
cmake_policy(SET CMP0063 NEW)
# Load bundled libraries from the lib/ directory relative to the binary.
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
# Root filesystem for cross-building.
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()
# Define build configuration options.
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Debug" CACHE
STRING "Flutter build mode" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Profile" "Release")
endif()
# Compilation settings that should be applied to most targets.
#
# Be cautious about adding new options here, as plugins use this function by
# default. In most cases, you should add new options to specific targets instead
# of modifying this function.
function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_14)
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
endfunction()
# Flutter library and tool build rules.
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
add_subdirectory(${FLUTTER_MANAGED_DIR})
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
# Define the application target. To change its name, change BINARY_NAME above,
# not the value here, or `flutter run` will no longer work.
#
# Any new source files that you add to the application should be added here.
add_executable(${BINARY_NAME}
"main.cc"
"my_application.cc"
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
)
# Apply the standard set of build settings. This can be removed for applications
# that need different build settings.
apply_standard_settings(${BINARY_NAME})
# Add dependency libraries. Add any application-specific dependencies here.
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
# Run the Flutter tool portions of the build. This must not be removed.
add_dependencies(${BINARY_NAME} flutter_assemble)
# Only the install-generated bundle's copy of the executable will launch
# correctly, since the resources must in the right relative locations. To avoid
# people trying to run the unbundled copy, put it in a subdirectory instead of
# the default top-level location.
set_target_properties(${BINARY_NAME}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
)
# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
include(flutter/generated_plugins.cmake)
# === Installation ===
# By default, "installing" just makes a relocatable bundle in the build
# directory.
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
endif()
# Start with a clean build bundle directory every time.
install(CODE "
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
" COMPONENT Runtime)
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
COMPONENT Runtime)
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
COMPONENT Runtime)
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
install(FILES "${bundled_library}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endforeach(bundled_library)
# Copy the native assets provided by the build.dart from all packages.
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
# Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
install(CODE "
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
" COMPONENT Runtime)
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
# Install the AOT library on non-Debug builds only.
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endif()

View File

@ -0,0 +1,88 @@
# This file controls Flutter-level build steps. It should not be edited.
cmake_minimum_required(VERSION 3.10)
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
# Configuration provided via flutter tool.
include(${EPHEMERAL_DIR}/generated_config.cmake)
# TODO: Move the rest of this into files in ephemeral. See
# https://github.com/flutter/flutter/issues/57146.
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
# which isn't available in 3.10.
function(list_prepend LIST_NAME PREFIX)
set(NEW_LIST "")
foreach(element ${${LIST_NAME}})
list(APPEND NEW_LIST "${PREFIX}${element}")
endforeach(element)
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
endfunction()
# === Flutter Library ===
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
# Published to parent scope for install step.
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
list(APPEND FLUTTER_LIBRARY_HEADERS
"fl_basic_message_channel.h"
"fl_binary_codec.h"
"fl_binary_messenger.h"
"fl_dart_project.h"
"fl_engine.h"
"fl_json_message_codec.h"
"fl_json_method_codec.h"
"fl_message_codec.h"
"fl_method_call.h"
"fl_method_channel.h"
"fl_method_codec.h"
"fl_method_response.h"
"fl_plugin_registrar.h"
"fl_plugin_registry.h"
"fl_standard_message_codec.h"
"fl_standard_method_codec.h"
"fl_string_codec.h"
"fl_value.h"
"fl_view.h"
"flutter_linux.h"
)
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
add_library(flutter INTERFACE)
target_include_directories(flutter INTERFACE
"${EPHEMERAL_DIR}"
)
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
target_link_libraries(flutter INTERFACE
PkgConfig::GTK
PkgConfig::GLIB
PkgConfig::GIO
)
add_dependencies(flutter flutter_assemble)
# === Flutter tool backend ===
# _phony_ is a non-existent file to force this command to run every time,
# since currently there's no way to get a full input/output list from the
# flutter tool.
add_custom_command(
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
${CMAKE_CURRENT_BINARY_DIR}/_phony_
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
VERBATIM
)
add_custom_target(flutter_assemble DEPENDS
"${FLUTTER_LIBRARY}"
${FLUTTER_LIBRARY_HEADERS}
)

View File

@ -0,0 +1,11 @@
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
void fl_register_plugins(FlPluginRegistry* registry) {
}

View File

@ -0,0 +1,15 @@
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter_linux/flutter_linux.h>
// Registers Flutter plugins.
void fl_register_plugins(FlPluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_

View File

@ -0,0 +1,23 @@
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)

6
frontend/linux/main.cc Normal file
View File

@ -0,0 +1,6 @@
#include "my_application.h"
int main(int argc, char** argv) {
g_autoptr(MyApplication) app = my_application_new();
return g_application_run(G_APPLICATION(app), argc, argv);
}

View File

@ -0,0 +1,104 @@
#include "my_application.h"
#include <flutter_linux/flutter_linux.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#include "flutter/generated_plugin_registrant.h"
struct _MyApplication {
GtkApplication parent_instance;
char** dart_entrypoint_arguments;
};
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
// Implements GApplication::activate.
static void my_application_activate(GApplication* application) {
MyApplication* self = MY_APPLICATION(application);
GtkWindow* window =
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
// Use a header bar when running in GNOME as this is the common style used
// by applications and is the setup most users will be using (e.g. Ubuntu
// desktop).
// If running on X and not using GNOME then just use a traditional title bar
// in case the window manager does more exotic layout, e.g. tiling.
// If running on Wayland assume the header bar will work (may need changing
// if future cases occur).
gboolean use_header_bar = TRUE;
#ifdef GDK_WINDOWING_X11
GdkScreen* screen = gtk_window_get_screen(window);
if (GDK_IS_X11_SCREEN(screen)) {
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
use_header_bar = FALSE;
}
}
#endif
if (use_header_bar) {
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
gtk_widget_show(GTK_WIDGET(header_bar));
gtk_header_bar_set_title(header_bar, "aurcache");
gtk_header_bar_set_show_close_button(header_bar, TRUE);
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
} else {
gtk_window_set_title(window, "aurcache");
}
gtk_window_set_default_size(window, 1280, 720);
gtk_widget_show(GTK_WIDGET(window));
g_autoptr(FlDartProject) project = fl_dart_project_new();
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
FlView* view = fl_view_new(project);
gtk_widget_show(GTK_WIDGET(view));
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
gtk_widget_grab_focus(GTK_WIDGET(view));
}
// Implements GApplication::local_command_line.
static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
MyApplication* self = MY_APPLICATION(application);
// Strip out the first argument as it is the binary name.
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
g_autoptr(GError) error = nullptr;
if (!g_application_register(application, nullptr, &error)) {
g_warning("Failed to register: %s", error->message);
*exit_status = 1;
return TRUE;
}
g_application_activate(application);
*exit_status = 0;
return TRUE;
}
// Implements GObject::dispose.
static void my_application_dispose(GObject* object) {
MyApplication* self = MY_APPLICATION(object);
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
}
static void my_application_class_init(MyApplicationClass* klass) {
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
}
static void my_application_init(MyApplication* self) {}
MyApplication* my_application_new() {
return MY_APPLICATION(g_object_new(my_application_get_type(),
"application-id", APPLICATION_ID,
"flags", G_APPLICATION_NON_UNIQUE,
nullptr));
}

View File

@ -0,0 +1,18 @@
#ifndef FLUTTER_MY_APPLICATION_H_
#define FLUTTER_MY_APPLICATION_H_
#include <gtk/gtk.h>
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
GtkApplication)
/**
* my_application_new:
*
* Creates a new Flutter-based application.
*
* Returns: a new #MyApplication.
*/
MyApplication* my_application_new();
#endif // FLUTTER_MY_APPLICATION_H_

397
frontend/pubspec.lock Normal file
View File

@ -0,0 +1,397 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
args:
dependency: transitive
description:
name: args
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
url: "https://pub.dev"
source: hosted
version: "2.4.2"
async:
dependency: transitive
description:
name: async
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.dev"
source: hosted
version: "2.11.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
characters:
dependency: transitive
description:
name: characters
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
url: "https://pub.dev"
source: hosted
version: "1.3.0"
clock:
dependency: transitive
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
url: "https://pub.dev"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.dev"
source: hosted
version: "1.18.0"
crypto:
dependency: transitive
description:
name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
url: "https://pub.dev"
source: hosted
version: "3.0.3"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
url: "https://pub.dev"
source: hosted
version: "1.0.6"
equatable:
dependency: transitive
description:
name: equatable
sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
url: "https://pub.dev"
source: hosted
version: "2.0.5"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
url: "https://pub.dev"
source: hosted
version: "1.3.1"
ffi:
dependency: transitive
description:
name: ffi
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
fl_chart:
dependency: "direct main"
description:
name: fl_chart
sha256: fe6fec7d85975a99c73b9515a69a6e291364accfa0e4a5b3ce6de814d74b9a1c
url: "https://pub.dev"
source: hosted
version: "0.66.0"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
url: "https://pub.dev"
source: hosted
version: "2.0.3"
flutter_svg:
dependency: "direct main"
description:
name: flutter_svg
sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c
url: "https://pub.dev"
source: hosted
version: "2.0.9"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
google_fonts:
dependency: "direct main"
description:
name: google_fonts
sha256: f0b8d115a13ecf827013ec9fc883390ccc0e87a96ed5347a3114cac177ef18e8
url: "https://pub.dev"
source: hosted
version: "6.1.0"
http:
dependency: transitive
description:
name: http
sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139
url: "https://pub.dev"
source: hosted
version: "1.1.2"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
lints:
dependency: transitive
description:
name: lints
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
matcher:
dependency: transitive
description:
name: matcher
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev"
source: hosted
version: "0.12.16"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev"
source: hosted
version: "0.5.0"
meta:
dependency: transitive
description:
name: meta
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
url: "https://pub.dev"
source: hosted
version: "1.10.0"
path:
dependency: transitive
description:
name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
url: "https://pub.dev"
source: hosted
version: "1.8.3"
path_parsing:
dependency: transitive
description:
name: path_parsing
sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
url: "https://pub.dev"
source: hosted
version: "1.0.1"
path_provider:
dependency: transitive
description:
name: path_provider
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
url: "https://pub.dev"
source: hosted
version: "2.1.1"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
url: "https://pub.dev"
source: hosted
version: "2.2.2"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
url: "https://pub.dev"
source: hosted
version: "2.3.1"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.dev"
source: hosted
version: "2.2.1"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
url: "https://pub.dev"
source: hosted
version: "6.0.2"
platform:
dependency: transitive
description:
name: platform
sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59"
url: "https://pub.dev"
source: hosted
version: "3.1.3"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8
url: "https://pub.dev"
source: hosted
version: "2.1.7"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_span:
dependency: transitive
description:
name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev"
source: hosted
version: "1.10.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
url: "https://pub.dev"
source: hosted
version: "1.11.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
url: "https://pub.dev"
source: hosted
version: "2.1.2"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
url: "https://pub.dev"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
url: "https://pub.dev"
source: hosted
version: "0.6.1"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
url: "https://pub.dev"
source: hosted
version: "1.3.2"
vector_graphics:
dependency: transitive
description:
name: vector_graphics
sha256: "0f0c746dd2d6254a0057218ff980fc7f5670fd0fcf5e4db38a490d31eed4ad43"
url: "https://pub.dev"
source: hosted
version: "1.1.9+1"
vector_graphics_codec:
dependency: transitive
description:
name: vector_graphics_codec
sha256: "0edf6d630d1bfd5589114138ed8fada3234deacc37966bec033d3047c29248b7"
url: "https://pub.dev"
source: hosted
version: "1.1.9+1"
vector_graphics_compiler:
dependency: transitive
description:
name: vector_graphics_compiler
sha256: d24333727332d9bd20990f1483af4e09abdb9b1fc7c3db940b56ab5c42790c26
url: "https://pub.dev"
source: hosted
version: "1.1.9+1"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
web:
dependency: transitive
description:
name: web
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
url: "https://pub.dev"
source: hosted
version: "0.3.0"
win32:
dependency: transitive
description:
name: win32
sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574
url: "https://pub.dev"
source: hosted
version: "5.1.1"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
url: "https://pub.dev"
source: hosted
version: "1.0.3"
xml:
dependency: transitive
description:
name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev"
source: hosted
version: "6.5.0"
sdks:
dart: ">=3.2.3 <4.0.0"
flutter: ">=3.16.0"

99
frontend/pubspec.yaml Normal file
View File

@ -0,0 +1,99 @@
name: aurcache
description: "A new Flutter project."
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1
environment:
sdk: '>=3.2.3 <4.0.0'
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
fl_chart: ^0.66.0
# flutter_icons:
# git:
# url: https://github.com/DaveatCor/flutter_icons_fork.git
# branch: master
flutter_svg: ^2.0.9
google_fonts: ^6.1.0
dev_dependencies:
flutter_test:
sdk: flutter
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^2.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
assets:
- assets/icons/
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages

View File

@ -0,0 +1,30 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:aurcache/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MyApp());
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}

BIN
frontend/web/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

59
frontend/web/index.html Normal file
View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<!--
If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from.
The path provided below has to start and end with a slash "/" in order for
it to work correctly.
For more details:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
This is a placeholder for base href that will be replaced by the value of
the `--base-href` argument provided to `flutter build`.
-->
<base href="$FLUTTER_BASE_HREF">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project.">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="aurcache">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>
<title>aurcache</title>
<link rel="manifest" href="manifest.json">
<script>
// The value below is injected by flutter build, do not touch.
const serviceWorkerVersion = null;
</script>
<!-- This script adds the flutter initialization JS code -->
<script src="flutter.js" defer></script>
</head>
<body>
<script>
window.addEventListener('load', function(ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
},
onEntrypointLoaded: function(engineInitializer) {
engineInitializer.initializeEngine().then(function(appRunner) {
appRunner.runApp();
});
}
});
});
</script>
</body>
</html>

View File

@ -0,0 +1,35 @@
{
"name": "aurcache",
"short_name": "aurcache",
"start_url": ".",
"display": "standalone",
"background_color": "#0175C2",
"theme_color": "#0175C2",
"description": "A new Flutter project.",
"orientation": "portrait-primary",
"prefer_related_applications": false,
"icons": [
{
"src": "icons/Icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/Icon-512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "icons/Icon-maskable-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icons/Icon-maskable-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
]
}