feat: add eventid query parameter to auto-open event details

- Add eventid URL parameter support to open specific event on page load
- Automatically fetch and display event detail drawer when eventid is present
- Show error message if event ID is invalid or doesn't exist
- Update URL when opening/closing event detail drawer
- Add error message UI with dismiss functionality
- Maintain eventid in URL for shareable links to specific events
This commit is contained in:
Claude 2025-11-23 07:24:01 +00:00
parent 96964f4f00
commit 8720a56c7d
No known key found for this signature in database

View file

@ -213,6 +213,7 @@ export default function App() {
const [userInfo, setUserInfo] = useState<UserInfoResponse>()
const [currentMember, setCurrentMember] = useState<PublicMember>()
const [token, setToken] = useState<string>()
const [errorMessage, setErrorMessage] = useState<string>("")
useEffect(() => {
const check = async () => {
@ -244,6 +245,39 @@ export default function App() {
check()
}, [])
// Handle eventid query parameter to auto-open event detail
useEffect(() => {
const loadEventFromUrl = async () => {
if (!token) return // Wait for authentication
const params = new URLSearchParams(window.location.search)
const eventId = params.get('eventid')
if (eventId) {
try {
const { data, error } = await saturdayClient.GET("/events/{eventId}", {
params: {
path: {
eventId: eventId,
},
},
})
if (error || !data) {
setErrorMessage(`无法找到工单 #${eventId},该工单可能不存在或已被删除`)
} else {
setActiveEvent(data as PublicEvent)
onOpen()
}
} catch (err) {
setErrorMessage(`加载工单 #${eventId} 时出错`)
}
}
}
loadEventFromUrl()
}, [token])
const list = useAsyncList<PublicEvent>({
async load() {
setIsLoading(true)
@ -299,10 +333,12 @@ export default function App() {
// Update URL query params when page or statusFilter changes
useEffect(() => {
const params = new URLSearchParams()
const params = new URLSearchParams(window.location.search)
params.set('page', page.toString())
if (statusFilter.length > 0) {
params.set('status', statusFilter.join(','))
} else {
params.delete('status')
}
const newUrl = `${window.location.pathname}?${params.toString()}`
window.history.replaceState({}, '', newUrl)
@ -367,6 +403,22 @@ export default function App() {
const onOpenEventDetail = (event: PublicEvent) => {
setActiveEvent(event)
onOpen()
// Update URL with eventid
const params = new URLSearchParams(window.location.search)
params.set('eventid', event.eventId)
const newUrl = `${window.location.pathname}?${params.toString()}`
window.history.replaceState({}, '', newUrl)
}
const onCloseEventDetail = () => {
onOpenChange()
// Remove eventid from URL
const params = new URLSearchParams(window.location.search)
params.delete('eventid')
const newUrl = `${window.location.pathname}?${params.toString()}`
window.history.replaceState({}, '', newUrl)
}
const MobileEventCard = ({ event }: { event: PublicEvent }) => (
@ -566,13 +618,35 @@ export default function App() {
}
isOpen={isOpen}
onOpenChange={onOpenChange}
onClose={() => {
onOpenChange()
}}
onClose={onCloseEventDetail}
onDelete={() => {}}
onEdit={() => {}}
>
</TicketDetailDrawer>
{/* Error Message Display */}
{errorMessage && (
<div className="fixed bottom-4 left-1/2 transform -translate-x-1/2 z-50 max-w-md w-full mx-4">
<div className="bg-red-50 border border-red-200 rounded-lg p-4 shadow-lg">
<div className="flex items-start gap-3">
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-red-600 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div className="flex-1">
<p className="text-sm font-medium text-red-800">{errorMessage}</p>
</div>
<button
onClick={() => setErrorMessage("")}
className="text-red-400 hover:text-red-600 flex-shrink-0"
>
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fillRule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clipRule="evenodd" />
</svg>
</button>
</div>
</div>
</div>
)}
</section>
)
}