Polish dating profile link, likes title, and offline RSVP calendar export.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
eric 2026-09-04 07:17:48 -05:00
parent 377db2284f
commit f9ab758926
6 changed files with 90 additions and 12 deletions

View File

@ -8,6 +8,14 @@ export const metadata: Metadata = {
}; };
const LOGS = [ const LOGS = [
{
date: "2026-09-04",
tag: "匹配资料 · 报名日历",
items: [
"匹配卡片可「查看资料」;喜欢页标题改为中性「喜欢」",
"线下报名成功自动下载日历;个人中心每场 RSVP 可加入日历",
],
},
{ {
date: "2026-09-04", date: "2026-09-04",
tag: "导航精简", tag: "导航精简",

View File

@ -10601,6 +10601,21 @@ a.profile-stat-link:hover {
margin: 16px 0; margin: 16px 0;
} }
.dating-view-profile {
display: inline-block;
margin-top: 4px;
font-size: 0.85rem;
color: var(--accent, #e8a87c);
text-decoration: none;
pointer-events: auto;
position: relative;
z-index: 2;
}
.dating-view-profile:hover {
text-decoration: underline;
}
.dating-actions { .dating-actions {
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -11567,6 +11582,18 @@ a.weather-card:hover {
margin-left: auto; margin-left: auto;
} }
.profile-rsvp-actions {
margin-left: auto;
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
justify-content: flex-end;
}
.profile-rsvp-actions .btn {
margin-left: 0;
}
.compare-history { .compare-history {
margin: 0 0 1.5rem; margin: 0 0 1.5rem;
padding: 1rem 1.15rem; padding: 1rem 1.15rem;

View File

@ -237,7 +237,7 @@ export default function ProfilePage() {
<strong>{connect.likes}</strong> <strong>{connect.likes}</strong>
<span>{t.profile.statLikes}</span> <span>{t.profile.statLikes}</span>
</Link> </Link>
<Link href="/dating" className="profile-stat-card profile-stat-link"> <Link href="/dating/likes" className="profile-stat-card profile-stat-link">
<span className="stat-emoji">✨</span> <span className="stat-emoji">✨</span>
<strong>{connect.matches}</strong> <strong>{connect.matches}</strong>
<span>{t.profile.statMatches}</span> <span>{t.profile.statMatches}</span>
@ -410,11 +410,28 @@ export default function ProfilePage() {
{m.city} · {m.date} {m.time} {m.city} · {m.date} {m.time}
</p> </p>
</div> </div>
<div className="profile-rsvp-actions">
{(m.mode === "online" || m.mode === "hybrid") && ( {(m.mode === "online" || m.mode === "hybrid") && (
<Link href={`/meetups/${m.id}/live`} className="btn btn-sm btn-primary"> <Link href={`/meetups/${m.id}/live`} className="btn btn-sm btn-primary">
{t.profile.openLive} {t.profile.openLive}
</Link> </Link>
)} )}
<button
type="button"
className="btn btn-sm btn-ghost"
onClick={() => {
const ics = buildMeetupIcs([m], m.title);
if (!ics) {
toast(t.meetups.exportCalFail, "info");
return;
}
downloadMeetupIcs(`nomadro-${m.id}.ics`, ics);
toast(t.meetups.exportCalDone);
}}
>
{t.meetups.addToCal}
</button>
</div>
</div> </div>
))} ))}
</div> </div>

View File

@ -337,6 +337,14 @@ export default function DatingClient() {
</span> </span>
))} ))}
</div> </div>
<Link
href={`/members/${top.userId || top.id}`}
className="dating-view-profile"
onPointerDown={(e) => e.stopPropagation()}
onClick={(e) => e.stopPropagation()}
>
{t.dating.viewProfile} →
</Link>
</div> </div>
</div> </div>
<div className="dating-actions reveal"> <div className="dating-actions reveal">

View File

@ -129,10 +129,26 @@ export default function MeetupsClient({ meetups }: Props) {
const res = await api.rsvpMeetup(meetup.id, undefined, token); const res = await api.rsvpMeetup(meetup.id, undefined, token);
setRsvpIds(new Set(rsvpIds).add(meetup.id)); setRsvpIds(new Set(rsvpIds).add(meetup.id));
const live = meetup.mode === "online" || meetup.mode === "hybrid"; const live = meetup.mode === "online" || meetup.mode === "hybrid";
if (live) {
toast(res.message || t.meetups.rsvpOk, "success", { toast(res.message || t.meetups.rsvpOk, "success", {
href: live ? meetupEventHref(meetup) : "/profile", href: meetupEventHref(meetup),
label: live ? t.meetups.liveBtn : t.meetups.rsvpCalCta, label: t.meetups.liveBtn,
}); });
} else {
const ics = buildMeetupIcs([meetup], meetup.title);
if (ics) {
downloadMeetupIcs(`nomadro-${meetup.id}.ics`, ics);
toast(res.message || t.meetups.rsvpOk, "success", {
href: "/profile",
label: t.meetups.viewRsvps,
});
} else {
toast(res.message || t.meetups.rsvpOk, "success", {
href: "/profile",
label: t.meetups.viewRsvps,
});
}
}
void loadPeers(meetup.id); void loadPeers(meetup.id);
} catch { } catch {
toast(t.meetups.rsvpFail, "error"); toast(t.meetups.rsvpFail, "error");

View File

@ -422,7 +422,7 @@ export const zh = {
matched: "你和", matched: "你和",
keepSwiping: "继续滑", keepSwiping: "继续滑",
chatNow: "去聊天", chatNow: "去聊天",
likesTitle: "我喜欢的", likesTitle: "喜欢",
likesSubtitle: "你右滑喜欢的游民会出现在这里", likesSubtitle: "你右滑喜欢的游民会出现在这里",
likesEmpty: "还没有喜欢任何人,去滑一张卡片吧", likesEmpty: "还没有喜欢任何人,去滑一张卡片吧",
backSwipe: "返回匹配", backSwipe: "返回匹配",
@ -686,6 +686,7 @@ export const zh = {
meetPeers: "同城可能认识的人", meetPeers: "同城可能认识的人",
goDating: "去匹配", goDating: "去匹配",
rsvpCalCta: "导出日历", rsvpCalCta: "导出日历",
viewRsvps: "查看报名",
viewProfile: "查看资料", viewProfile: "查看资料",
}, },
community: { community: {
@ -1696,7 +1697,7 @@ export const en: { [K in keyof typeof zh]: typeof zh[K] extends string ? string
matched: "You matched with", matched: "You matched with",
keepSwiping: "Keep swiping", keepSwiping: "Keep swiping",
chatNow: "Open chat", chatNow: "Open chat",
likesTitle: "People you liked", likesTitle: "Likes",
likesSubtitle: "Profiles you swiped right on", likesSubtitle: "Profiles you swiped right on",
likesEmpty: "No likes yet — go swipe some cards", likesEmpty: "No likes yet — go swipe some cards",
backSwipe: "Back to match", backSwipe: "Back to match",
@ -1960,6 +1961,7 @@ export const en: { [K in keyof typeof zh]: typeof zh[K] extends string ? string
meetPeers: "People you may meet nearby", meetPeers: "People you may meet nearby",
goDating: "Go match", goDating: "Go match",
rsvpCalCta: "Export calendar", rsvpCalCta: "Export calendar",
viewRsvps: "View RSVPs",
viewProfile: "View profile", viewProfile: "View profile",
}, },
community: { community: {