feat: implement and apply RestaurantBackground widget with vector pattern and set transparent backgrounds for history screens.

This commit is contained in:
Suherdy Yacob 2026-06-16 17:33:59 +07:00
parent 54688d23a9
commit 44c943b088
3 changed files with 291 additions and 4 deletions

View File

@ -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) {

View File

@ -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,

View 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;
}