Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,8 @@ export function LocationScheduleDetailSheet({
const categoryLabel = scheduleCategoryLabel(detailSchedule.category);

return (
<ScheduleDetailSheet
badges={[...(categoryLabel ? [categoryLabel] : []), '地点日程']}
onClose={onClose}
title={detailSchedule.title}
visible={schedule !== null}
>
<ScheduleDetailSheet onClose={onClose} title={detailSchedule.title} visible={schedule !== null}>
{categoryLabel ? <DetailSection icon="◈" label="分类" primary={categoryLabel} /> : null}
{location ? <DetailSection icon="📍" label="地点" primary={location} /> : null}
{reminder ? (
<DetailSection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { Pressable, StyleSheet, Text, View } from 'react-native';
import Svg, { Circle, Path } from 'react-native-svg';

import type { LocationScheduleView } from '../application';
import { colors, spacing } from '../../../shared/ui/theme';
import { scheduleCategoryLabel } from './scheduleDisplay';
import { colors } from '../../../shared/ui/theme';

export function LocationScheduleRow({
item,
Expand All @@ -13,7 +12,6 @@ export function LocationScheduleRow({
onPress?: () => void;
}) {
const locationLabel = item.locationName ?? '地点触发';
const categoryLabel = scheduleCategoryLabel(item.category);
return (
<Pressable
accessibilityRole={onPress ? 'button' : undefined}
Expand All @@ -25,16 +23,6 @@ export function LocationScheduleRow({
<LocationPinIcon />
</View>
<View style={styles.copy}>
<View style={styles.badges}>
{categoryLabel ? (
<View style={[styles.badge, styles.categoryBadge]}>
<Text style={styles.categoryBadgeText}>{categoryLabel}</Text>
</View>
) : null}
<View style={styles.badge}>
<Text style={styles.badgeText}>位置日程</Text>
</View>
</View>
<Text style={styles.title} numberOfLines={2}>
{item.title}
</Text>
Expand Down Expand Up @@ -62,18 +50,7 @@ function LocationPinIcon() {
}

const styles = StyleSheet.create({
badge: {
alignSelf: 'flex-start',
backgroundColor: colors.accent,
borderRadius: 999,
paddingHorizontal: spacing.sm,
paddingVertical: 2,
},
badgeText: { color: colors.text, fontSize: 11, fontWeight: '700' },
badges: { flexDirection: 'row', flexWrap: 'wrap', gap: spacing.xs },
categoryBadge: { backgroundColor: colors.input },
categoryBadgeText: { color: colors.mutedText, fontSize: 11, fontWeight: '700' },
copy: { flex: 1, gap: 6, minWidth: 0 },
copy: { flex: 1, gap: 4, minWidth: 0 },
iconWrap: {
alignItems: 'center',
backgroundColor: colors.accent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { LocationScheduleRow } from './LocationScheduleRow';
import { MonthCalendar } from './MonthCalendar';
import { ScheduleOccurrenceDetailSheet } from './ScheduleOccurrenceDetailSheet';
import { ScheduleOccurrenceRow } from './ScheduleOccurrenceRow';
import { emptyAgendaMessage, formatAgendaSectionTitle } from './scheduleDisplay';
import { useScheduleCalendar } from './useScheduleCalendar';
import type { CalendarFocusTarget } from './calendarFocus';

Expand Down Expand Up @@ -56,6 +57,8 @@ export function ScheduleCalendarScreen({
const selectedLocation =
calendar.locationSchedules.find((item) => item.scheduleId === selectedLocationId) ?? null;
const selectedLabel = SELECTED_DATE_FORMATTER.format(calendar.selectedDate);
const agendaTitle = formatAgendaSectionTitle(calendar.selectedDate);
const emptyAgenda = emptyAgendaMessage(calendar.selectedDate);
const displayUsername = username.trim() || '用户';
const avatarInitial = Array.from(displayUsername)[0]?.toLocaleUpperCase() ?? '用';

Expand All @@ -69,7 +72,9 @@ export function ScheduleCalendarScreen({
<View style={styles.content}>
<View style={styles.header}>
<View style={styles.headerTop}>
<Text style={styles.eyebrow}>我的日程</Text>
<Text numberOfLines={1} style={styles.title}>
{selectedLabel}
</Text>
<View style={styles.accountActions} testID="schedule-account-actions">
<View accessibilityLabel={`当前用户 ${displayUsername}`} style={styles.userPill}>
<View style={styles.avatar}>
Expand Down Expand Up @@ -104,9 +109,6 @@ export function ScheduleCalendarScreen({
</Pressable>
</View>
</View>
<Text numberOfLines={1} style={styles.title}>
{selectedLabel}
</Text>
</View>

<MonthCalendar
Expand Down Expand Up @@ -137,22 +139,22 @@ export function ScheduleCalendarScreen({
{!calendar.loading && !calendar.error ? (
<View style={styles.agenda}>
<View style={styles.sectionHeader}>
<View>
<Text style={styles.sectionEyebrow}>当日安排</Text>
<Text style={styles.sectionTitle}>日程</Text>
</View>
<Text style={styles.sectionTitle}>{agendaTitle}</Text>
<Text style={styles.sectionCount}>{calendar.selectedOccurrences.length} 项</Text>
</View>

{calendar.selectedOccurrences.length === 0 ? (
<View style={styles.empty}>
<Text style={styles.emptyTitle}>这一天暂时没有日程</Text>
<Text style={styles.emptyCopy}>留一点时间给自己,或用语音助手添加安排。</Text>
<Text style={styles.emptyTitle}>{emptyAgenda.title}</Text>
{emptyAgenda.detail ? (
<Text style={styles.emptyCopy}>{emptyAgenda.detail}</Text>
) : null}
</View>
) : (
calendar.selectedOccurrences.map((item) => (
calendar.selectedOccurrences.map((item, index) => (
<ScheduleOccurrenceRow
item={item}
isLast={index === calendar.selectedOccurrences.length - 1}
key={`${item.scheduleId}-${item.occurrenceStart}`}
onPress={() => setSelectedOccurrenceKey(occurrenceKey(item))}
/>
Expand All @@ -162,10 +164,7 @@ export function ScheduleCalendarScreen({
{calendar.locationSchedules.length > 0 ? (
<View style={styles.locationSection}>
<View style={styles.sectionHeader}>
<View>
<Text style={styles.sectionEyebrow}>位置触发</Text>
<Text style={styles.sectionTitle}>地点提醒</Text>
</View>
<Text style={styles.sectionTitle}>地点提醒</Text>
<Text style={styles.sectionCount}>{calendar.locationSchedules.length} 项</Text>
</View>
{calendar.locationSchedules.map((item) => (
Expand Down Expand Up @@ -215,11 +214,11 @@ function LogoutIcon() {
const styles = StyleSheet.create({
accountActions: {
alignItems: 'center',
flex: 1,
flexDirection: 'row',
flexShrink: 1,
gap: spacing.sm,
justifyContent: 'flex-end',
marginLeft: spacing.sm,
marginLeft: 'auto',
maxWidth: 240,
minWidth: 0,
},
Expand Down Expand Up @@ -265,7 +264,6 @@ const styles = StyleSheet.create({
},
emptyTitle: { color: colors.text, fontSize: 15, fontWeight: '700' },
error: { color: colors.error, fontSize: 15, textAlign: 'center' },
eyebrow: { color: colors.mutedText, fontSize: 13, fontWeight: '700' },
header: {
paddingBottom: spacing.lg,
paddingHorizontal: spacing.lg,
Expand All @@ -276,6 +274,7 @@ const styles = StyleSheet.create({
flexDirection: 'row',
justifyContent: 'space-between',
minWidth: 0,
width: '100%',
},
locationSection: {
borderTopColor: colors.border,
Expand All @@ -293,7 +292,6 @@ const styles = StyleSheet.create({
screen: { backgroundColor: colors.background, flex: 1 },
scrollContent: { paddingBottom: spacing.lg },
sectionCount: { color: colors.mutedText, fontSize: 12, fontWeight: '600' },
sectionEyebrow: { color: colors.mutedText, fontSize: 12, fontWeight: '600', marginBottom: 3 },
sectionHeader: {
alignItems: 'flex-end',
flexDirection: 'row',
Expand All @@ -314,7 +312,14 @@ const styles = StyleSheet.create({
},
signOutButtonPressed: { opacity: 0.62 },
stateText: { color: colors.mutedText },
title: { color: colors.text, fontSize: 28, fontWeight: '800', lineHeight: 34, marginTop: 4 },
title: {
color: colors.text,
flex: 1,
fontSize: 28,
fontWeight: '800',
lineHeight: 34,
minWidth: 0,
},
userPill: {
alignItems: 'center',
backgroundColor: colors.surface,
Expand Down
32 changes: 10 additions & 22 deletions frontend/src/features/schedule/presentation/ScheduleDetailSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ import { Modal, Pressable, ScrollView, StyleSheet, Text, View } from 'react-nati
import { colors, spacing } from '../../../shared/ui/theme';

export function ScheduleDetailSheet({
badges,
children,
onClose,
title,
visible,
}: {
badges: readonly string[];
children: ReactNode;
onClose: () => void;
title: string;
Expand All @@ -36,15 +34,6 @@ export function ScheduleDetailSheet({
<ScrollView contentContainerStyle={styles.content} showsVerticalScrollIndicator={false}>
<View style={styles.titleBlock}>
<Text style={styles.title}>{title}</Text>
<View style={styles.badges}>
{badges.map((badge, index) => (
<View key={badge} style={[styles.badge, index === 0 && styles.primaryBadge]}>
<Text style={[styles.badgeText, index === 0 && styles.primaryBadgeText]}>
{badge}
</Text>
</View>
))}
</View>
</View>
{children}
</ScrollView>
Expand Down Expand Up @@ -121,14 +110,6 @@ const styles = StyleSheet.create({
flex: 1,
justifyContent: 'flex-end',
},
badge: {
backgroundColor: colors.input,
borderRadius: 999,
paddingHorizontal: 11,
paddingVertical: 6,
},
badgeText: { color: colors.mutedText, fontSize: 12, fontWeight: '700' },
badges: { flexDirection: 'row', flexWrap: 'wrap', gap: spacing.sm },
closeButton: {
alignItems: 'center',
backgroundColor: colors.input,
Expand Down Expand Up @@ -170,8 +151,6 @@ const styles = StyleSheet.create({
metaIcon: { color: colors.mutedText, fontSize: 15 },
metaText: { color: colors.mutedText, flex: 1, fontSize: 12 },
pressed: { opacity: 0.62 },
primaryBadge: { backgroundColor: colors.accent },
primaryBadgeText: { color: colors.text },
section: {
alignItems: 'flex-start',
backgroundColor: colors.background,
Expand All @@ -189,9 +168,18 @@ const styles = StyleSheet.create({
borderRadius: 12,
height: 38,
justifyContent: 'center',
overflow: 'hidden',
width: 38,
},
sectionIconText: { color: colors.text, fontSize: 18, fontWeight: '700' },
sectionIconText: {
color: colors.text,
fontSize: 18,
height: 18,
includeFontPadding: false,
lineHeight: 18,
textAlign: 'center',
textAlignVertical: 'center',
},
sectionLabel: { color: colors.mutedText, fontSize: 12, fontWeight: '700', marginBottom: 4 },
sectionPrimary: { color: colors.text, fontSize: 16, fontWeight: '700', lineHeight: 22 },
sectionSecondary: { color: colors.mutedText, fontSize: 13, lineHeight: 19, marginTop: 3 },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,9 @@ export function ScheduleOccurrenceDetailSheet({
detailOccurrence.timezone,
);
const categoryLabel = scheduleCategoryLabel(detailOccurrence.category);
const badges = [
...(categoryLabel ? [categoryLabel] : []),
detailOccurrence.scheduleCategory === 'time' ? '时间日程' : '地点日程',
detailOccurrence.recurrenceMode === 'recurring' ? '周期日程' : '一次性',
...(detailOccurrence.isAllDay ? ['全天'] : []),
];

return (
<ScheduleDetailSheet
badges={badges}
onClose={onClose}
title={detailOccurrence.title}
visible={occurrence !== null}
Expand Down Expand Up @@ -97,6 +90,7 @@ export function ScheduleOccurrenceDetailSheet({
</View>
)}
</View>
{categoryLabel ? <DetailSection icon="◈" label="分类" primary={categoryLabel} /> : null}
{location ? <DetailSection icon="📍" label="地点" primary={location} /> : null}
{reminder ? (
<DetailSection
Expand Down Expand Up @@ -190,9 +184,18 @@ const styles = StyleSheet.create({
borderRadius: 10,
height: 30,
justifyContent: 'center',
overflow: 'hidden',
width: 30,
},
timeIconText: { color: colors.text, fontSize: 17, fontWeight: '700' },
timeIconText: {
color: colors.text,
fontSize: 17,
height: 17,
includeFontPadding: false,
lineHeight: 17,
textAlign: 'center',
textAlignVertical: 'center',
},
timeLabel: { color: colors.mutedText, fontSize: 12, fontWeight: '700' },
timePoint: { flex: 1, minWidth: 96 },
timePointDate: { color: colors.mutedText, fontSize: 13, fontWeight: '600', marginTop: 5 },
Expand Down
Loading
Loading