tangled
alpha
login
or
join now
taurean.bryant.land
/
drydown
1
fork
atom
a a vibe-coded abomination experiment of a fragrance review platform built on the atmosphere.
drydown.social
1
fork
atom
overview
issues
pulls
pipelines
making cards editable when they should be
taurean.bryant.land
2 months ago
9b2771cc
ebebd383
+51
-10
4 changed files
expand all
collapse all
unified
split
src
app.tsx
components
ReviewCard.tsx
ReviewDashboard.tsx
ReviewList.tsx
+5
src/app.tsx
···
96
96
<ReviewDashboard
97
97
session={session}
98
98
onCreateNew={handleCreateNew}
99
99
+
onEditReview={(uri, stage) => {
100
100
+
setEditReviewUri(uri)
101
101
+
setEditReviewStage(stage)
102
102
+
setView('edit-review')
103
103
+
}}
99
104
/>
100
105
<button onClick={handleLogout} style={{ marginTop: '2rem' }}>Sign Out</button>
101
106
</>
+20
-7
src/components/ReviewCard.tsx
···
4
4
review: { uri: string; value: any }
5
5
fragranceName: string
6
6
status: 'ready' | 'inProgress' | 'completed'
7
7
+
onClick?: () => void
7
8
}
8
9
9
9
-
export function ReviewCard({ review, fragranceName, status }: ReviewCardProps) {
10
10
+
export function ReviewCard({ review, fragranceName, status, onClick }: ReviewCardProps) {
10
11
const { value } = review
11
12
12
13
return (
13
13
-
<div style={{
14
14
-
border: '1px solid #ddd',
15
15
-
borderRadius: '8px',
16
16
-
padding: '1rem',
17
17
-
marginBottom: '1rem'
18
18
-
}}>
14
14
+
<div
15
15
+
onClick={onClick}
16
16
+
style={{
17
17
+
border: '1px solid #ddd',
18
18
+
borderRadius: '8px',
19
19
+
padding: '1rem',
20
20
+
marginBottom: '1rem',
21
21
+
cursor: onClick ? 'pointer' : 'default',
22
22
+
backgroundColor: onClick ? '#fff' : '#f9f9f9', // subtle hint
23
23
+
transition: 'background-color 0.2s',
24
24
+
}}
25
25
+
onMouseEnter={(e) => {
26
26
+
if (onClick) e.currentTarget.style.backgroundColor = '#f0f8ff'
27
27
+
}}
28
28
+
onMouseLeave={(e) => {
29
29
+
if (onClick) e.currentTarget.style.backgroundColor = '#fff'
30
30
+
}}
31
31
+
>
19
32
<h4 style={{ margin: '0 0 0.5rem 0', fontSize: '1.1rem' }}>
20
33
{fragranceName}
21
34
</h4>
+22
-2
src/components/ReviewDashboard.tsx
···
3
3
import { ReviewList } from './ReviewList'
4
4
import type { OAuthSession } from '@atproto/oauth-client-browser'
5
5
6
6
+
import { getAvailableStage } from '../utils/reviewUtils'
7
7
+
6
8
interface ReviewDashboardProps {
7
9
session: OAuthSession
8
10
onCreateNew: () => void
11
11
+
onEditReview: (uri: string, stage: 'stage2' | 'stage3') => void
9
12
}
10
13
11
11
-
export function ReviewDashboard({ session, onCreateNew }: ReviewDashboardProps) {
14
14
+
export function ReviewDashboard({ session, onCreateNew, onEditReview }: ReviewDashboardProps) {
12
15
const [reviews, setReviews] = useState<Array<{ uri: string; value: any }>>([])
13
16
const [fragrances, setFragrances] = useState<Map<string, { name: string }>>(new Map())
14
17
const [isLoading, setIsLoading] = useState(true)
···
59
62
{isLoading ? (
60
63
<div>Loading reviews...</div>
61
64
) : (
62
62
-
<ReviewList reviews={reviews} fragrances={fragrances} />
65
65
+
<ReviewList
66
66
+
reviews={reviews}
67
67
+
fragrances={fragrances}
68
68
+
onReviewClick={(review) => {
69
69
+
// Determine the stage to open
70
70
+
let stage = getAvailableStage(review.value)
71
71
+
72
72
+
// If getAvailableStage returns null (e.g. because it's too early/late or completed),
73
73
+
// we default to the next logical stage based on data presence.
74
74
+
if (!stage) {
75
75
+
if (!review.value.drydownRating) stage = 'stage2'
76
76
+
else if (!review.value.endRating) stage = 'stage3'
77
77
+
else stage = 'stage3' // Fallback for completed reviews if we want to view them
78
78
+
}
79
79
+
80
80
+
onEditReview(review.uri, stage!)
81
81
+
}}
82
82
+
/>
63
83
)}
64
84
</div>
65
85
)
+4
-1
src/components/ReviewList.tsx
···
4
4
interface ReviewListProps {
5
5
reviews: Array<{ uri: string; value: any }>
6
6
fragrances: Map<string, { name: string }>
7
7
+
onReviewClick: (review: { uri: string; value: any }) => void
7
8
}
8
9
9
9
-
export function ReviewList({ reviews, fragrances }: ReviewListProps) {
10
10
+
export function ReviewList({ reviews, fragrances, onReviewClick }: ReviewListProps) {
10
11
const { readyToUpdate, inProgress, completed } = categorizeReviews(reviews)
11
12
12
13
const getFragranceName = (fragranceUri: string) => {
···
26
27
review={review}
27
28
fragranceName={getFragranceName(review.value.fragrance)}
28
29
status="ready"
30
30
+
onClick={() => onReviewClick(review)}
29
31
/>
30
32
))}
31
33
</section>
···
42
44
review={review}
43
45
fragranceName={getFragranceName(review.value.fragrance)}
44
46
status="inProgress"
47
47
+
onClick={() => onReviewClick(review)}
45
48
/>
46
49
))}
47
50
</section>