803 lines
32 KiB
Dart
803 lines
32 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:wordpress/providers/api_controller.dart';
|
|
import 'package:wordpress/utils/ftaf.dart';
|
|
import 'package:wordpress/viewmodel/cart_screen.dart';
|
|
|
|
// Providers
|
|
final selectedColorProvider = StateProvider<String?>((ref) => null);
|
|
final selectedWeightProvider = StateProvider<String?>((ref) => null);
|
|
final quantityProvider = StateProvider<int>((ref) => 1);
|
|
final currentImageIndexProvider = StateProvider<int>((ref) => 0);
|
|
final isFavoriteProvider = StateProvider<bool>((ref) => false);
|
|
|
|
class BigBasketDetailsScreen extends ConsumerWidget {
|
|
final int productId;
|
|
|
|
const BigBasketDetailsScreen({super.key, required this.productId});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final detailAsync = ref.watch(productDetailProvider(productId));
|
|
final selectedColor = ref.watch(selectedColorProvider);
|
|
final selectedWeight = ref.watch(selectedWeightProvider);
|
|
final quantity = ref.watch(quantityProvider);
|
|
final currentImageIndex = ref.watch(currentImageIndexProvider);
|
|
final isFavorite = ref.watch(isFavoriteProvider);
|
|
|
|
return Scaffold(
|
|
backgroundColor: Colors.grey[50],
|
|
body: detailAsync.when(
|
|
data: (product) {
|
|
final images = product.images ?? [];
|
|
String? mainImage = images.isNotEmpty ? images.first.src : null;
|
|
|
|
// Update main image based on selected color
|
|
if (selectedColor != null && images.isNotEmpty) {
|
|
final match = images.firstWhere(
|
|
(img) =>
|
|
(img.name != null &&
|
|
img.name!.toLowerCase() == selectedColor.toLowerCase()) ||
|
|
(img.alt != null &&
|
|
img.alt!.toLowerCase() == selectedColor.toLowerCase()),
|
|
orElse: () => images.first,
|
|
);
|
|
mainImage = match.src ?? mainImage;
|
|
}
|
|
|
|
return CustomScrollView(
|
|
slivers: [
|
|
// Custom App Bar with image
|
|
SliverAppBar(
|
|
expandedHeight: 350,
|
|
pinned: true,
|
|
backgroundColor: Colors.white,
|
|
elevation: 0,
|
|
leading: Container(
|
|
margin: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white.withOpacity(0.9),
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: IconButton(
|
|
icon: const Icon(Icons.arrow_back, color: Colors.black),
|
|
onPressed: () => Navigator.pop(context),
|
|
),
|
|
),
|
|
actions: [
|
|
Container(
|
|
margin: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white.withOpacity(0.9),
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: IconButton(
|
|
icon: Icon(
|
|
isFavorite ? Icons.favorite : Icons.favorite_border,
|
|
color: isFavorite ? Colors.red : Colors.black,
|
|
),
|
|
onPressed: () {
|
|
ref.read(isFavoriteProvider.notifier).state =
|
|
!isFavorite;
|
|
},
|
|
),
|
|
),
|
|
Container(
|
|
margin: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white.withOpacity(0.9),
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: IconButton(
|
|
icon: const Icon(Icons.share, color: Colors.black),
|
|
onPressed: () {
|
|
// Share functionality
|
|
},
|
|
),
|
|
),
|
|
],
|
|
flexibleSpace: FlexibleSpaceBar(
|
|
background: Container(
|
|
color: Colors.white,
|
|
child: images.isNotEmpty
|
|
? PageView.builder(
|
|
itemCount: images.length,
|
|
onPageChanged: (index) {
|
|
ref
|
|
.read(currentImageIndexProvider.notifier)
|
|
.state =
|
|
index;
|
|
},
|
|
itemBuilder: (context, index) {
|
|
return Container(
|
|
margin: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(12),
|
|
color: Colors.grey[100],
|
|
),
|
|
child: ClipRRect(
|
|
borderRadius: BorderRadius.circular(12),
|
|
child: Image.network(
|
|
images[index].src ?? '',
|
|
fit: BoxFit.contain,
|
|
errorBuilder: (context, error, stackTrace) {
|
|
return Container(
|
|
color: Colors.grey[200],
|
|
child: const Center(
|
|
child: Icon(
|
|
Icons.image_not_supported,
|
|
size: 80,
|
|
color: Colors.grey,
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
},
|
|
)
|
|
: Container(
|
|
margin: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(12),
|
|
color: Colors.grey[200],
|
|
),
|
|
child: const Center(
|
|
child: Icon(
|
|
Icons.image_not_supported,
|
|
size: 100,
|
|
color: Colors.grey,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
// Product Content
|
|
SliverToBoxAdapter(
|
|
child: Container(
|
|
color: Colors.white,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Image indicators
|
|
if (images.length > 1)
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: List.generate(
|
|
images.length,
|
|
(index) => Container(
|
|
margin: const EdgeInsets.symmetric(
|
|
horizontal: 4,
|
|
),
|
|
width: 8,
|
|
height: 8,
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.circle,
|
|
color: currentImageIndex == index
|
|
? Colors.green[600]
|
|
: Colors.grey[300],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
// Product Title & Brand
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(
|
|
product.name ?? "Product Name",
|
|
style: const TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.black87,
|
|
),
|
|
),
|
|
Text(
|
|
'Price : ₹ ${product.price.toString()}',
|
|
style: const TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.black87,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 8),
|
|
Row(
|
|
children: [
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 8,
|
|
vertical: 4,
|
|
),
|
|
decoration: BoxDecoration(
|
|
color: Colors.green[50],
|
|
borderRadius: BorderRadius.circular(4),
|
|
border: Border.all(
|
|
color: Colors.green[200]!,
|
|
),
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(
|
|
Icons.star,
|
|
size: 14,
|
|
color: Colors.green[600],
|
|
),
|
|
const SizedBox(width: 4),
|
|
Text(
|
|
"4.2",
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.green[600],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Text(
|
|
"1,234 reviews",
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.grey[600],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
const SizedBox(height: 24),
|
|
|
|
// Attributes Section
|
|
if (product.attributes != null &&
|
|
product.attributes!.isNotEmpty)
|
|
_buildAttributesSection(
|
|
product,
|
|
ref,
|
|
selectedColor,
|
|
selectedWeight,
|
|
),
|
|
|
|
const SizedBox(height: 24),
|
|
|
|
// Quantity Selector
|
|
Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 16),
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(color: Colors.grey[300]!),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
const Text(
|
|
"Quantity:",
|
|
style: TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
const Spacer(),
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(8),
|
|
border: Border.all(color: Colors.grey[300]!),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
InkWell(
|
|
onTap: () {
|
|
if (quantity > 1) {
|
|
ref
|
|
.read(quantityProvider.notifier)
|
|
.state--;
|
|
}
|
|
},
|
|
child: Container(
|
|
padding: const EdgeInsets.all(12),
|
|
child: const Icon(
|
|
Icons.remove,
|
|
size: 18,
|
|
color: Colors.grey,
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 16,
|
|
vertical: 12,
|
|
),
|
|
decoration: BoxDecoration(
|
|
border: Border.symmetric(
|
|
vertical: BorderSide(
|
|
color: Colors.grey[300]!,
|
|
),
|
|
),
|
|
),
|
|
child: Text(
|
|
quantity.toString(),
|
|
style: const TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
),
|
|
InkWell(
|
|
onTap: () {
|
|
ref
|
|
.read(quantityProvider.notifier)
|
|
.state++;
|
|
},
|
|
child: Container(
|
|
padding: const EdgeInsets.all(12),
|
|
child: Icon(
|
|
Icons.add,
|
|
size: 18,
|
|
color: Colors.green[600],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 24),
|
|
|
|
// Product Description
|
|
if (product.shortDescription != null &&
|
|
product.shortDescription!.isNotEmpty)
|
|
Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 16),
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(color: Colors.grey[300]!),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text(
|
|
"Product Details",
|
|
style: TextStyle(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
const SizedBox(height: 12),
|
|
HtmlWidget(
|
|
product.shortDescription!,
|
|
textStyle: TextStyle(
|
|
fontSize: 14,
|
|
color: Colors.grey[700],
|
|
height: 1.5,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 24),
|
|
|
|
// Delivery Info
|
|
Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 16),
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.blue[50],
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(color: Colors.blue[100]!),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Icon(
|
|
Icons.local_shipping,
|
|
color: Colors.blue[700],
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
const Text(
|
|
"Free Delivery",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
Text(
|
|
"Get it by tomorrow, 6:00 AM - 10:00 AM",
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.grey[600],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 12),
|
|
Row(
|
|
children: [
|
|
Icon(
|
|
Icons.assignment_return,
|
|
color: Colors.blue[700],
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
const Text(
|
|
"Easy Return",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
Text(
|
|
"7 days return policy",
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.grey[600],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 100), // Space for bottom buttons
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
loading: () =>
|
|
const Scaffold(body: Center(child: CircularProgressIndicator())),
|
|
error: (err, stack) =>
|
|
Scaffold(body: Center(child: Text("Error: $err"))),
|
|
),
|
|
bottomNavigationBar: detailAsync.when(
|
|
data: (product) => _buildBottomBar(
|
|
context,
|
|
ref,
|
|
product,
|
|
selectedColor,
|
|
selectedWeight,
|
|
quantity,
|
|
),
|
|
loading: () => const SizedBox.shrink(),
|
|
error: (err, stack) => const SizedBox.shrink(),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildAttributesSection(
|
|
product,
|
|
WidgetRef ref,
|
|
String? selectedColor,
|
|
String? selectedWeight,
|
|
) {
|
|
return Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 16),
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(color: Colors.grey[300]!),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: product.attributes!.map<Widget>((attr) {
|
|
final attrName = attr.name?.toLowerCase();
|
|
|
|
if (attrName == "color") {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text(
|
|
"Available Colors",
|
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
|
),
|
|
const SizedBox(height: 12),
|
|
Wrap(
|
|
spacing: 12,
|
|
runSpacing: 8,
|
|
children: attr.options!.map<Widget>((option) {
|
|
final isSelected = option == selectedColor;
|
|
Color colorValue = _getColorFromName(option);
|
|
|
|
return GestureDetector(
|
|
onTap: () {
|
|
ref.read(selectedColorProvider.notifier).state = option;
|
|
},
|
|
child: Container(
|
|
width: 45,
|
|
height: 45,
|
|
decoration: BoxDecoration(
|
|
color: colorValue,
|
|
shape: BoxShape.circle,
|
|
border: Border.all(
|
|
color: isSelected
|
|
? Colors.green[600]!
|
|
: Colors.grey[400]!,
|
|
width: isSelected ? 3 : 1,
|
|
),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
blurRadius: 4,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: isSelected
|
|
? Icon(
|
|
Icons.check,
|
|
color: colorValue == Colors.white
|
|
? Colors.black
|
|
: Colors.white,
|
|
size: 20,
|
|
)
|
|
: null,
|
|
),
|
|
);
|
|
}).toList(),
|
|
),
|
|
const SizedBox(height: 16),
|
|
],
|
|
);
|
|
} else if (attrName == "weight" || attrName == "size") {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"Select ${attr.name}",
|
|
style: const TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
const SizedBox(height: 12),
|
|
Wrap(
|
|
spacing: 12,
|
|
runSpacing: 8,
|
|
children: attr.options!.map<Widget>((option) {
|
|
final isSelected = option == selectedWeight;
|
|
return GestureDetector(
|
|
onTap: () {
|
|
ref.read(selectedWeightProvider.notifier).state =
|
|
option;
|
|
},
|
|
child: Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 16,
|
|
vertical: 12,
|
|
),
|
|
decoration: BoxDecoration(
|
|
color: isSelected ? Colors.green[600] : Colors.white,
|
|
border: Border.all(
|
|
color: isSelected
|
|
? Colors.green[600]!
|
|
: Colors.grey[400]!,
|
|
width: 1.5,
|
|
),
|
|
borderRadius: BorderRadius.circular(25),
|
|
),
|
|
child: Text(
|
|
option,
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w600,
|
|
color: isSelected ? Colors.white : Colors.black,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}).toList(),
|
|
),
|
|
const SizedBox(height: 8),
|
|
],
|
|
);
|
|
}
|
|
|
|
return const SizedBox.shrink();
|
|
}).toList(),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildBottomBar(
|
|
BuildContext context,
|
|
WidgetRef ref,
|
|
product,
|
|
String? selectedColor,
|
|
String? selectedWeight,
|
|
int quantity,
|
|
) {
|
|
return Container(
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, -5),
|
|
),
|
|
],
|
|
),
|
|
child: SafeArea(
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
child: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.green[600],
|
|
foregroundColor: Colors.white,
|
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
elevation: 2,
|
|
),
|
|
onPressed: () {
|
|
if (_validateSelection(
|
|
context,
|
|
selectedColor,
|
|
selectedWeight,
|
|
product,
|
|
)) {
|
|
// Handle Add to Cart
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text(
|
|
"Added $quantity x ${product.name} to cart",
|
|
),
|
|
backgroundColor: Colors.green[600],
|
|
action: SnackBarAction(
|
|
label: "View Cart",
|
|
textColor: Colors.white,
|
|
onPressed: () async {
|
|
await CartButtonHelper.addToCartAndNavigate(
|
|
context: context,
|
|
ref: ref,
|
|
product: product,
|
|
quantity: quantity,
|
|
selectedColor: selectedColor,
|
|
selectedWeight: selectedWeight,
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
},
|
|
child: const Text(
|
|
"Add to Cart",
|
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
bool _validateSelection(
|
|
BuildContext context,
|
|
String? selectedColor,
|
|
String? selectedWeight,
|
|
product,
|
|
) {
|
|
bool hasColorAttribute =
|
|
product.attributes?.any(
|
|
(attr) => attr.name?.toLowerCase() == "color",
|
|
) ??
|
|
false;
|
|
bool hasWeightAttribute =
|
|
product.attributes?.any(
|
|
(attr) =>
|
|
attr.name?.toLowerCase() == "weight" ||
|
|
attr.name?.toLowerCase() == "size",
|
|
) ??
|
|
false;
|
|
|
|
if (hasColorAttribute && selectedColor == null) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text("Please select a color"),
|
|
backgroundColor: Colors.red,
|
|
),
|
|
);
|
|
return false;
|
|
}
|
|
|
|
if (hasWeightAttribute && selectedWeight == null) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text("Please select size/weight"),
|
|
backgroundColor: Colors.red,
|
|
),
|
|
);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Color _getColorFromName(String colorName) {
|
|
if (colorName.startsWith("#") && colorName.length == 7) {
|
|
return Color(
|
|
int.parse(colorName.substring(1, 7), radix: 16) + 0xFF000000,
|
|
);
|
|
}
|
|
|
|
switch (colorName.toLowerCase()) {
|
|
case "red":
|
|
return Colors.red;
|
|
case "blue":
|
|
return Colors.blue;
|
|
case "green":
|
|
return Colors.green;
|
|
case "black":
|
|
return Colors.black;
|
|
case "white":
|
|
return Colors.white;
|
|
case "orange":
|
|
return Colors.orange;
|
|
case "yellow":
|
|
return Colors.yellow;
|
|
case "purple":
|
|
return Colors.purple;
|
|
case "pink":
|
|
return Colors.pink;
|
|
case "brown":
|
|
return Colors.brown;
|
|
default:
|
|
return Colors.grey;
|
|
}
|
|
}
|
|
}
|