Geniale | L Amica
return ( <div className="max-w-4xl mx-auto p-6"> <h2 className="text-2xl font-serif mb-4">Your parallel lives</h2> <div className="grid grid-cols-2 gap-8"> <div className="border-r pr-4"> <h3 className="font-bold text-lg">You</h3> events.filter(e => e.isSelf).map(event => ( <div key=event._id className="mb-3 p-2 bg-gray-100 rounded"> <strong>event.year</strong> – event.title </div> )) </div> <div> <h3 className="font-bold text-lg">friendName</h3> events.filter(e => !e.isSelf).map(event => ( <div key=event._id className="mb-3 p-2 bg-amber-50 rounded"> <strong>event.year</strong> – event.title </div> )) </div> </div> </div> );
useEffect(() => axios.get( /api/timeline/$pairId ).then(res => setEvents(res.data.events); setFriendName(res.data.friendName); ); , [pairId]); l amica geniale
// SecretLetter model const letterSchema = new Schema( pairId: type: Schema.Types.ObjectId, ref: 'FriendPair' , fromUser: type: Schema.Types.ObjectId, ref: 'User' , contentEncrypted: String, // encrypted with user's key unlocked: type: Boolean, default: false , unlockCondition: type: String, enum: ['mutual', 'time', 'milestone'] ); | Method | Endpoint | Description | |--------|----------|-------------| | POST | /api/pair/create | Create a friendship pair | | POST | /api/pair/join | Join with invite code | | GET | /api/timeline/:pairId | Get both users’ events sorted by year | | POST | /api/secrets | Create a secret letter | | POST | /api/secrets/unlock | Unlock when friend reciprocates | | GET | /api/progress/:pairId | Compare goals & challenges | Frontend (React + Tailwind) Component: ParallelTimeline.jsx import useEffect, useState from 'react'; import axios from 'axios'; export default function ParallelTimeline( pairId ) const [events, setEvents] = useState([]); const [friendName, setFriendName] = useState(''); return ( <