fixed bugs from qa test Co-authored-by: Jipson George <152465898+Jipson-cosq@users.noreply.github.com> Co-authored-by: DhanshCOSQ <dhanshas@cosq.net> Reviewed-on: cosqnet/telemednet#7 Co-authored-by: Jipson George <jipsongeorge@cosq.net> Co-committed-by: Jipson George <jipsongeorge@cosq.net>
427 lines
12 KiB
Dart
427 lines
12 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:animate_do/animate_do.dart';
|
|
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
|
import 'package:medora/route/route_names.dart';
|
|
|
|
class Specialty {
|
|
final String name;
|
|
final IconData icon;
|
|
final Color color;
|
|
final String description;
|
|
|
|
Specialty({
|
|
required this.name,
|
|
required this.icon,
|
|
required this.color,
|
|
required this.description,
|
|
});
|
|
}
|
|
|
|
class SpecialtyScreen extends StatefulWidget {
|
|
const SpecialtyScreen({super.key});
|
|
|
|
@override
|
|
State<SpecialtyScreen> createState() => _SpecialtyScreenState();
|
|
}
|
|
|
|
class _SpecialtyScreenState extends State<SpecialtyScreen> {
|
|
final List<Specialty> _allSpecialties = [
|
|
Specialty(
|
|
name: 'Pediatric',
|
|
icon: Icons.child_care,
|
|
color: Colors.blue,
|
|
description: 'Medical care for infants, children, and adolescents',
|
|
),
|
|
Specialty(
|
|
name: 'General Medicine',
|
|
icon: Icons.medical_services,
|
|
color: Colors.green,
|
|
description:
|
|
'Primary healthcare for adults and general medical conditions',
|
|
),
|
|
Specialty(
|
|
name: 'Family Medicine',
|
|
icon: Icons.family_restroom,
|
|
color: Colors.teal,
|
|
description: 'Comprehensive healthcare for families and individuals',
|
|
),
|
|
Specialty(
|
|
name: 'Cardiologist',
|
|
icon: Icons.favorite,
|
|
color: Colors.red,
|
|
description: 'Diagnosis and treatment of heart conditions',
|
|
),
|
|
Specialty(
|
|
name: 'Neurology',
|
|
icon: Icons.psychology,
|
|
color: Colors.purple,
|
|
description: 'Treatment of nervous system disorders',
|
|
),
|
|
Specialty(
|
|
name: 'Gastroenterology',
|
|
icon: Icons.local_hospital,
|
|
color: Colors.orange,
|
|
description: 'Digestive system disorders and treatment',
|
|
),
|
|
Specialty(
|
|
name: 'Dermatologist',
|
|
icon: Icons.face,
|
|
color: Colors.pink,
|
|
description: 'Skin, hair, and nail conditions',
|
|
),
|
|
Specialty(
|
|
name: 'Orthopedic',
|
|
icon: Icons.wheelchair_pickup,
|
|
color: Colors.indigo,
|
|
description: 'Musculoskeletal system and injury treatment',
|
|
),
|
|
Specialty(
|
|
name: 'Ophthalmology',
|
|
icon: Icons.remove_red_eye,
|
|
color: Colors.brown,
|
|
description: 'Eye care and vision treatment',
|
|
),
|
|
Specialty(
|
|
name: 'ENT',
|
|
icon: Icons.hearing,
|
|
color: Colors.cyan,
|
|
description: 'Ear, nose, and throat specialist',
|
|
),
|
|
Specialty(
|
|
name: 'Psychiatry',
|
|
icon: Icons.psychology_outlined,
|
|
color: Colors.deepPurple,
|
|
description: 'Mental health and behavioral disorders',
|
|
),
|
|
Specialty(
|
|
name: 'Gynecology',
|
|
icon: Icons.pregnant_woman,
|
|
color: Colors.pinkAccent,
|
|
description: "Women's health and reproductive care",
|
|
),
|
|
Specialty(
|
|
name: 'Urology',
|
|
icon: Icons.water_drop,
|
|
color: Colors.lightBlue,
|
|
description: 'Urinary tract and male reproductive health',
|
|
),
|
|
Specialty(
|
|
name: 'Endocrinology',
|
|
icon: Icons.biotech,
|
|
color: Colors.amber,
|
|
description: 'Hormone and metabolic disorders',
|
|
),
|
|
Specialty(
|
|
name: 'Oncology',
|
|
icon: Icons.bloodtype,
|
|
color: Colors.redAccent,
|
|
description: 'Cancer diagnosis and treatment',
|
|
),
|
|
Specialty(
|
|
name: 'Rheumatology',
|
|
icon: Icons.accessibility,
|
|
color: Colors.deepOrange,
|
|
description: 'Arthritis and autoimmune conditions',
|
|
),
|
|
Specialty(
|
|
name: 'Pulmonology',
|
|
icon: Icons.air,
|
|
color: Colors.lightGreen,
|
|
description: 'Respiratory system disorders',
|
|
),
|
|
Specialty(
|
|
name: 'Nephrology',
|
|
icon: Icons.water,
|
|
color: Colors.blueGrey,
|
|
description: 'Kidney diseases and disorders',
|
|
),
|
|
Specialty(
|
|
name: 'Dentistry',
|
|
icon: Icons.cleaning_services,
|
|
color: Colors.cyan,
|
|
description: 'Oral health and dental care',
|
|
),
|
|
Specialty(
|
|
name: 'Physical Therapy',
|
|
icon: Icons.accessibility_new,
|
|
color: Colors.deepPurple,
|
|
description: 'Rehabilitation and physical medicine',
|
|
),
|
|
Specialty(
|
|
name: 'Sports Medicine',
|
|
icon: Icons.sports,
|
|
color: Colors.green,
|
|
description: 'Athletic injuries and performance',
|
|
),
|
|
Specialty(
|
|
name: 'Allergy & Immunology',
|
|
icon: Icons.sick,
|
|
color: Colors.orange,
|
|
description: 'Allergies and immune system disorders',
|
|
),
|
|
Specialty(
|
|
name: 'Pain Management',
|
|
icon: Icons.healing,
|
|
color: Colors.red,
|
|
description: 'Chronic pain treatment',
|
|
),
|
|
Specialty(
|
|
name: 'Sleep Medicine',
|
|
icon: Icons.bedtime,
|
|
color: Colors.indigo,
|
|
description: 'Sleep disorders and treatment',
|
|
),
|
|
Specialty(
|
|
name: 'Geriatrics',
|
|
icon: Icons.elderly,
|
|
color: Colors.brown,
|
|
description: 'Healthcare for elderly patients',
|
|
),
|
|
];
|
|
|
|
late List<Specialty> _filteredSpecialties;
|
|
final TextEditingController _searchController = TextEditingController();
|
|
bool _isSearching = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_filteredSpecialties = _allSpecialties;
|
|
_searchController.addListener(_onSearchChanged);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_searchController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
void _onSearchChanged() {
|
|
final searchQuery = _searchController.text.toLowerCase();
|
|
setState(() {
|
|
_isSearching = searchQuery.isNotEmpty;
|
|
_filteredSpecialties = _allSpecialties
|
|
.where((specialty) =>
|
|
specialty.name.toLowerCase().contains(searchQuery) ||
|
|
specialty.description.toLowerCase().contains(searchQuery))
|
|
.toList();
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: const Color(0xFFF5F7FF),
|
|
body: CustomScrollView(
|
|
slivers: [
|
|
_buildSliverAppBar(),
|
|
SliverToBoxAdapter(
|
|
child: _buildSearchBar(),
|
|
),
|
|
SliverPadding(
|
|
padding: const EdgeInsets.all(16),
|
|
sliver: _buildSpecialtiesGrid(),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSliverAppBar() {
|
|
return SliverAppBar(
|
|
expandedHeight: 55,
|
|
floating: true,
|
|
pinned: true,
|
|
stretch: true,
|
|
backgroundColor: Colors.white,
|
|
elevation: 0,
|
|
leading: IconButton(
|
|
icon: const Icon(Icons.arrow_back, color: Colors.black87),
|
|
onPressed: () => Navigator.pop(context),
|
|
),
|
|
flexibleSpace: FlexibleSpaceBar(
|
|
title: Text(
|
|
'Find a Specialist',
|
|
style: GoogleFonts.poppins(
|
|
color: Colors.black87,
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 20,
|
|
),
|
|
),
|
|
centerTitle: true,
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSearchBar() {
|
|
return FadeIn(
|
|
child: Padding(
|
|
padding: const EdgeInsets.fromLTRB(16, 8, 16, 0),
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(16),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.grey.withOpacity(0.1),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: TextField(
|
|
controller: _searchController,
|
|
decoration: InputDecoration(
|
|
hintText: 'Search specialties...',
|
|
hintStyle: GoogleFonts.poppins(
|
|
color: Colors.grey,
|
|
fontSize: 14,
|
|
),
|
|
prefixIcon: const Icon(Icons.search, color: Colors.grey),
|
|
suffixIcon: _isSearching
|
|
? IconButton(
|
|
icon: const Icon(Icons.clear),
|
|
onPressed: () {
|
|
_searchController.clear();
|
|
FocusScope.of(context).unfocus();
|
|
},
|
|
)
|
|
: null,
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(16),
|
|
borderSide: BorderSide.none,
|
|
),
|
|
filled: true,
|
|
fillColor: Colors.white,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSpecialtiesGrid() {
|
|
return SliverAnimationBuilder(
|
|
child: MasonryGridView.count(
|
|
crossAxisCount: 2,
|
|
mainAxisSpacing: 16,
|
|
crossAxisSpacing: 16,
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
itemCount: _filteredSpecialties.length,
|
|
itemBuilder: (context, index) {
|
|
final specialty = _filteredSpecialties[index];
|
|
return FadeInUp(
|
|
delay: Duration(milliseconds: 100 * index),
|
|
child: _buildSpecialtyCard(specialty),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSpecialtyCard(Specialty specialty) {
|
|
return GestureDetector(
|
|
onTap: () {
|
|
Navigator.pushNamed(
|
|
context,
|
|
RouteNames.doctorListScreen,
|
|
arguments: {
|
|
'specialty': specialty.name,
|
|
},
|
|
);
|
|
},
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(20),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: specialty.color.withOpacity(0.1),
|
|
blurRadius: 20,
|
|
offset: const Offset(0, 5),
|
|
),
|
|
],
|
|
),
|
|
child: ClipRRect(
|
|
borderRadius: BorderRadius.circular(20),
|
|
child: Stack(
|
|
children: [
|
|
Positioned(
|
|
right: -20,
|
|
top: -20,
|
|
child: CircleAvatar(
|
|
radius: 40,
|
|
backgroundColor: specialty.color.withOpacity(0.1),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: specialty.color.withOpacity(0.1),
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Icon(
|
|
specialty.icon,
|
|
color: specialty.color,
|
|
size: 28,
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
Text(
|
|
specialty.name,
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.black87,
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
specialty.description,
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 12,
|
|
color: Colors.grey[600],
|
|
),
|
|
maxLines: 2,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class SliverAnimationBuilder extends StatelessWidget {
|
|
final Widget child;
|
|
|
|
const SliverAnimationBuilder({
|
|
super.key,
|
|
required this.child,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return SliverAnimatedList(
|
|
initialItemCount: 1,
|
|
itemBuilder: (context, index, animation) {
|
|
return SlideInUp(
|
|
from: 50,
|
|
child: child,
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|