a a vibe-coded abomination experiment of a fragrance review platform built on the atmosphere. drydown.social
at main 128 lines 3.8 kB view raw
1import { calculateElapsedHours } from './reviewUtils' 2 3export interface EditValidationResult { 4 canEditStage1: boolean 5 canEditStage2: boolean 6 canEditStage3: boolean 7 canAddStage2: boolean 8 canAddStage3: boolean 9 canEditText: boolean 10 canChangeFragrance: boolean 11 error?: string 12} 13 14/** 15 * Determines what stages can be edited based on review state and elapsed time 16 */ 17export function validateEditPermissions(review: any): EditValidationResult { 18 const elapsed = calculateElapsedHours(review.createdAt) 19 20 // Text and fragrance can ALWAYS be edited 21 const canEditText = true 22 const canChangeFragrance = true 23 24 // After 24 hours, ratings/stages cannot be edited 25 if (elapsed >= 24) { 26 return { 27 canEditStage1: false, 28 canEditStage2: false, 29 canEditStage3: false, 30 canAddStage2: false, 31 canAddStage3: false, 32 canEditText, 33 canChangeFragrance, 34 error: 'Stage ratings cannot be edited after 24 hours' 35 } 36 } 37 38 const hasStage1 = !!(review.openingRating && review.openingProjection) 39 const hasStage2 = !!(review.drydownRating && review.midProjection && review.sillage) 40 const hasStage3 = !!(review.endRating && review.complexity && review.longevity && review.overallRating) 41 42 // Stage 1 can always be edited within 24 hours 43 const canEditStage1 = hasStage1 44 45 // Stage 2 can be edited if it exists, or added after 1.5 hours 46 const canEditStage2 = hasStage2 47 const canAddStage2 = !hasStage2 && elapsed >= 1.5 48 49 // Stage 3 can be edited if it exists, or added after 4 hours 50 const canEditStage3 = hasStage3 51 const canAddStage3 = !hasStage3 && elapsed >= 4 52 53 return { 54 canEditStage1, 55 canEditStage2, 56 canEditStage3, 57 canAddStage2, 58 canAddStage3, 59 canEditText, 60 canChangeFragrance 61 } 62} 63 64/** 65 * Validates that a stage update is allowed based on timing and current state 66 */ 67export function validateStageUpdate( 68 review: any, 69 stage: 'stage1' | 'stage2' | 'stage3' 70): { valid: boolean; error?: string } { 71 const permissions = validateEditPermissions(review) 72 73 if (permissions.error) { 74 return { valid: false, error: permissions.error } 75 } 76 77 if (stage === 'stage1') { 78 // Stage 1 can always be edited within 24 hours 79 if (!permissions.canEditStage1) { 80 return { valid: false, error: 'Stage 1 cannot be edited after 24 hours' } 81 } 82 } 83 84 if (stage === 'stage2') { 85 if (!permissions.canEditStage2 && !permissions.canAddStage2) { 86 const elapsed = calculateElapsedHours(review.createdAt) 87 if (elapsed < 1.5) { 88 const minsRemaining = Math.ceil((1.5 - elapsed) * 60) 89 return { 90 valid: false, 91 error: `Heart notes are available in ${minsRemaining} minutes` 92 } 93 } 94 return { valid: false, error: 'Stage 2 cannot be updated at this time' } 95 } 96 } 97 98 if (stage === 'stage3') { 99 if (!permissions.canEditStage3 && !permissions.canAddStage3) { 100 const elapsed = calculateElapsedHours(review.createdAt) 101 if (elapsed < 4) { 102 const minsRemaining = Math.ceil((4 - elapsed) * 60) 103 return { 104 valid: false, 105 error: `Final notes are available in ${minsRemaining} minutes` 106 } 107 } 108 const hasStage2 = !!(review.drydownRating && review.midProjection && review.sillage) 109 if (!hasStage2) { 110 return { 111 valid: false, 112 error: 'Stage 2 must be completed before adding Stage 3' 113 } 114 } 115 return { valid: false, error: 'Stage 3 cannot be updated at this time' } 116 } 117 } 118 119 return { valid: true } 120} 121 122/** 123 * Check if review's fragrance connection can be changed 124 * This is allowed at ANY time, even after 24 hours when other edits are locked 125 */ 126export function canChangeFragrance(_review: any): boolean { 127 return true // Always allowed 128}