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
2. Progressive Disclosure Pattern
3. Incentive Visualization
4. Form Components Library
5. Mobile Optimization
6. Empty States & Guidance
Design Deliverables
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">m²</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
Phase 2: Core Form Components
Phase 3: Form Logic & State
Phase 4: Visual Feedback & Incentives
Phase 5: Smart Contract Integration
Phase 6: Testing & Optimization
Acceptance Criteria
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));
}
}
};
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
2. Progressive Disclosure Pattern
3. Incentive Visualization
4. Form Components Library
5. Mobile Optimization
6. Empty States & Guidance
Design Deliverables
Design Principles
Part 2: Frontend Implementation
Technical Stack
UI/UX Implementation
1. Form Integration
Position in submission flow:
Component structure:
2. Enhanced Impact Form Component
3. Form Sections with Progressive Disclosure
Section 1: Basic Metrics (Always visible first)
Section 2: Waste Details (Expand on tap)
Section 3: Additional Context (Optional, expand on tap)
4. Input Components
Location Type Selector:
Waste Type Multi-Select:
Area Input with Unit Toggle:
5. Smart Defaults & Auto-completion
6. Progress Indicator
7. Save as Draft
8. Data Validation
9. Bonus DCU Display
10. Hypercert Milestone Progress
11. Privacy Controls
Mobile Optimization
Responsive Design
Keyboard Handling
Implementation Tasks
Phase 1: Design & Structure
Phase 2: Core Form Components
Phase 3: Form Logic & State
Phase 4: Visual Feedback & Incentives
Phase 5: Smart Contract Integration
claimWithEnhancedData()contract functionPhase 6: Testing & Optimization
Acceptance Criteria
Analytics & Success Metrics
Track the following metrics:
Localization Support
Error Handling & Edge Cases