What you'll build
In the final part you'll add an admin screen that only the shop owner can access. From here, the owner can add new products (with images uploaded to Firebase Storage), edit existing ones, toggle stock availability, and mark orders as shipped or delivered.
By the end of this part:
- A hidden admin route accessible only to a designated admin UID
- A product management screen: add, edit, and delete products
- Image upload using the device camera or gallery via Firebase Storage
- An order management screen with status update controls
Restrict admin access
The admin screen should only be accessible to one specific Firebase UID — the shop owner's account.
Add the owner's UID to your config file:
// lib/config.dart
const kPaystackPublicKey = 'pk_test_your_key_here';
const kAdminUid = 'REPLACE_WITH_OWNER_FIREBASE_UID';
To find the owner's UID: sign in with the owner account, then go to Firebase console → Authentication → Users and copy the UID from the list.
Add an isAdmin getter to your auth provider:
Add an isAdminProvider to lib/features/auth/auth_provider.dart that returns true if currentUser?.uid == kAdminUid, otherwise false.
Add the image upload packages
flutter pub add image_picker firebase_storage
For iOS, add the following to ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Used to take product photos</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Used to select product photos</string>
Build the admin product screen
Build the admin product management screen at lib/features/admin/admin_products_screen.dart. The screen shows a list of all products (regardless of stock status) with their name, price, and stock status. Each row has an edit icon and a delete icon. A FloatingActionButton opens an "Add product" bottom sheet with fields for: name, description, price (numeric input), category (dropdown: Dresses, Tops, Trousers, Accessories), sizes (multi-select chips: XS, S, M, L, XL), and stock status toggle. The bottom sheet also has an image section: a row of image thumbnails and an "Add photo" button. Tapping "Add photo" opens the device gallery using ImagePicker. Selected images are uploaded to Firebase Storage at products/{productId}/images/{filename} and the download URLs are saved to the product document. Tapping an existing product's edit icon opens the same bottom sheet pre-filled with the product's data. All writes go to Firestore's products collection. Deleting a product sets inStock: false rather than deleting the document (in case orders reference the product).
Build the admin orders screen
Build the admin orders screen at lib/features/admin/admin_orders_screen.dart. Show all orders from all users (the admin's Firestore rules allow this — add a rule in Part 4's security rules: `allow read, write: if request.auth.uid == kAdminUid`), sorted by createdAt descending. Each order row shows: customer name (from deliveryAddress.name), order date, total, item count, and a status dropdown. The dropdown has options: Pending, Paid, Shipped, Delivered. Changing the dropdown value immediately updates the order's status field in Firestore. Add a filter row at the top to show only orders of a specific status.
Add the admin Firestore rule
Update the Firestore security rules to allow the admin UID full access:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Admin has full access to everything
match /{document=**} {
allow read, write: if request.auth != null
&& request.auth.uid == 'REPLACE_WITH_OWNER_FIREBASE_UID';
}
// Products are public read
match /products/{productId} {
allow read: if true;
}
// Orders belong to their owner
match /orders/{orderId} {
allow read, write: if request.auth != null
&& request.auth.uid == resource.data.userId;
allow create: if request.auth != null
&& request.auth.uid == request.resource.data.userId;
}
}
}
Wire up the admin route
Update the router to include the admin route and protect it:
Update lib/router.dart. Add a /admin route that shows an AdminShell screen with two tabs: Products and Orders. In the router's redirect logic, if the user navigates to /admin and isAdminProvider is false (or the user is not signed in), redirect to /. The admin route should not appear in the bottom navigation bar — it is only accessible by navigating directly. Add a hidden entry point: in the AppBar (app_scaffold.dart), if isAdminProvider is true, show a small wrench icon in the actions that navigates to /admin.
Test the admin flow
- Sign in with the owner account
- The wrench icon should appear in the AppBar
- Tap it to open the admin screen
- Tap the + button to add a product — fill in all fields, select photos, tap Save
- The product should appear in the catalog immediately (Firestore stream)
- Switch to the Orders tab — existing orders should be visible
- Change an order's status to "Shipped" — the customer's Orders screen should update in real-time
- Sign out and sign in with a non-admin account — the wrench icon should not appear, and navigating to /admin manually should redirect to /
You've shipped it
That's the complete series. Here's what you built:
| Part | What was built |
|---|---|
| 1 | Flutter project, navigation shell, boutique theme |
| 2 | Firebase + Firestore, product catalog, product detail |
| 3 | Shopping cart with Riverpod state management |
| 4 | Firebase Auth — email/password and Google sign-in |
| 5 | Paystack checkout, order creation |
| 6 | Order history with real-time status updates |
| 7 | Owner admin screen — product and order management |
Every screen in this app was written by BlocWeave from plain-language prompts inside VS Code. The prompts in this series are a starting point — describe your own customisations and BlocWeave adapts the code to your exact needs.
Install BlocWeave from the VS Code Marketplace and start building.
BlocWeave