diff --git a/lib/components/point_header.dart b/lib/components/point_header.dart new file mode 100644 index 0000000..d2f4eb1 --- /dev/null +++ b/lib/components/point_header.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:freekake/providers/point_provider.dart'; +import 'package:provider/provider.dart'; + +class PointsHeader extends StatelessWidget { + @override + Widget build(BuildContext context) { + final points = context.watch().points; + + return Container( + padding: EdgeInsets.all(12), + color: const Color.fromARGB(99, 255, 255, 255), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Text( + "Activity", //${points.xp}/${points.xpToNextLevel()}", + style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), + ), + Text( + "", + // "🔥 Level: ${points.level}", + // style: TextStyle(color: Colors.orangeAccent), + ), + Text( + "🏆", + // "💎 GP: ${points.gp}", + style: TextStyle(color: Colors.lightBlue), + ), + Text( + "🟡", + // "🎯" SP: ${points.sp}", + style: TextStyle(color: Colors.greenAccent), + ), + ], + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index caeca33..83003bf 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:freekake/providers/character_provider.dart'; import 'package:freekake/providers/menu_selection_provider.dart'; +import 'package:freekake/providers/point_provider.dart'; import 'package:freekake/screen/Home_screen.dart'; import 'package:provider/provider.dart'; @@ -27,6 +28,7 @@ class MyApp extends StatelessWidget { providers: [ ChangeNotifierProvider(create: (context) => CharacterProvider()), ChangeNotifierProvider(create: (context) => MenuSelectionProvider()), + ChangeNotifierProvider(create: (_) => PointsProvider()), ], child: MaterialApp( debugShowCheckedModeBanner: false, diff --git a/lib/providers/point_provider.dart b/lib/providers/point_provider.dart new file mode 100644 index 0000000..1fbece8 --- /dev/null +++ b/lib/providers/point_provider.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:freekake/util/player_point.dart'; + +class PointsProvider with ChangeNotifier { + PlayerPoints _points = PlayerPoints(xp: 0, gp: 0, sp: 0, level: 1); + + PlayerPoints get points => _points; + + void gainXP(int value) { + _points.addXP(value); + notifyListeners(); + } + + void gainGP(int value) { + _points.addGP(value); + notifyListeners(); + } + + void gainSP(int value) { + _points.addSP(value); + notifyListeners(); + } +} diff --git a/lib/screen/Home_screen.dart b/lib/screen/Home_screen.dart index f49b5e7..df55393 100644 --- a/lib/screen/Home_screen.dart +++ b/lib/screen/Home_screen.dart @@ -77,8 +77,8 @@ class _HomeScreenState extends State { child: DropdownButtonHideUnderline( child: DropdownButton2( customButton: Container( - height: 50, - width: 50, + height: 100, + width: 100, decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), image: const DecorationImage( @@ -173,14 +173,14 @@ class _HomeScreenState extends State { ), ], ), - child: Text( - "Halo....Jotaslim", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Color(0xFF000000), - ), - ), + // child: Text( + // "Halo....Jotaslim", + // style: TextStyle( + // fontSize: 12, + // fontWeight: FontWeight.bold, + // color: Color(0xFF000000), + // ), + // ), ), SizedBox(height: 10), setHomeImage("assets/images/cepott.png", 300), @@ -223,9 +223,12 @@ class _HomeScreenState extends State { class _MenuItems { static const List firstItems = [like, share, download]; static const List secondItems = [cancel]; - static const like = MenuItem(text: 'Like', icon: Icons.favorite); - static const share = MenuItem(text: 'Share', icon: Icons.share); - static const download = MenuItem(text: 'Download', icon: Icons.download); + static const like = MenuItem(text: 'Hello', icon: Icons.favorite); + static const share = MenuItem(text: 'Furikake', icon: Icons.share); + static const download = MenuItem( + text: 'Makanan Bergizi', + icon: Icons.download, + ); static const cancel = MenuItem(text: 'Cancel', icon: Icons.cancel); static Widget buildItem(MenuItem item) { diff --git a/lib/screen/saya/akun_saya.dart b/lib/screen/saya/akun_saya.dart index 8eda900..9b414fc 100644 --- a/lib/screen/saya/akun_saya.dart +++ b/lib/screen/saya/akun_saya.dart @@ -125,16 +125,15 @@ class _AkunSayaState extends State { style: TextStyle(color: Colors.black), ), - TextFormField( - initialValue: "Jl. Sentosa jaya", - decoration: const InputDecoration( - border: UnderlineInputBorder(), - labelText: 'Alamat', - labelStyle: TextStyle(color: Colors.black), - ), - style: TextStyle(color: Colors.black), - ), - + // TextFormField( + // initialValue: "Jl. Sentosa jaya", + // decoration: const InputDecoration( + // border: UnderlineInputBorder(), + // labelText: 'Alamat', + // labelStyle: TextStyle(color: Colors.black), + // ), + // style: TextStyle(color: Colors.black), + // ), TextFormField( initialValue: "******", decoration: const InputDecoration( @@ -144,15 +143,6 @@ class _AkunSayaState extends State { ), style: TextStyle(color: Colors.black), ), - TextFormField( - initialValue: "+62923", - decoration: const InputDecoration( - border: UnderlineInputBorder(), - labelText: 'No. HP', - labelStyle: TextStyle(color: Colors.black), - ), - style: TextStyle(color: Colors.black), - ), ], ), ), diff --git a/lib/screen/saya/data_saya.dart b/lib/screen/saya/data_saya.dart new file mode 100644 index 0000000..d5dda1e --- /dev/null +++ b/lib/screen/saya/data_saya.dart @@ -0,0 +1,260 @@ +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:freekake/components/bottom_navbar.dart'; +import 'package:freekake/components/main_menu.dart'; +import 'package:freekake/components/scan_button.dart'; +import 'package:image_picker/image_picker.dart'; +import 'dart:io'; + +// import 'package:image_picker_web/image_picker_web.dart'; +import 'package:flutter/foundation.dart' show kIsWeb; + +class DataSaya extends StatefulWidget { + const DataSaya({super.key}); + + @override + _DataSayaState createState() => _DataSayaState(); +} + +class _DataSayaState extends State { + dynamic _profileImage; + dynamic _headerImage; + ImageProvider? imageProvider; + + final ImagePicker _picker = ImagePicker(); + + Future _pickImage(bool isProfile) async { + if (kIsWeb) { + // Uint8List? bytesFromPicker = await ImagePickerWeb.getImageAsBytes(); + // if (bytesFromPicker != null) { + // setState(() { + // if (isProfile) { + // _profileImage = bytesFromPicker; + // } else { + // _headerImage = bytesFromPicker; + // } + // }); + // } + } else { + final pickedFile = await _picker.pickImage(source: ImageSource.gallery); + if (pickedFile != null) { + final imageFile = File(pickedFile.path); + setState(() { + if (isProfile) { + _profileImage = imageFile; + } else { + _headerImage = imageFile; + } + + imageProvider = + kIsWeb ? MemoryImage(_profileImage) : FileImage(_profileImage); + }); + } else { + imageProvider = AssetImage("assets/images/luffy.png"); + } + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Data Pribadi"), + backgroundColor: Color.fromARGB(225, 79, 76, 182), + ), + resizeToAvoidBottomInset: false, + backgroundColor: const Color.fromARGB(255, 255, 255, 255), + body: Stack( + children: [ + Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.only(top: 0.0, left: 20, right: 20), + child: Container( + height: MediaQuery.of(context).size.height * 0.7, + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + color: const Color.fromARGB(255, 212, 211, 208), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ), + ), + ), + ), + ), + Column( + children: [ + SizedBox( + height: 80, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(40), + bottomRight: Radius.circular(40), + ), + color: Color.fromARGB(225, 79, 76, 182), + ), + ), + ), + SizedBox(height: 70), + Expanded( + child: Padding( + padding: EdgeInsets.all(20), + child: ListView( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 40), + children: [ + TextFormField( + initialValue: "Hasan", + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: 'Nama Siswa', + labelStyle: TextStyle(color: Colors.black), + ), + style: TextStyle(color: Colors.black), + ), + TextFormField( + initialValue: "Jawa Barat", + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: 'Provinsi', + labelStyle: TextStyle(color: Colors.black), + ), + style: TextStyle(color: Colors.black), + ), + + TextFormField( + initialValue: "Bandung", + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: 'Kabupaten', + labelStyle: TextStyle(color: Colors.black), + ), + style: TextStyle(color: Colors.black), + ), + + TextFormField( + initialValue: "SDN 1 Bandung Barat", + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: 'Sekolah', + labelStyle: TextStyle(color: Colors.black), + ), + style: TextStyle(color: Colors.black), + ), + TextFormField( + initialValue: "Laki-laki", + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: 'Jenis Kelamin', + labelStyle: TextStyle(color: Colors.black), + ), + style: TextStyle(color: Colors.black), + ), + TextFormField( + initialValue: "Bandung 13-05-2025", + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: 'Sekolah', + labelStyle: TextStyle(color: Colors.black), + ), + style: TextStyle(color: Colors.black), + ), + TextFormField( + initialValue: "56 Kg", + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: 'Berat Badan', + labelStyle: TextStyle(color: Colors.black), + ), + style: TextStyle(color: Colors.black), + ), + TextFormField( + initialValue: "170", + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: 'Tinggi Badan', + labelStyle: TextStyle(color: Colors.black), + ), + style: TextStyle(color: Colors.black), + ), + ], + ), + ), + ), + ], + ), + // Profile Picture (bisa diubah) + Positioned( + top: 25, + left: MediaQuery.of(context).size.width / 2 - 50, + child: GestureDetector( + onTap: () => _pickImage(true), + child: Stack( + alignment: Alignment.bottomRight, + children: [ + CircleAvatar( + radius: 50, + backgroundColor: Colors.grey[300], + backgroundImage: + _profileImage != null + ? (kIsWeb + ? MemoryImage(_profileImage) as ImageProvider + : FileImage(_profileImage) as ImageProvider) + : null, + child: + _profileImage == null + ? Image.asset("assets/images/luffy.png") + : null, + ), + CircleAvatar( + radius: 15, + backgroundColor: Colors.blue, + child: Icon(Icons.edit, color: Colors.white, size: 15), + ), + ], + ), + ), + ), + + Positioned( + top: 130, + left: MediaQuery.of(context).size.width / 2 - 30, + child: GestureDetector( + onTap: () => _pickImage(true), + child: Stack( + alignment: Alignment.bottomRight, + children: [ + Text( + "Luffy kun", + style: TextStyle( + color: Colors.deepPurple, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ), + ], + ), + ); + } + + Widget _buildListItem(IconData icon, String label, {bool isLogout = false}) { + return ListTile( + leading: Icon( + icon, + color: + isLogout + ? const Color.fromARGB(255, 181, 47, 47) + : const Color.fromARGB(255, 255, 255, 255), + ), + title: Text(label, style: TextStyle(fontSize: 16, color: Colors.black)), + trailing: Icon(Icons.arrow_forward_ios, size: 16), + onTap: () {}, + ); + } +} diff --git a/lib/screen/saya/point_saya.dart b/lib/screen/saya/point_saya.dart new file mode 100644 index 0000000..4253420 --- /dev/null +++ b/lib/screen/saya/point_saya.dart @@ -0,0 +1,214 @@ +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:freekake/components/bottom_navbar.dart'; +import 'package:freekake/components/main_menu.dart'; +import 'package:freekake/components/point_header.dart'; +import 'package:freekake/components/scan_button.dart'; +import 'package:image_picker/image_picker.dart'; +import 'dart:io'; + +// import 'package:image_picker_web/image_picker_web.dart'; +import 'package:flutter/foundation.dart' show kIsWeb; + +class PointSaya extends StatefulWidget { + const PointSaya({super.key}); + + @override + _PointSayaState createState() => _PointSayaState(); +} + +class _PointSayaState extends State { + dynamic _profileImage; + dynamic _headerImage; + ImageProvider? imageProvider; + + final ImagePicker _picker = ImagePicker(); + + Future _pickImage(bool isProfile) async { + if (kIsWeb) { + // Uint8List? bytesFromPicker = await ImagePickerWeb.getImageAsBytes(); + // if (bytesFromPicker != null) { + // setState(() { + // if (isProfile) { + // _profileImage = bytesFromPicker; + // } else { + // _headerImage = bytesFromPicker; + // } + // }); + // } + } else { + final pickedFile = await _picker.pickImage(source: ImageSource.gallery); + if (pickedFile != null) { + final imageFile = File(pickedFile.path); + setState(() { + if (isProfile) { + _profileImage = imageFile; + } else { + _headerImage = imageFile; + } + + imageProvider = + kIsWeb ? MemoryImage(_profileImage) : FileImage(_profileImage); + }); + } else { + imageProvider = AssetImage("assets/images/luffy.png"); + } + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Point Saya"), + backgroundColor: Color.fromARGB(225, 79, 76, 182), + ), + resizeToAvoidBottomInset: false, + backgroundColor: const Color.fromARGB(255, 255, 255, 255), + body: Stack( + children: [ + Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.only(top: 0.0, left: 20, right: 20), + child: Container( + height: MediaQuery.of(context).size.height * 0.7, + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + color: const Color.fromARGB(255, 137, 123, 69), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ), + ), + child: Column( + spacing: 10, + children: [ + PointsHeader(), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox(width: 40), + Text("Furikake", style: TextStyle(color: Colors.white)), + SizedBox(width: 130), + Text( + "", + // "🔥 Level: ${points.level}", + // style: TextStyle(color: Colors.orangeAccent), + ), + Text("100", style: TextStyle(color: Colors.lightBlue)), + SizedBox(width: 60), + Text("20", style: TextStyle(color: Colors.greenAccent)), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox(width: 40), + Text("Furikake", style: TextStyle(color: Colors.white)), + SizedBox(width: 130), + Text( + "", + // "🔥 Level: ${points.level}", + // style: TextStyle(color: Colors.orangeAccent), + ), + Text("100", style: TextStyle(color: Colors.lightBlue)), + SizedBox(width: 60), + Text("20", style: TextStyle(color: Colors.greenAccent)), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox(width: 40), + Text("Furikake", style: TextStyle(color: Colors.white)), + SizedBox(width: 130), + Text( + "", + // "🔥 Level: ${points.level}", + // style: TextStyle(color: Colors.orangeAccent), + ), + Text("100", style: TextStyle(color: Colors.lightBlue)), + SizedBox(width: 60), + Text("20", style: TextStyle(color: Colors.greenAccent)), + ], + ), + ], + ), + ), + ), + ), + // Profile Picture (bisa diubah) + Positioned( + top: 25, + left: MediaQuery.of(context).size.width / 2 - 50, + child: GestureDetector( + onTap: () => _pickImage(true), + child: Stack( + alignment: Alignment.bottomRight, + children: [ + CircleAvatar( + radius: 50, + backgroundColor: Colors.grey[300], + backgroundImage: + _profileImage != null + ? (kIsWeb + ? MemoryImage(_profileImage) as ImageProvider + : FileImage(_profileImage) as ImageProvider) + : null, + child: + _profileImage == null + ? Image.asset("assets/images/luffy.png") + : null, + ), + CircleAvatar( + radius: 15, + backgroundColor: Colors.blue, + child: Icon(Icons.edit, color: Colors.white, size: 15), + ), + ], + ), + ), + ), + + Positioned( + top: 130, + left: MediaQuery.of(context).size.width / 2 - 30, + child: GestureDetector( + onTap: () => _pickImage(true), + child: Stack( + alignment: Alignment.bottomRight, + children: [ + Text( + "Luffy kun", + style: TextStyle( + color: Colors.deepPurple, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ), + ], + ), + ); + } + + Widget _buildListItem(IconData icon, String label, {bool isLogout = false}) { + return ListTile( + leading: Icon( + icon, + color: + isLogout + ? const Color.fromARGB(255, 181, 47, 47) + : const Color.fromARGB(255, 255, 255, 255), + ), + title: Text(label, style: TextStyle(fontSize: 16, color: Colors.black)), + trailing: Icon(Icons.arrow_forward_ios, size: 16), + onTap: () {}, + ); + } +} diff --git a/lib/screen/saya/profile_screen.dart b/lib/screen/saya/profile_screen.dart index 302bb82..8d659a6 100644 --- a/lib/screen/saya/profile_screen.dart +++ b/lib/screen/saya/profile_screen.dart @@ -7,6 +7,8 @@ import 'package:freekake/components/main_menu.dart'; import 'package:freekake/components/scan_button.dart'; import 'package:freekake/components/topbar_container.dart'; import 'package:freekake/screen/saya/akun_saya.dart'; +import 'package:freekake/screen/saya/data_saya.dart'; +import 'package:freekake/screen/saya/point_saya.dart'; import 'package:image_picker/image_picker.dart'; import 'dart:io'; @@ -215,12 +217,24 @@ class _ProfileScreenState extends State { padding: const EdgeInsets.symmetric(horizontal: 25.0), child: Divider(height: 0), ), - _buildListItem(Icons.person, "Data Diri", () => {}), + _buildListItem(Icons.person, "Data Diri", () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => DataSaya()), + ); + }), Padding( padding: const EdgeInsets.symmetric(horizontal: 25.0), child: Divider(height: 0), ), - _buildListItem(Icons.person, "Point Saya", () => {}), + _buildListItem(Icons.person, "Point Saya", () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PointSaya(), + ), + ); + }), Padding( padding: const EdgeInsets.symmetric( horizontal: 25.0, diff --git a/lib/util/player_point.dart b/lib/util/player_point.dart new file mode 100644 index 0000000..cefe9ab --- /dev/null +++ b/lib/util/player_point.dart @@ -0,0 +1,31 @@ +class PlayerPoints { + int xp; + int gp; + int sp; + int level; + + PlayerPoints({ + required this.xp, + required this.gp, + required this.sp, + required this.level, + }); + + void addXP(int value) { + xp += value; + if (xp >= xpToNextLevel()) { + levelUp(); + } + } + + void addGP(int value) => gp += value; + void addSP(int value) => sp += value; + + int xpToNextLevel() => 1000 + (level * 200); + + void levelUp() { + level++; + sp++; + xp = 0; + } +}