diff --git a/assets/globe.svg b/assets/globe.svg
new file mode 100644
index 0000000..c077e74
--- /dev/null
+++ b/assets/globe.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/plus.svg b/assets/plus.svg
new file mode 100644
index 0000000..2f994ff
--- /dev/null
+++ b/assets/plus.svg
@@ -0,0 +1,23 @@
+
diff --git a/assets/profile.svg b/assets/profile.svg
new file mode 100644
index 0000000..50ed2f3
--- /dev/null
+++ b/assets/profile.svg
@@ -0,0 +1,3 @@
+
diff --git a/lib/components/bottom_navigation.dart b/lib/components/bottom_navigation.dart
new file mode 100644
index 0000000..1a56028
--- /dev/null
+++ b/lib/components/bottom_navigation.dart
@@ -0,0 +1,61 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+
+class BottomNavigation extends StatefulWidget {
+ const BottomNavigation({Key? key, required this.onSelect}) : super(key: key);
+
+ final Function(int) onSelect;
+
+ @override
+ State createState() => _BottomNavigationState();
+}
+
+class _BottomNavigationState extends State {
+ int selected = 1;
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ IconButton(
+ onPressed: () {
+ setState(() {
+ selected = 1;
+ widget.onSelect(1);
+ });
+ },
+ icon: SvgPicture.asset(
+ 'assets/globe.svg',
+ color: selected == 1 ? Colors.pink : const Color(0xFF292929),
+ ),
+ ),
+ IconButton(
+ iconSize: 65,
+ padding: const EdgeInsets.only(bottom: 20),
+ onPressed: () {
+ setState(() {
+ selected = 2;
+ widget.onSelect(2);
+ });
+ },
+ icon: SvgPicture.asset(
+ 'assets/plus.svg',
+ ),
+ ),
+ IconButton(
+ onPressed: () {
+ setState(() {
+ selected = 3;
+ widget.onSelect(3);
+ });
+ },
+ icon: SvgPicture.asset(
+ 'assets/profile.svg',
+ color: selected == 3 ? Colors.pink : const Color(0xFF292929),
+ ),
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/components/room_card.dart b/lib/components/room_card.dart
index af1469b..ef98910 100644
--- a/lib/components/room_card.dart
+++ b/lib/components/room_card.dart
@@ -1,13 +1,38 @@
import 'package:flutter/material.dart';
-enum RoomStatus { waitingForPlayers, awaitingForAccept, started }
+String calculateMembersCountLabel(int count) {
+ if (count % 10 == 1 && count % 100 != 11) {
+ return "человек";
+ } else if (count % 10 >= 2 &&
+ count % 10 <= 4 &&
+ (count % 100 < 10 || count % 100 >= 20)) {
+ return "человека";
+ } else {
+ return "человек";
+ }
+}
+
+enum RoomStatus {
+ waitingForPlayers(name: "Ожидаем игроков", color: Colors.yellow),
+ awaitingForAccept(name: "Ожидаем подтверждения", color: Colors.red),
+ started(name: "Игра началась", color: Colors.green);
+
+ const RoomStatus({
+ required this.name,
+ required this.color,
+ });
+
+ final String name;
+ final Color color;
+}
class RoomCard extends StatelessWidget {
- const RoomCard(
- {super.key,
- required this.name,
- required this.membersCount,
- required this.status});
+ const RoomCard({
+ super.key,
+ required this.name,
+ required this.membersCount,
+ required this.status,
+ });
final String name;
final int membersCount;
@@ -15,20 +40,12 @@ class RoomCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
- return Container(
- decoration: BoxDecoration(
- border: Border.all(color: Colors.grey.shade400),
- borderRadius: const BorderRadius.all(Radius.circular(16.0)),
- // ignore: prefer_const_literals_to_create_immutables
- boxShadow: [
- const BoxShadow(
- color: Colors.grey,
- spreadRadius: 3,
- blurRadius: 7,
- offset: Offset(0, 7))
- ],
- color: Colors.white),
- padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 28),
+ return Card(
+ elevation: 5,
+ shape: const RoundedRectangleBorder(
+ borderRadius: BorderRadius.all(Radius.circular(10))),
+ child: Container(
+ padding: const EdgeInsets.all(15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -36,21 +53,38 @@ class RoomCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Text(name),
+ Text(
+ name,
+ style: const TextStyle(
+ fontSize: 20,
+ ),
+ ),
const SizedBox(height: 10),
- Text("$membersCount человек"),
+ Text(
+ "$membersCount ${calculateMembersCountLabel(membersCount)}",
+ style: TextStyle(
+ fontSize: 16,
+ color: Colors.black.withOpacity(0.5),
+ ),
+ ),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
- Text(status.name),
- const SizedBox(height: 10),
- const Text("скоро начало")
+ Text(
+ status.name,
+ style: TextStyle(
+ color: status.color,
+ fontSize: 16,
+ ),
+ ),
],
)
],
- ));
+ ),
+ ),
+ );
}
}
diff --git a/lib/main.dart b/lib/main.dart
index 72fa6f0..f26aa44 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,4 +1,7 @@
+import 'dart:developer';
+
import 'package:flutter/material.dart';
+import 'package:secret_santa_flutter/components/bottom_navigation.dart';
import 'package:secret_santa_flutter/components/room_card.dart';
void main() {
@@ -8,24 +11,14 @@ void main() {
class MyApp extends StatelessWidget {
const MyApp({super.key});
- // This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Тайный дед мороз',
theme: ThemeData(
- // This is the theme of your application.
- //
- // Try running your application with "flutter run". You'll see the
- // application has a blue toolbar. Then, without quitting the app, try
- // changing the primarySwatch below to Colors.green and then invoke
- // "hot reload" (press "r" in the console where you ran "flutter run",
- // or simply save your changes to "hot reload" in a Flutter IDE).
- // Notice that the counter didn't reset back to zero; the application
- // is not restarted.
primarySwatch: Colors.blue,
),
- home: const MyHomePage(title: 'Flutter Demo Home Page'),
+ home: const MyHomePage(title: 'Тайный дед мороз'),
);
}
}
@@ -33,15 +26,6 @@ class MyApp extends StatelessWidget {
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
- // This widget is the home page of your application. It is stateful, meaning
- // that it has a State object (defined below) that contains fields that affect
- // how it looks.
-
- // This class is the configuration for the state. It holds the values (in this
- // case the title) provided by the parent (in this case the App widget) and
- // used by the build method of the State. Fields in a Widget subclass are
- // always marked "final".
-
final String title;
@override
@@ -49,72 +33,62 @@ class MyHomePage extends StatefulWidget {
}
class _MyHomePageState extends State {
- int _counter = 0;
-
- void _incrementCounter() {
- setState(() {
- // This call to setState tells the Flutter framework that something has
- // changed in this State, which causes it to rerun the build method below
- // so that the display can reflect the updated values. If we changed
- // _counter without calling setState(), then the build method would not be
- // called again, and so nothing would appear to happen.
- _counter++;
- });
- }
+ var selected = 0;
@override
Widget build(BuildContext context) {
- // This method is rerun every time setState is called, for instance as done
- // by the _incrementCounter method above.
- //
- // The Flutter framework has been optimized to make rerunning build methods
- // fast, so that you can just rebuild anything that needs updating rather
- // than having to individually change instances of widgets.
- return Scaffold(
- appBar: AppBar(
- // Here we take the value from the MyHomePage object that was created by
- // the App.build method, and use it to set our appbar title.
- title: Text(widget.title),
- ),
- body: Center(
- // Center is a layout widget. It takes a single child and positions it
- // in the middle of the parent.
- child: Column(
- // Column is also a layout widget. It takes a list of children and
- // arranges them vertically. By default, it sizes itself to fit its
- // children horizontally, and tries to be as tall as its parent.
- //
- // Invoke "debug painting" (press "p" in the console, choose the
- // "Toggle Debug Paint" action from the Flutter Inspector in Android
- // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
- // to see the wireframe for each widget.
- //
- // Column has various properties to control how it sizes itself and
- // how it positions its children. Here we use mainAxisAlignment to
- // center the children vertically; the main axis here is the vertical
- // axis because Columns are vertical (the cross axis would be
- // horizontal).
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- const RoomCard(
- name: "aboa",
- membersCount: 2,
- status: RoomStatus.awaitingForAccept),
- const Text(
- 'You have pushed the button this many times:',
- ),
- Text(
- '$_counter',
- style: Theme.of(context).textTheme.headlineMedium,
+ return Material(
+ child: SafeArea(
+ child: Container(
+ color: Colors.white,
+ child: Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ SizedBox(
+ height: 70,
+ child: Container(
+ alignment: Alignment.center,
+ child: const Text(
+ "Список комнат",
+ style: TextStyle(
+ fontSize: 22,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ),
+ ),
+ Expanded(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 18.0),
+ child: ListView.builder(
+ itemCount: 2,
+ itemBuilder: (context, idx) {
+ return Container(
+ padding: const EdgeInsets.only(bottom: 10.0),
+ child: const RoomCard(
+ name: "aboba",
+ membersCount: 3,
+ status: RoomStatus.awaitingForAccept),
+ );
+ },
+ ),
+ ),
+ ),
+ SizedBox(
+ height: 100,
+ child: BottomNavigation(
+ onSelect: (int selected) {
+ setState(() => this.selected = selected);
+ log("Selected: $selected");
+ },
+ ),
+ )
+ ],
),
- ],
+ ),
),
),
- floatingActionButton: FloatingActionButton(
- onPressed: _incrementCounter,
- tooltip: 'Increment',
- child: const Icon(Icons.add),
- ), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
diff --git a/pubspec.lock b/pubspec.lock
index 087b13b..2d36b8c 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1,6 +1,14 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
+ args:
+ dependency: transitive
+ description:
+ name: args
+ sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.0"
async:
dependency: transitive
description:
@@ -70,6 +78,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
+ flutter_svg:
+ dependency: "direct main"
+ description:
+ name: flutter_svg
+ sha256: "12006889e2987c549c4c1ec1a5ba4ec4b24d34d2469ee5f9476c926dcecff266"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.4"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -123,6 +139,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.8.2"
+ path_parsing:
+ dependency: transitive
+ description:
+ name: path_parsing
+ sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.1"
+ petitparser:
+ dependency: transitive
+ description:
+ name: petitparser
+ sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.1.0"
sky_engine:
dependency: transitive
description: flutter
@@ -176,6 +208,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.4.16"
+ vector_graphics:
+ dependency: transitive
+ description:
+ name: vector_graphics
+ sha256: "4cf8e60dbe4d3a693d37dff11255a172594c0793da542183cbfe7fe978ae4aaa"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.4"
+ vector_graphics_codec:
+ dependency: transitive
+ description:
+ name: vector_graphics_codec
+ sha256: "278ad5f816f58b1967396d1f78ced470e3e58c9fe4b27010102c0a595c764468"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.4"
+ vector_graphics_compiler:
+ dependency: transitive
+ description:
+ name: vector_graphics_compiler
+ sha256: "0bf61ad56e6fd6688a2865d3ceaea396bc6a0a90ea0d7ad5049b1b76c09d6163"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.4"
vector_math:
dependency: transitive
description:
@@ -184,5 +240,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
+ xml:
+ dependency: transitive
+ description:
+ name: xml
+ sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.2.2"
sdks:
dart: ">=2.19.4 <3.0.0"
+ flutter: ">=3.7.0-0"
diff --git a/pubspec.yaml b/pubspec.yaml
index d501388..25be5ad 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -35,6 +35,7 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
+ flutter_svg: ^2.0.4
dev_dependencies:
flutter_test:
@@ -58,10 +59,11 @@ flutter:
# the material Icons class.
uses-material-design: true
- # To add assets to your application, add an assets section, like this:
- # assets:
- # - images/a_dot_burr.jpeg
- # - images/a_dot_ham.jpeg
+ # To add assets to your application, add an assets section, like this:
+ assets:
+ - assets/globe.svg
+ - assets/plus.svg
+ - assets/profile.svg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware