Gemini App of Techdoc
Gemini App of Techdoc
Leveraging
20 years of experience, let's structure this into a robust Flutter frontend and a scalable PHP/PostgreSQL
backend, focusing on a premium, innovative UI/UX.
1. Clarity & Simplicity: Reduce cognitive load at every step. Guide the user naturally.
2. Efficiency: Minimize taps and required inputs. Pre-fill where possible.
3. Feedback & Transparency: Keep the user informed about processes (uploads, loading, status) and
choices.
4. Aesthetics & Polish: Use smooth animations, high-quality visuals, and consistent design language.
5. Trust & Security: Visually reassure the user about data privacy and process integrity.
lib/
├── main.dart
├── core/ # Core utilities, constants, themes, base classes
│ ├── theme/
│ ├── constants/
│ ├── utils/
│ └── network/ # API client setup (e.g., Dio)
├── features/ # Feature-based modules
│ ├── auth/
│ │ ├── presentation/
│ │ │ ├── pages/ # SignInScreen.dart
│ │ │ ├── widgets/ # GoogleSignInButton.dart, AppleSignInButton.dart
│ │ │ └── bloc/ # AuthBloc, AuthState, AuthEvent
│ │ └── data/ # Repositories, DataSources (interact with backend)
│ ├── service_selection/
│ │ ├── presentation/
│ │ │ ├── pages/ # ServiceSelectionScreen.dart
│ │ │ └── widgets/ # ServiceTab.dart, TrackOrderButton.dart
│ │ └── ... (bloc, data)
│ ├── hardware_flow/ # Covers Device -> Brand -> Issue -> Media -> Schedule ->
Review
│ │ ├── presentation/
│ │ │ ├── pages/ # DeviceSelectionScreen.dart, BrandSelectionScreen.dart, ...
ReviewScreen.dart
│ │ │ ├── widgets/ # DeviceGridItem.dart, BrandListItem.dart,
IssueDropdown.dart, MediaUploader.dart, CalendarView.dart, SlotSelector.dart,
SummaryCard.dart
│ │ │ └── cubit/ # HardwareFlowCubit (manages state across the multi-step
hardware flow)
│ │ └── ... (data)
│ ├── software_flow/
│ │ ├── presentation/
│ │ │ ├── pages/ # SoftwareContactScreen.dart
│ │ │ └── ... (widgets, bloc)
│ │ └── ... (data)
│ ├── tracking/
│ │ ├── presentation/
│ │ │ ├── pages/ # DeviceStatusScreen.dart
│ │ │ └── widgets/ # StatusStepper.dart, MapView.dart (if real-time GPS)
│ │ └── ... (bloc, data)
│ └── profile/
│ ├── presentation/
│ │ ├── pages/ # UserProfileScreen.dart
│ │ └── ... (widgets, bloc)
│ └── ... (data)
└── app_router.dart # Navigation configuration
content_copydownload
Use code with caution.
UI: Minimalist design. App logo prominently displayed. Clear heading like "Welcome" or "Get Started".
o Buttons: Large, easily tappable "Sign in with Google" and "Sign in with Apple" buttons using
official branding guidelines/icons (sign_in_with_apple, google_sign_in packages).
Place them centrally.
o Alternative: Consider only showing these two buttons initially. If a user needs a different
method later (perhaps for corporate accounts), that could be a separate flow. Avoid clutter.
o Feedback: Use CircularProgressIndicator overlaid during the OAuth process. Display
clear error messages via SnackBar or a dialog on failure (e.g., "Authentication failed. Please
try again.").
UX: Smooth fade-in animation. Instant visual feedback on button press. Seamless transition to the
native OAuth flow.
Navigation:
o Success: context.go('/profile') or context.go('/service-selection') (Decide
initial landing page post-login). Use pushReplacement logic to prevent going back to login.
o Failure: Remain on the page, show error message.
UI:
o AppBar: Clean AppBar with the app title. Potentially place the "Track My Order" button here
for high visibility, perhaps with an icon
(e.g., Icons.location_pin or Icons.receipt_long).
o Tabs: Use a TabBar with two distinct tabs: "Software Services" and "Hardware Services".
Innovation: Instead of plain text, use Card widgets within the TabBarView for each
service. Each card has:
A high-quality, vibrant, slightly abstract image representing
software/hardware.
Clear, concise title ("Software Support", "Hardware Repair").
Short description.
Subtle hover/press effect (e.g., scale transform, shadow elevation change).
o Track My Order: If not in AppBar, a clearly
labeled OutlinedButton or TextButton positioned consistently (e.g., below tabs, above
footer).
UX: Smooth tab transitions (FadeTransition or SlideTransition). Images load efficiently
(use FadeInImage with placeholders). Tapping a service card provides immediate visual feedback
before navigating.
Navigation:
o Software Tab Tap: context.go('/software-contact')
o Hardware Tab Tap: context.go('/hardware-device-selection')
o Track My Order Tap: context.go('/track-order')
UI:
o AppBar: Title like "Select Brand". Back button. Maybe show selected device type subtly (e.g.,
"Select Brand for Laptop").
o List/Grid: Use ListView.builder or GridView.builder depending on the number of
brands.
o Item: Custom widget (BrandListItem) showing:
High-quality brand logo (Image.network with caching via cached_network_image).
Brand name (as fallback or supplementary).
Use InkWell and perhaps MouseRegion (for web/desktop) for hover effects (slight
zoom, border, or background change).
o Innovation: Consider a sticky header/search bar if the list is very long. Fetch brands
dynamically from the backend.
UX: Logos should be clear and crisp. Fast loading. Smooth scrolling. Clear visual feedback on
selection.
Navigation: On tap: context.go('/hardware-issue-selection', extra: {'deviceType':
deviceType, 'brand': selectedBrand}) (passing data forward).
UI:
o AppBar: Title "Describe the Issue". Back button.
o Form: Use Form widget for validation.
AI-Powered Dropdown:
Use a package like flutter_typeahead or dropdown_search.
Fetch common issues from the backend based on device/brand.
As the user types, filter suggestions intelligently (simple string matching or
more advanced backend logic).
Label: "Select Issue Category (or type to search)".
Device Details: TextFormField widgets for:
Device Model (Label: "Model Name/Number")
Serial Number (Label: "Serial Number (Optional, helps speed up service)").
Add info tooltip explaining where to find it.
Issue Description (TextField with maxLines: 3 or more. Label: "Detailed
Issue Description").
Progress Indicator: Could use a Stepper widget visually at the top to show
progress through the hardware flow (Device -> Brand -> Issue -> Media -> Schedule -
> Review).
UX: The "AI" dropdown should feel responsive and helpful, not cumbersome. Provide clear validation
messages (validator property on fields). Use TextInputAction.next to move focus logically.
Navigation: On valid form submission (e.g., via an "Next" or "Continue"
button): context.go('/hardware-media-upload', extra: { ...allCollectedData }). Use
a Cubit/Bloc to hold the state of this multi-step flow.
UI:
o AppBar: Title "Upload Photos/Video". Back button. Stepper updated.
o Instructions: Clear text: "Upload up to 4 images and 1 video (max 45s) showing the issue."
o Image Slots: Use a Wrap or Row of 4 placeholder widgets (e.g., DottedBorder boxes
with Icons.add_a_photo). When an image is selected/uploaded, replace placeholder with
a Stack containing the thumbnail (Image.file or Image.network after upload) and a small
'X' button to remove it.
o Video Slot: Similar placeholder (Icons.videocam) / thumbnail display.
o Upload
Progress: Show LinearProgressIndicator or CircularProgressIndicator during
upload, possibly overlaid on the thumbnail.
o AI Suggestions: Display contextual tips dynamically near the upload buttons or as
dismissible banners (e.g., "Tip: Ensure good lighting for clear photos.", "Suggestion: Capture
the serial number if visible."). These can be static or fetched based on the issue type.
UX: Use image_picker package. Handle permissions gracefully. Clear feedback on upload
success/failure for each file. Visual indication of limits (e.g., disable 'add' button when 4 images are
present). Compress images client-side (flutter_image_compress) before upload to save
bandwidth/time. Validate video duration.
Navigation: "Next" button enabled only after minimum requirements met (e.g., at least one
image/video, depending on rules). context.go('/hardware-appointment-scheduling', extra:
{ ...allDataIncludingMediaUrls }).
UI:
o AppBar: Title "Schedule Pickup". Back button. Stepper updated.
o Calendar: Use table_calendar package or similar.
Highlight today's date.
Visually disable dates outside the 72-hour rolling window from tomorrow.
Mark dates with available slots. Fetch availability from GET /appointment/slots.
o Time Slots: Below the calendar, display available time slots for the selected date in
a Wrap or GridView.
Show slots like "9:00 AM - 11:00 AM".
Visually disable/grey out booked slots.
Real-time Counter: Display "X slots available for [Date]" - update this when
fetching/re-fetching slots. Maybe a subtle refresh button or automatic polling.
UX: Selecting a date should instantly load/display its slots. Selecting a time slot should be clear (e.g.,
change background color). Smooth transitions between date selections. Prevent selection of
unavailable dates/slots.
Navigation: "Next" button enabled only after a valid date and time slot are
selected. context.go('/hardware-review', extra: { ...allDataIncludingTimeSlot }).
UI:
o AppBar: Title "Review & Confirm". Back button. Stepper shows completion.
o Summary: Use a ListView with clearly sectioned data (Card or ListTile with dividers):
Service Type (Hardware)
Device & Brand
Issue Details (Category, Description, Model, Serial)
Uploaded Media (Thumbnails - tapping could show full screen)
Scheduled Pickup Slot (Date & Time)
User Contact Info (from profile, maybe allow editing here?)
o Edit: Provide "Edit" buttons next to each section, navigating back to the relevant screen while
preserving the flow state (context.go('/hardware-issue-selection', editMode:
true)).
o Submit Button: Large, prominent ElevatedButton labeled "Confirm Appointment".
UX: Easy scannability is key. Ensure all collected data is presented clearly. The edit functionality adds
flexibility. Show a loading indicator on submit.
Navigation:
o On Submit button tap: Call POST /appointment/create with all data.
o On Success: Navigate to a dedicated Confirmation Screen (context.go('/appointment-
confirmation', extra: {appointmentDetails})). Show success message
(SnackBar or dialog).
o On Failure: Show specific error message (e.g., "Selected slot just became unavailable. Please
choose another.", "Failed to create appointment. Please try again."). Potentially navigate back
to scheduling page.
UI:
o AppBar: Title "Track My Order".
o List: If multiple active orders, show a list. Tapping one leads to details.
o Detail View:
Show device info & issue summary.
Status Display: Use a vertical Stepper widget (or custom timeline view) showing
stages: "Booked", "Pickup Scheduled [Date/Time]", "Picked-Up", "Inward Scan @
Facility", "Diagnosing", "Repairing", "Repair Complete", "Out for Delivery",
"Delivered". Highlight the current status.
Timestamps: Show dates/times for completed steps.
Map Integration (Optional): If live delivery tracking (GPS) is active, embed
a google_maps_flutter widget showing the agent's location.
UX: Clear visual progression of the repair status. Fetch status from GET /device/{id}/status on
screen load and potentially periodically or via push notification trigger. Map view adds significant value
during delivery.
-- Brands
CREATE TABLE brands (
id SERIAL PRIMARY KEY,
name VARCHAR(100) UNIQUE NOT NULL,
logo_key VARCHAR(255) NULL -- Key for logo in storage
);
-- OTPs
CREATE TABLE otps (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
appointment_id UUID NOT NULL REFERENCES appointments(id) ON DELETE CASCADE,
otp_hash VARCHAR(255) NOT NULL, -- Store hashed OTP
purpose VARCHAR(50) NOT NULL, -- e.g., 'pickup_verification',
'delivery_confirmation'
expires_at TIMESTAMPTZ NOT NULL,
verified_at TIMESTAMPTZ NULL,
attempts SMALLINT DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_otps_appointment_id_purpose ON otps(appointment_id, purpose);
CREATE INDEX idx_otps_expires_at ON otps(expires_at);
-- Notifications Log
CREATE TYPE notification_channel AS ENUM ('fcm', 'sms', 'email');
CREATE TYPE notification_status AS ENUM ('pending', 'sent', 'failed', 'delivered',
'read'); -- Delivery/Read status might come via webhooks
CREATE TABLE notifications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id),
appointment_id UUID NULL REFERENCES appointments(id),
channel notification_channel NOT NULL,
recipient VARCHAR(255) NOT NULL, -- Email, Phone, FCM Token
message TEXT NOT NULL,
status notification_status NOT NULL DEFAULT 'pending',
scheduled_at TIMESTAMPTZ NULL, -- For delayed notifications
sent_at TIMESTAMPTZ NULL,
error_message TEXT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_notifications_user_id ON notifications(user_id);
CREATE INDEX idx_notifications_status ON notifications(status);
content_copydownload
Use code with caution.SQL
1. Sign Up/In: Flutter uses OAuth packages -> Calls Backend /auth/{provider}/callback ->
Backend validates, creates/finds user, returns API token -> Flutter stores token, navigates to Service
Selection.
2. Service/Device Selection: Flutter UI -> Navigation logic passes selections. Hardware flow uses
Cubit/Bloc to maintain state.
3. Issue/Media: Flutter UI -> Fetches issue suggestions (GET /issues?q=...) -> Collects form data ->
Uploads media (POST /appointments/{id}/media) -> Backend stores media on S3, returns
keys/URLs -> Flutter adds URLs to flow state.
4. Scheduling: Flutter UI -> Fetches slots (GET /appointments/slots) -> User selects -> Flutter adds
to flow state.
5. Review & Confirm: Flutter displays summary from flow state -> User submits -> Flutter sends all data
(POST /appointments) -> Backend validates everything (incl. final slot check), creates appointment,
triggers notifications (queued).
6. OTP & Pickup: Backend generates secure exec link (VerificationService) -> Backend generates
OTP (POST /internal/.../otp/generate) upon link verification -> Triggers SMS/Push -> Flutter
user sees OTP request / Exec enters OTP -> Backend verifies (POST
/appointments/{id}/otp/verify).
7. Tracking & Notifications: Backend updates status (POST /internal/.../status) -> Triggers
Notifications (FCM, SMS, Email via Queue) -> Flutter receives push notification, updates UI -> Flutter
fetches latest status timeline (GET /appointments/{id}/status) -> Flutter fetches live location
(GET /appointments/{id}/delivery/track) if applicable.
This detailed structure provides a robust foundation for building a high-quality, user-centric repair service
application using Flutter and PHP/PostgreSQL, incorporating innovative UX elements and strong backend
practices.