Skip to content
This repository has been archived by the owner on Jul 12, 2024. It is now read-only.

Feature community filters #27

Merged
merged 4 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/assets/svg/country_svg.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class CountrySvg extends StatelessWidget {

@override
Widget build(BuildContext context) {
final Color defaultColor = color ?? Colors.black;
final Color defaultColor = color ?? Colors.yellow[700]!;
String infoSvg = generateCountrySvg(fill, strokeWidth, defaultColor);
return SvgPicture.string(
infoSvg,
Expand Down
39 changes: 39 additions & 0 deletions lib/assets/svg/sex_svg.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

class SexSvg extends StatelessWidget {
final String fill;
final int strokeWidth;
final Color? color;
final double widht;
final double height;

const SexSvg(
{super.key,
this.color,
this.fill = "none",
this.strokeWidth = 30,
this.widht = 17,
this.height = 17});

String generateSexSvg(String fillColor, int strokeWidth, Color color) {
final colorHex = '#${color.value.toRadixString(16).substring(2)}';
return '''
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<circle cx="216" cy="200" r="136" stroke="$colorHex" stroke-width="$strokeWidth" fill="$fillColor"></circle>
<path d="M216 352v128M272 416H160M432 112V32h-80M335.28 128.72L432 32" stroke="$colorHex" stroke-width="$strokeWidth" fill="$fillColor"></path>
</svg>
''';
}

@override
Widget build(BuildContext context) {
final Color defaultColor = color ?? Colors.yellow[700]!;
String infoSvg = generateSexSvg(fill, strokeWidth, defaultColor);
return SvgPicture.string(
infoSvg,
width: widht,
height: height,
);
}
}
39 changes: 39 additions & 0 deletions lib/assets/svg/switch_svg.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

class SwitchSvg extends StatelessWidget {
final String fill;
final int strokeWidth;
final Color? color;
final double widht;
final double height;

const SwitchSvg(
{super.key,
this.color,
this.fill = "none",
this.strokeWidth = 30,
this.widht = 17,
this.height = 17});

String generateSwitchSvg(String fillColor, int strokeWidth, Color color) {
final colorHex = '#${color.value.toRadixString(16).substring(2)}';
return '''
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<circle cx="368" cy="256" r="128" stroke="$colorHex" stroke-width="$strokeWidth" fill="$fillColor"></circle>
<rect x="16" y="128" width="480" height="256" rx="128" ry="128" stroke="$colorHex" stroke-width="$strokeWidth" fill="$fillColor"></rect>
</svg>
''';
}

@override
Widget build(BuildContext context) {
final Color defaultColor = color ?? Colors.yellow[700]!;
String infoSvg = generateSwitchSvg(fill, strokeWidth, defaultColor);
return SvgPicture.string(
infoSvg,
width: widht,
height: height,
);
}
}
27 changes: 21 additions & 6 deletions lib/pages/home/community.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:langx_flutter/components/community/usercard.dart';
import 'package:langx_flutter/providers/user_provider.dart';

// Pages Import
import 'package:langx_flutter/pages/home/filters.dart';

class Community extends ConsumerStatefulWidget {
const Community({super.key});

Expand Down Expand Up @@ -65,23 +68,35 @@ class _CommunityState extends ConsumerState<Community> {
backgroundColor: const Color.fromARGB(31, 163, 163, 163),
body: CustomScrollView(
slivers: [
const SliverAppBar(
SliverAppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Community"),
const Text("Community"),
Row(
children: [
Icon(Icons.search, size: 30),
SizedBox(width: 10.0),
Icon(Icons.filter_list, size: 30),
IconButton(
icon: const Icon(Icons.search, size: 30),
onPressed: () {},
),
const SizedBox(width: 10.0),
IconButton(
icon: const Icon(Icons.filter_list, size: 30),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const FiltersPage()),
);
},
),
],
),
],
),
centerTitle: false,
pinned: true,
backgroundColor: Color(0xFFFBC02D),
backgroundColor: const Color(0xFFFBC02D),
foregroundColor: Colors.black,
),
SliverToBoxAdapter(
Expand Down
250 changes: 250 additions & 0 deletions lib/pages/home/filters.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
import 'package:flutter/material.dart';

import 'package:langx_flutter/assets/svg/battery_svg.dart';
import 'package:langx_flutter/assets/svg/word_svg.dart';
import 'package:langx_flutter/assets/svg/country_svg.dart';
import 'package:langx_flutter/assets/svg/sex_svg.dart';
import 'package:langx_flutter/assets/svg/switch_svg.dart';

class FiltersPage extends StatefulWidget {
const FiltersPage({super.key});

@override
FiltersPageState createState() => FiltersPageState();
}

typedef BoolCallback = void Function(bool? value);

class FiltersPageState extends State<FiltersPage> {
bool matchMyGender = false;
bool _motherEnglish = false;
bool _motherChinese = false;
bool _studyEnglish = false;
bool _studyChinese = false;

RangeValues rangeValues = const RangeValues(18, 60);
String rangeLable = 'No Filter';

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.yellow[700],
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context);
},
),
title: const Text('Filters'),
actions: [
IconButton(
icon: const Icon(Icons.refresh),
onPressed: () {},
),
IconButton(
icon: const Icon(Icons.check),
onPressed: () {},
),
],
),
body: ListView(
padding: const EdgeInsets.all(8.0),
children: [
_buildFilterSection(
title: 'Mother Language',
options: [
_buildOptionRow(
'English',
const BatterySvg(widht: 25, height: 25),
_motherEnglish, (bool? value) {
setState(() {
_motherEnglish = value ?? false;
});
}),
_buildOptionRow(
'Chinese (Simplified)',
const WordSvg(widht: 25, height: 25),
_motherChinese, (bool? value) {
setState(() {
_motherChinese = value ?? false;
});
}),
],
),
_buildFilterSection(
title: 'Study Language',
options: [
_buildOptionRow(
'English',
const BatterySvg(widht: 25, height: 25),
_studyEnglish, (bool? value) {
setState(() {
_studyEnglish = value ?? false;
});
}),
_buildOptionRow(
'Chinese (Simplified)',
const WordSvg(widht: 25, height: 25),
_studyChinese, (bool? value) {
setState(() {
_studyChinese = value ?? false;
});
}),
],
),
_buildFilterSection(
title: 'Country',
options: [
_buildOptionRow2(
'No Filter', const CountrySvg(widht: 25, height: 25)),
],
),
_buildFilterSection(
title: 'Gender',
options: [
_buildOptionRow2(
'No Filter', const SexSvg(widht: 25, height: 25)),
_buildOptionRow2(
'Match My Gender', const SwitchSvg(widht: 25, height: 25)),
],
),
_buildFilterSection(
title: 'Age',
options: [
Container(
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: Colors.grey,
width: 1.0,
),
),
),
child: ListTile(
leading:
Icon(Icons.calendar_today, color: Colors.yellow[700]),
title: Text(rangeLable),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: RangeSlider(
activeColor: Colors.yellow[700],
values: rangeValues,
min: 0,
max: 100,
divisions: 100,
labels: RangeLabels(
rangeValues.start.round().toString(),
rangeValues.end.round().toString(),
),
onChanged: (RangeValues values) {
setState(() {
rangeValues = values;

rangeLable =
"between ${rangeValues.start.round().toString()} and ${rangeValues.end.round().toString()} ";
});
},
),
),
],
),
Padding(
padding: const EdgeInsets.all(16.0),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.yellow[700],
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16.0),
),
onPressed: () {},
child: const Text(
'APPLY',
style: TextStyle(fontSize: 16),
),
),
),
],
),
);
}

Widget _buildFilterSection({
required String title,
required List<Widget> options,
bool hasArrow = false,
}) {
return Card(
elevation: 8.0,
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
margin: const EdgeInsets.symmetric(vertical: 4.0),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTile(
title: Text(title),
trailing: hasArrow ? const Icon(Icons.arrow_forward_ios) : null,
),
Column(children: options),
],
),
),
);
}

Widget _buildOptionRow(String text, StatelessWidget icon, bool selection,
BoolCallback onChange) {
return Container(
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: Colors.grey,
width: 1.0,
),
),
),
child: ListTile(
leading: icon,
title: Text(text),
trailing: Checkbox(
activeColor: Colors.yellow[700],
checkColor: Colors.black,
value: selection,
onChanged: onChange),
),
);
}

Widget _buildOptionRow2(String text, StatelessWidget icon) {
return Container(
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: Colors.grey,
width: 1.0,
),
),
),
child: ListTile(
leading: icon,
title: Text(text),
trailing: IconButton(
iconSize: 30,
icon: const Icon(Icons.chevron_right),
onPressed: () {
debugPrint("Print");
},
color: Colors.grey,
),
),
);
}
}
Loading