feat: implement and apply RestaurantBackground widget with vector pattern and set transparent backgrounds for history screens.
This commit is contained in:
parent
54688d23a9
commit
44c943b088
@ -5,6 +5,7 @@ import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../services/odoo_service.dart';
|
||||
import '../services/notification_service.dart';
|
||||
import '../services/theme_manager.dart';
|
||||
import '../widgets/restaurant_background.dart';
|
||||
import 'notifications_screen.dart';
|
||||
import 'loyalty_dashboard.dart';
|
||||
import 'branches_screen.dart';
|
||||
@ -201,11 +202,13 @@ class _MainShellState extends State<MainShell> {
|
||||
],
|
||||
),
|
||||
),
|
||||
child: RestaurantBackground(
|
||||
child: IndexedStack(
|
||||
index: _currentIndex,
|
||||
children: _pages,
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: NavigationBar(
|
||||
selectedIndex: _currentIndex,
|
||||
onDestinationSelected: (index) {
|
||||
|
||||
@ -80,10 +80,14 @@ class _OrdersScreenState extends State<OrdersScreen> {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
if (_isLoading) {
|
||||
return const Scaffold(body: Center(child: CircularProgressIndicator()));
|
||||
return const Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
body: Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
appBar: AppBar(title: const Text('Order & Points History')),
|
||||
body: RefreshIndicator(
|
||||
onRefresh: _fetchHistory,
|
||||
|
||||
280
lib/widgets/restaurant_background.dart
Normal file
280
lib/widgets/restaurant_background.dart
Normal file
@ -0,0 +1,280 @@
|
||||
import 'dart:math' as math;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// A custom background wrapper that renders a highly premium, subtle
|
||||
/// vector pattern of noodle bowls, wavy noodles, chopsticks, and spices (star anise/leaves)
|
||||
/// watermark in the background of the screen.
|
||||
class RestaurantBackground extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const RestaurantBackground({super.key, required this.child});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: CustomPaint(
|
||||
painter: NoodlePatternPainter(
|
||||
color: colorScheme.onSurface.withValues(alpha: 0.08),
|
||||
),
|
||||
),
|
||||
),
|
||||
child,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NoodlePatternPainter extends CustomPainter {
|
||||
final Color color;
|
||||
|
||||
NoodlePatternPainter({required this.color});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
// Use a fixed-seed Random generator so coordinates remain perfectly stable
|
||||
// on every repaint (preventing elements from flickering/moving).
|
||||
final random = math.Random(5758);
|
||||
|
||||
// Jittered grid parameters adjusted for larger scales
|
||||
const double stepX = 145.0;
|
||||
const double stepY = 145.0;
|
||||
|
||||
int index = 0;
|
||||
for (double y = 40; y < size.height; y += stepY) {
|
||||
final double startX = (index % 2 == 0) ? 35.0 : 100.0;
|
||||
for (double x = startX; x < size.width; x += stepX) {
|
||||
// Apply random jitter of up to +/- 30 pixels to x and y coordinates
|
||||
final double jitterX = (random.nextDouble() - 0.5) * 60.0;
|
||||
final double jitterY = (random.nextDouble() - 0.5) * 60.0;
|
||||
final double drawX = x + jitterX;
|
||||
final double drawY = y + jitterY;
|
||||
|
||||
// Skip drawing if the jittered offset pushes it outside the screen
|
||||
if (drawX < 0 ||
|
||||
drawX > size.width ||
|
||||
drawY < 0 ||
|
||||
drawY > size.height) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Random rotation between -0.6 and +0.6 radians
|
||||
final double rotation = (random.nextDouble() - 0.5) * 1.2;
|
||||
|
||||
// Random scale factor enlarged to range between 1.1x and 1.5x
|
||||
final double scale = 1.1 + random.nextDouble() * 0.4;
|
||||
|
||||
// Randomize the element's opacity slightly relative to the base color
|
||||
final double alphaScale = 0.6 + random.nextDouble() * 0.8;
|
||||
final elementColor = color.withValues(
|
||||
alpha: (color.alpha / 255.0 * alphaScale).clamp(0.02, 0.15),
|
||||
);
|
||||
|
||||
final paint = Paint()
|
||||
..color = elementColor
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 1.0
|
||||
..strokeCap = StrokeCap.round;
|
||||
|
||||
final fillPaint = Paint()
|
||||
..color = elementColor
|
||||
..style = PaintingStyle.fill;
|
||||
|
||||
// Randomly select one of the 3 restaurant/noodle categories to draw
|
||||
final int elementIndex = random.nextInt(3);
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(drawX, drawY);
|
||||
canvas.rotate(rotation);
|
||||
canvas.scale(scale);
|
||||
|
||||
if (elementIndex == 0) {
|
||||
_drawBowl(canvas, paint);
|
||||
} else if (elementIndex == 1) {
|
||||
_drawDrumstick(canvas, paint, fillPaint);
|
||||
} else {
|
||||
final vegIndex = random.nextInt(5);
|
||||
if (vegIndex == 0) {
|
||||
_drawMushroom(canvas, paint, fillPaint);
|
||||
} else if (vegIndex == 1) {
|
||||
_drawCarrot(canvas, paint, fillPaint);
|
||||
} else if (vegIndex == 2) {
|
||||
_drawBroccoli(canvas, paint, fillPaint);
|
||||
} else if (vegIndex == 3) {
|
||||
_drawChili(canvas, paint, fillPaint);
|
||||
} else {
|
||||
_drawTomato(canvas, paint, fillPaint);
|
||||
}
|
||||
}
|
||||
|
||||
canvas.restore();
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
void _drawBowl(Canvas canvas, Paint paint) {
|
||||
// Draw a noodle bowl outline
|
||||
final path = Path()
|
||||
..moveTo(-12, -4)
|
||||
..arcTo(Rect.fromLTWH(-12, -10, 24, 18), 0, 3.14159, false)
|
||||
..lineTo(-12, -4)
|
||||
..close();
|
||||
canvas.drawPath(path, paint);
|
||||
|
||||
// Rim lines
|
||||
canvas.drawLine(const Offset(-13, -4), const Offset(13, -4), paint);
|
||||
|
||||
// Steam/Noodles rising
|
||||
final steam = Path()
|
||||
..moveTo(-5, -6)
|
||||
..quadraticBezierTo(-7, -10, -5, -15)
|
||||
..moveTo(0, -6)
|
||||
..quadraticBezierTo(-2, -11, 0, -16)
|
||||
..moveTo(5, -6)
|
||||
..quadraticBezierTo(3, -10, 5, -15);
|
||||
canvas.drawPath(steam, paint);
|
||||
}
|
||||
|
||||
void _drawDrumstick(Canvas canvas, Paint paint, Paint fillPaint) {
|
||||
// Plump cartoon-style chicken drumstick with asymmetric meaty bulge
|
||||
final path = Path()
|
||||
// Bone shaft left
|
||||
..moveTo(-1.5, 3)
|
||||
..lineTo(-1.5, 9)
|
||||
// Left bone joint knob
|
||||
..cubicTo(-3.5, 9, -4.5, 11.5, -2.5, 13.5)
|
||||
..cubicTo(-1.0, 14.5, 0.0, 12.0, 0.0, 11.0)
|
||||
// Right bone joint knob
|
||||
..cubicTo(0.0, 12.0, 1.0, 14.5, 2.5, 13.5)
|
||||
..cubicTo(4.5, 11.5, 3.5, 9, 1.5, 9)
|
||||
// Bone shaft right
|
||||
..lineTo(1.5, 3)
|
||||
// Taper out to meaty part
|
||||
..lineTo(5.5, 0)
|
||||
// Asymmetric bulbous meat bulge (wide to the right, flatter on the left)
|
||||
..cubicTo(12.0, -3.5, 8.5, -12, 0, -12)
|
||||
..cubicTo(-6.0, -12, -7.0, -3.5, -5.5, 0)
|
||||
..close();
|
||||
|
||||
canvas.drawPath(path, paint);
|
||||
canvas.drawPath(path, fillPaint);
|
||||
}
|
||||
|
||||
void _drawChili(Canvas canvas, Paint paint, Paint fillPaint) {
|
||||
canvas.save();
|
||||
canvas.rotate(0.3); // Slight tilt for organic look
|
||||
final body = Path()
|
||||
..moveTo(-3, -7)
|
||||
..quadraticBezierTo(2, -7, 4, -3)
|
||||
..quadraticBezierTo(5, 3, -4, 9) // Pointy pepper tip
|
||||
..quadraticBezierTo(-3, 2, -3, -7)
|
||||
..close();
|
||||
canvas.drawPath(body, paint);
|
||||
canvas.drawPath(body, fillPaint);
|
||||
|
||||
// Stem at the top
|
||||
final stem = Path()
|
||||
..moveTo(0, -7)
|
||||
..quadraticBezierTo(1, -12, -3, -13);
|
||||
canvas.drawPath(stem, paint);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void _drawTomato(Canvas canvas, Paint paint, Paint fillPaint) {
|
||||
// Round tomato body
|
||||
final body = Path()
|
||||
..addOval(
|
||||
Rect.fromCenter(center: const Offset(0, 1), width: 14, height: 12),
|
||||
);
|
||||
canvas.drawPath(body, paint);
|
||||
canvas.drawPath(body, fillPaint);
|
||||
|
||||
// Star-shaped leafy top
|
||||
final leaves = Path()
|
||||
..moveTo(0, -5)
|
||||
..lineTo(-2, -8)
|
||||
..moveTo(0, -5)
|
||||
..lineTo(2, -8)
|
||||
..moveTo(0, -5)
|
||||
..lineTo(0, -9)
|
||||
..moveTo(0, -5)
|
||||
..quadraticBezierTo(-1, -7, -3.5, -6)
|
||||
..moveTo(0, -5)
|
||||
..quadraticBezierTo(1, -7, 3.5, -6);
|
||||
canvas.drawPath(leaves, paint);
|
||||
}
|
||||
|
||||
void _drawMushroom(Canvas canvas, Paint paint, Paint fillPaint) {
|
||||
// Cap
|
||||
final cap = Path()
|
||||
..moveTo(-9, 0)
|
||||
..arcTo(Rect.fromLTWH(-9, -8, 18, 11), 3.14159, 3.14159, false)
|
||||
..close();
|
||||
canvas.drawPath(cap, paint);
|
||||
canvas.drawPath(cap, fillPaint);
|
||||
|
||||
// Stalk
|
||||
final stalk = Path()
|
||||
..moveTo(-3, 0)
|
||||
..lineTo(-3, 6)
|
||||
..quadraticBezierTo(0, 8, 3, 6)
|
||||
..lineTo(3, 0)
|
||||
..close();
|
||||
canvas.drawPath(stalk, paint);
|
||||
canvas.drawPath(stalk, fillPaint);
|
||||
}
|
||||
|
||||
void _drawCarrot(Canvas canvas, Paint paint, Paint fillPaint) {
|
||||
canvas.save();
|
||||
canvas.rotate(-0.785); // Point carrot downwards
|
||||
|
||||
// Carrot cone root body
|
||||
final root = Path()
|
||||
..moveTo(-4, -6)
|
||||
..lineTo(4, -6)
|
||||
..lineTo(0, 9) // tip
|
||||
..close();
|
||||
canvas.drawPath(root, paint);
|
||||
canvas.drawPath(root, fillPaint);
|
||||
|
||||
// Leaves at the top
|
||||
final leaves = Path()
|
||||
..moveTo(-2, -6)
|
||||
..quadraticBezierTo(-4, -12, -6, -10)
|
||||
..moveTo(0, -6)
|
||||
..quadraticBezierTo(0, -14, 2, -12)
|
||||
..moveTo(2, -6)
|
||||
..quadraticBezierTo(4, -11, 6, -9);
|
||||
canvas.drawPath(leaves, paint);
|
||||
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void _drawBroccoli(Canvas canvas, Paint paint, Paint fillPaint) {
|
||||
// Stem
|
||||
final stem = Path()
|
||||
..moveTo(-2.5, 2)
|
||||
..lineTo(-2.5, 8)
|
||||
..quadraticBezierTo(0, 10, 2.5, 8)
|
||||
..lineTo(2.5, 2)
|
||||
..close();
|
||||
canvas.drawPath(stem, paint);
|
||||
canvas.drawPath(stem, fillPaint);
|
||||
|
||||
// Crown cloud shape
|
||||
final crown = Path()
|
||||
..moveTo(-7, 2)
|
||||
..cubicTo(-11, 2, -11, -5, -5, -5)
|
||||
..cubicTo(-5, -11, 5, -11, 5, -5)
|
||||
..cubicTo(11, -5, 11, 2, 7, 2)
|
||||
..close();
|
||||
canvas.drawPath(crown, paint);
|
||||
canvas.drawPath(crown, fillPaint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user