Skip to content
This repository was archived by the owner on Sep 17, 2026. It is now read-only.
This repository was archived by the owner on Sep 17, 2026. It is now read-only.

Enhanced Impact Form UI/UX & Figma Design Updates #69

Description

@LuminaEnvision

Overview

Implement optional detailed impact data collection form with intuitive UX and update Figma designs for mobile-first cleanup submission flow.

Part 1: Figma Design Updates

Design File

Figma: DeCleanup Network

Design Tasks

1. Enhanced Submission Flow Screens

  • Design "Enhanced Impact Report" option screen after photo upload
  • Create multi-step form layout with progress indicator
  • Design input components for each data field (area, weight, waste types, etc.)
  • Create "Quick Select" buttons for common waste types and locations
  • Design mobile keyboard-friendly number inputs
  • Add visual feedback for completed sections

2. Progressive Disclosure Pattern

  • Design collapsed state: "Add detailed impact data (+5 DCU bonus)"
  • Design expanded state with form sections
  • Create smooth transition animations
  • Design section headers with completion checkmarks

3. Incentive Visualization

  • Design bonus badge: "+5 DCU for Enhanced Report"
  • Create "Verified Impact Report" badge for completed submissions
  • Design Hypercert milestone progress indicator (X/10 cleanups)
  • Create celebration modal for reaching 10-cleanup milestone

4. Form Components Library

  • Location type selector (beach, park, street, forest, waterway)
  • Waste type multi-select with icons
  • Area input with unit toggle (m² / ft²)
  • Weight input with unit toggle (kg / lbs)
  • Duration picker (hours + minutes)
  • Bags filled stepper control
  • Text area for observations

5. Mobile Optimization

  • Ensure all inputs are thumb-friendly (min 44px touch targets)
  • Design single-column layout for mobile
  • Create bottom sheet pattern for multi-selects
  • Optimize for one-handed use
  • Add "Save Draft" functionality

6. Empty States & Guidance

  • Design helper text for each field explaining impact
  • Create example submissions for reference
  • Design tooltip system for field explanations
  • Add visual guidelines (e.g., "1 standard trash bag ≈ 2kg")

Design Deliverables

  • Complete form flow screens (6-8 screens)
  • Component library for form inputs
  • Animation specifications
  • Mobile and desktop responsive variants
  • Dark mode versions (if applicable)

Design Principles

  • Mobile-first: Design for smallest screens first
  • Progressive: Basic submission easy, enhanced optional
  • Clear incentives: Show bonus DCU prominently
  • Quick completion: Most fields optional, smart defaults
  • Visual feedback: Show progress and impact clearly

Part 2: Frontend Implementation

Technical Stack

  • React
  • TypeScript
  • Tailwind CSS (core utility classes only)
  • Form library: React Hook Form
  • Wallet integration: existing context

UI/UX Implementation

1. Form Integration

Position in submission flow:

Photo upload → Basic details → [NEW] Enhanced Impact (Optional) → Review → Submit

Component structure:

<CleanupSubmissionFlow>
  <PhotoUpload />
  <BasicDetails />
  <EnhancedImpactForm optional />  {/* NEW */}
  <ReviewSubmission />
  <SubmitButton />
</CleanupSubmissionFlow>

2. Enhanced Impact Form Component

interface EnhancedImpactFormProps {
  onComplete: (data: EnhancedImpactData) => void;
  onSkip: () => void;
}

const EnhancedImpactForm: React.FC<EnhancedImpactFormProps> = ({
  onComplete,
  onSkip
}) => {
  const [isExpanded, setIsExpanded] = useState(false);
  
  return (
    <div className="enhanced-impact-section">
      {!isExpanded ? (
        <button onClick={() => setIsExpanded(true)} className="expand-btn">
          <span>📊 Add detailed impact data</span>
          <span className="bonus-badge">+5 DCU bonus</span>
        </button>
      ) : (
        <FormSections onComplete={onComplete} />
      )}
      <button onClick={onSkip} className="skip-btn">
        Skip (continue with basic submission)
      </button>
    </div>
  );
};

3. Form Sections with Progressive Disclosure

Section 1: Basic Metrics (Always visible first)

  • Area cleaned (m² or ft²)
  • Location type (visual selector with icons)
  • Estimated weight (kg or lbs)
  • Number of bags

Section 2: Waste Details (Expand on tap)

  • Waste types (multi-select chips)
  • Duration (hour + minute picker)

Section 3: Additional Context (Optional, expand on tap)

  • Environmental observations (text area)
  • Prevention suggestions (text area)
  • Equipment used (multi-select)
  • Safety measures (multi-select)

4. Input Components

Location Type Selector:

const locationTypes = [
  { id: 'beach', icon: '🏖️', label: 'Beach' },
  { id: 'park', icon: '🌳', label: 'Park' },
  { id: 'street', icon: '🛣️', label: 'Street' },
  { id: 'forest', icon: '🌲', label: 'Forest' },
  { id: 'waterway', icon: '💧', label: 'Waterway' },
];

<div className="grid grid-cols-2 gap-2">
  {locationTypes.map(type => (
    <button
      key={type.id}
      onClick={() => setValue('locationType', type.id)}
      className={selected === type.id ? 'selected' : ''}
    >
      <span className="text-2xl">{type.icon}</span>
      <span>{type.label}</span>
    </button>
  ))}
</div>

Waste Type Multi-Select:

const wasteTypes = [
  'Plastic Bottles',
  'Cigarette Butts',
  'Food Packaging',
  'Glass',
  'Metal Cans',
  'Paper/Cardboard',
  'Hazardous Materials',
  'Other'
];

<div className="flex flex-wrap gap-2">
  {wasteTypes.map(type => (
    <Chip
      key={type}
      label={type}
      selected={selected.includes(type)}
      onToggle={() => toggleWasteType(type)}
    />
  ))}
</div>

Area Input with Unit Toggle:

<div className="flex gap-2">
  <input
    type="number"
    value={area}
    onChange={(e) => setArea(e.target.value)}
    placeholder="0"
    className="flex-1"
  />
  <select value={unit} onChange={(e) => setUnit(e.target.value)}>
    <option value="sqm"></option>
    <option value="sqft">ft²</option>
  </select>
</div>
<p className="helper-text">Approximate area cleaned</p>

5. Smart Defaults & Auto-completion

// Auto-populate based on location and time
useEffect(() => {
  if (photos.length > 0) {
    // Extract timestamp from photo metadata
    const timestamp = extractPhotoTimestamp(photos[0]);
    setValue('timestamp', timestamp);
    
    // Estimate duration from photo timestamps
    if (photos.length >= 2) {
      const duration = calculateDuration(photos[0], photos[photos.length - 1]);
      setValue('durationMinutes', duration);
    }
  }
}, [photos]);

// Auto-generate scope of work
useEffect(() => {
  if (locationType && wasteTypes.length > 0) {
    const scope = `${locationType} ${wasteTypes.join(', ')} removal`;
    setValue('scopeOfWork', scope);
  }
}, [locationType, wasteTypes]);

6. Progress Indicator

const ProgressIndicator = ({ currentStep, totalSteps, completedFields }) => (
  <div className="progress-bar">
    <div className="progress-fill" style={{ width: `${(currentStep / totalSteps) * 100}%` }} />
    <span className="progress-text">
      {completedFields}/{totalSteps} fields completed
    </span>
  </div>
);

7. Save as Draft

const saveDraft = async (data: Partial<EnhancedImpactData>) => {
  try {
    await window.storage.set(
      `draft:${userAddress}:${Date.now()}`,
      JSON.stringify(data)
    );
    toast.success('Draft saved!');
  } catch (error) {
    console.error('Failed to save draft:', error);
  }
};

// Auto-save every 30 seconds
useEffect(() => {
  const interval = setInterval(() => {
    if (isDirty) {
      saveDraft(getValues());
    }
  }, 30000);
  return () => clearInterval(interval);
}, [isDirty]);

8. Data Validation

const schema = z.object({
  areaCleaned: z.number().min(1).max(1000000).optional(),
  locationType: z.enum(['beach', 'park', 'street', 'forest', 'waterway']).optional(),
  wasteTypes: z.array(z.string()).optional(),
  estimatedWeight: z.number().min(0).max(10000).optional(),
  bagsFilled: z.number().min(0).max(255).optional(),
  durationMinutes: z.number().min(1).max(1440).optional(),
});

// Validation with helpful error messages
const { register, handleSubmit, formState: { errors } } = useForm({
  resolver: zodResolver(schema),
});

9. Bonus DCU Display

const BonusBadge = () => (
  <div className="bonus-badge">
    <span className="bonus-icon">🎁</span>
    <div className="bonus-text">
      <strong>+5 DCU Bonus</strong>
      <small>Complete enhanced form</small>
    </div>
  </div>
);

10. Hypercert Milestone Progress

const HypercertProgress = ({ userCleanups }) => {
  const progress = userCleanups % 10;
  const nextMilestone = Math.ceil(userCleanups / 10) * 10;
  
  return (
    <div className="hypercert-progress">
      <div className="progress-circle">
        <CircularProgress value={(progress / 10) * 100} />
        <span className="progress-number">{progress}/10</span>
      </div>
      <div className="progress-info">
        <p className="font-semibold">Next Hypercert in {10 - progress} cleanups</p>
        <p className="text-sm text-gray-600">
          Permanent impact certificate at {nextMilestone} cleanups
        </p>
      </div>
    </div>
  );
};

11. Privacy Controls

const PrivacySettings = ({ settings, onChange }) => (
  <div className="privacy-settings">
    <h4>Privacy Controls</h4>
    <label>
      <input
        type="checkbox"
        checked={settings.shareLocationData}
        onChange={(e) => onChange('shareLocationData', e.target.checked)}
      />
      Share location data with partners
    </label>
    <label>
      <input
        type="checkbox"
        checked={settings.includeInAnalytics}
        onChange={(e) => onChange('includeInAnalytics', e.target.checked)}
      />
      Include in anonymized analytics
    </label>
    <p className="text-xs text-gray-500">
      Your data helps us measure global impact and attract corporate sponsors
    </p>
  </div>
);

Mobile Optimization

Responsive Design

/* Mobile-first approach */
.enhanced-impact-form {
  padding: 1rem;
}

/* Single column on mobile */
.form-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}

/* Two columns on tablet+ */
@media (min-width: 768px) {
  .form-grid {
    grid-template-columns: 1fr 1fr;
  }
}

/* Touch-friendly targets */
.form-button,
.form-input,
.chip {
  min-height: 44px;
  min-width: 44px;
}

Keyboard Handling

// Optimize for mobile keyboards
<input
  type="number"
  inputMode="decimal"  // Shows decimal keyboard on mobile
  pattern="[0-9]*"
  placeholder="0"
/>

// Prevent zoom on input focus (iOS)
<input style={{ fontSize: '16px' }} />

Implementation Tasks

Phase 1: Design & Structure

  • Complete Figma designs for all form screens
  • Create component library in Figma
  • Get design approval
  • Export design assets and specifications

Phase 2: Core Form Components

  • Build location type selector
  • Build waste type multi-select
  • Build number inputs with unit toggles
  • Build duration picker
  • Build text areas for context
  • Build privacy settings toggle

Phase 3: Form Logic & State

  • Implement form state management (React Hook Form)
  • Add validation with error messages
  • Implement smart defaults and auto-completion
  • Add save draft functionality
  • Integrate with existing submission flow

Phase 4: Visual Feedback & Incentives

  • Add progress indicator
  • Implement bonus DCU badge
  • Create Hypercert milestone progress widget
  • Build celebration modal for milestones
  • Add "Verified Impact Report" badge to submissions

Phase 5: Smart Contract Integration

  • Connect form submission to claimWithEnhancedData() contract function
  • Handle enhanced data bonus minting
  • Display transaction confirmations
  • Error handling for failed transactions

Phase 6: Testing & Optimization

  • Mobile responsiveness testing (iOS & Android)
  • Accessibility testing (screen readers, keyboard navigation)
  • Performance optimization (lazy loading, code splitting)
  • User testing with 5-10 real users
  • A/B test completion rates with/without bonus incentive

Acceptance Criteria

  • Form integrates seamlessly into existing submission flow
  • All fields capture data correctly
  • Mobile UX smooth with no zoom/scroll issues
  • Save draft works correctly
  • Bonus DCU (+5) displays prominently
  • Hypercert progress (X/10) visible on dashboard
  • Privacy controls function properly
  • Form submission triggers smart contract correctly
  • Enhanced submissions get "Verified Impact Report" badge
  • Completion rates improve by 20%+ vs basic submission

Analytics & Success Metrics

Track the following metrics:

  • Enhanced form completion rate
  • Average time to complete enhanced form
  • Most commonly selected waste types and locations
  • Correlation between enhanced data and user retention
  • Bonus DCU claimed vs total submissions
  • User feedback on form UX

Localization Support

// Unit conversion for international users
const convertUnits = (value: number, from: string, to: string) => {
  const conversions = {
    'sqm_to_sqft': value * 10.764,
    'sqft_to_sqm': value / 10.764,
    'kg_to_lbs': value * 2.205,
    'lbs_to_kg': value / 2.205,
  };
  return conversions[`${from}_to_${to}`] || value;
};

// Auto-detect user's preferred units
const preferredUnits = useMemo(() => {
  const locale = navigator.language;
  return locale.startsWith('en-US') 
    ? { area: 'sqft', weight: 'lbs' }
    : { area: 'sqm', weight: 'kg' };
}, []);

Error Handling & Edge Cases

// Handle offline submissions
const submitWithOfflineSupport = async (data) => {
  try {
    await submitToBlockchain(data);
  } catch (error) {
    if (!navigator.onLine) {
      // Save to local storage for later sync
      await saveOfflineSubmission(data);
      toast.info('Saved offline. Will sync when connected.');
    } else {
      toast.error('Submission failed. Please try again.');
    }
  }
};

// Handle incomplete drafts
const recoverDrafts = async () => {
  const draftKeys = await window.storage.list('draft:' + userAddress);
  if (draftKeys.keys.length > 0) {
    const shouldRecover = confirm('Found saved draft. Continue editing?');
    if (shouldRecover) {
      const draft = await window.storage.get(draftKeys.keys[0]);
      loadDraftData(JSON.parse(draft.value));
    }
  }
};

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    • Status
      💡 Ideas

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions