Homeowner bulk job posting flow. Capture multiple photos, let AI organize them into separate jobs, review and edit, then batch submit.
CameraView component. useMassCapture().addPhoto(uri) on capture, startNewJobGroup() to begin a new job.
GalleryPicker multi-select. useMassCapture().addPhoto() called per selected image. Count badge updates live.
PhotoGrid component. useMassCapture().splitGroupAtPhoto(id) on scissor tap, removePhoto(id) on delete.
MassReviewScreen with detection overlay. useJobTypeDetection().detectForGroups() runs on mount, onProgress/onResult callbacks update each card.
JobReviewCard list. Expand/collapse per card. updateReviewCard(id, {...}) for title/description edits.
JobReviewCard expanded. onTitleChange, onDescriptionChange, onJobTypePress callbacks. JobTypeSelector modal on type tap.
MassReviewScreen confirmation state. handleSubmit(true) for post, handleSubmit(false) for drafts. validateCards() checks titles, descriptions, job types.
MassReviewScreen success state. createJobBatch result.successCount === result.totalCount triggers clearSession() and router.replace("/(poster)/jobs").
jobs — title, description, jobTypeId, status, propertyId, photos[], aiGenerated, isUrgentjobPhotos — jobId, storageId, localUri, width, height, order, groupIndexposterProperties — nickname, address, city, state, zipCode, posterIdjobTypes — name, categoryName, keywords[], icon, isActiveuseMassCapture() — session state, addPhoto, startNewJobGroup, splitGroupAtPhoto, removePhoto, finishCapture, finishOrganizing, updateReviewCard, setDetectionResult, setAddress, setPropertyId, clearSession, goBackuseJobTypeDetection() — detectForGroups, progress, isDetecting, getAllJobTypes. Callbacks: onProgress, onResult, onErroruseToast() — showToast({ message, type }) for validation errors, success, warningsposter.jobs.createJobBatch — propertyId?, address, city, state, zipCode, jobs[{title, description, jobTypeId, photos[], aiGenerated}], publishImmediatelyposter.properties.list — Returns all poster properties for property pickerAI Detection — Gemini 3 Flash analyzes photos per group. Returns jobTypeId, jobTypeName, confidence, reasoning, alternatives[], suggestedTitle, suggestedDescriptionAsyncStorage — Session state persisted locally via useMassCapture hook. Survives app restart until clearSession()