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

Commit

Permalink
Merge pull request #27 from langx/feature-community-filters
Browse files Browse the repository at this point in the history
Feature community filters
  • Loading branch information
xuelink authored Jun 28, 2024
2 parents 4362d7d + 3cfc037 commit 16f3184
Show file tree
Hide file tree
Showing 5 changed files with 350 additions and 7 deletions.
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,
),
),
);
}
}

0 comments on commit 16f3184

Please sign in to comment.