update
This commit is contained in:
parent
63c6c9f87a
commit
404e577983
@ -8,14 +8,14 @@ import { useSession } from 'next-auth/react'
|
||||
|
||||
import LoadingSpinner from '@/app/components/LoadingSpinner'
|
||||
import TeamMemberView from '@/app/components/TeamMemberView'
|
||||
import { useTeamManager } from '@/app/hooks/useTeamManager'
|
||||
//import { useTeamManager } from '@/app/hooks/useTeamManager'
|
||||
|
||||
export default function TeamAdminClient({ teamId }: { teamId: string }) {
|
||||
const [refetchKey, setRefetchKey] = useState<string>()
|
||||
const { data: session } = useSession()
|
||||
|
||||
// jetzt wird die ID korrekt übergeben ➜ /api/team/[id]
|
||||
const teamManager = useTeamManager({ teamId, refetchKey }, null)
|
||||
//const teamManager = useTeamManager({ teamId, refetchKey }, null)
|
||||
|
||||
if (teamManager.isLoading) return <LoadingSpinner />
|
||||
|
||||
|
||||
@ -140,6 +140,32 @@ export async function POST(
|
||||
where: { steamId, actionData: invitationId },
|
||||
data: { read: true, actionType: null, actionData: null },
|
||||
})
|
||||
|
||||
|
||||
// 1. Teamdaten laden (inkl. Leader)
|
||||
const team = await prisma.team.findUnique({
|
||||
where: { id: teamId },
|
||||
select: { leader: true },
|
||||
})
|
||||
|
||||
// 2. Admins holen
|
||||
const admins = await prisma.user.findMany({
|
||||
where: { isAdmin: true },
|
||||
select: { steamId: true },
|
||||
})
|
||||
|
||||
// 3. Zielnutzer: Leader + Admins
|
||||
const targetUserIds = [
|
||||
team?.leader,
|
||||
...admins.map(admin => admin.steamId),
|
||||
].filter(Boolean) // entfernt null/undefined
|
||||
|
||||
// 4. SSE senden
|
||||
await sendServerSSEMessage({
|
||||
type: 'team-updated',
|
||||
teamId,
|
||||
targetUserIds,
|
||||
})
|
||||
|
||||
return NextResponse.json({ message: 'Einladung gelöscht' })
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ export default function NotificationCenter() {
|
||||
const [notifications, setNotifications] = useState<Notification[]>([])
|
||||
const [open, setOpen] = useState(false)
|
||||
const { source, connect } = useSSE()
|
||||
const { markAllAsRead, markOneAsRead, handleInviteAction } = useTeamManager({}, null)
|
||||
//const { markAllAsRead, markOneAsRead, handleInviteAction } = useTeamManager({}, null)
|
||||
const router = useRouter()
|
||||
const [previewText, setPreviewText] = useState<string | null>(null)
|
||||
const [showPreview, setShowPreview] = useState(false)
|
||||
|
||||
@ -4,7 +4,7 @@ import { useSession } from 'next-auth/react'
|
||||
import { useEffect } from 'react'
|
||||
import { useSSE } from '@/app/lib/useSSEStore'
|
||||
|
||||
export default function SSEManager() {
|
||||
export default function SSEListener() {
|
||||
const { data: session } = useSession()
|
||||
const connect = useSSE((s) => s.connect)
|
||||
const disconnect = useSSE((s) => s.disconnect)
|
||||
@ -18,6 +18,7 @@ export default function SSEManager() {
|
||||
|
||||
eventSource.onmessage = (event) => {
|
||||
try {
|
||||
console.error('[SSE] Nachricht empfangen:', event.data)
|
||||
const data = JSON.parse(event.data)
|
||||
|
||||
switch (data.type) {
|
||||
@ -25,6 +25,7 @@ import Button from './Button'
|
||||
import Image from 'next/image'
|
||||
import TeamPremierRankBadge from './TeamPremierRankBadge'
|
||||
import Link from 'next/link'
|
||||
import { useWebSocketListener } from '../hooks/useWebSocketListener'
|
||||
|
||||
type Props = {
|
||||
team: Team | null
|
||||
@ -63,7 +64,7 @@ export default function TeamMemberView({
|
||||
adminMode = false,
|
||||
}: Props) {
|
||||
const { data: session } = useSession()
|
||||
const { source, connect } = useSSE()
|
||||
const { source } = useSSE()
|
||||
const [kickCandidate, setKickCandidate] = useState<Player | null>(null)
|
||||
const [promoteCandidate, setPromoteCandidate] = useState<Player | null>(null)
|
||||
|
||||
@ -72,7 +73,6 @@ export default function TeamMemberView({
|
||||
const canManage = adminMode || isLeader
|
||||
const canInvite = isLeader && !adminMode
|
||||
const canAddDirect = adminMode
|
||||
//const { leaveTeam, reloadTeam, renameTeam, revokeInvitation } = useTeamManager({}, null)
|
||||
const [showRenameModal, setShowRenameModal] = useState(false)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const [isEditingName, setIsEditingName] = useState(false)
|
||||
@ -84,11 +84,7 @@ export default function TeamMemberView({
|
||||
const [saveSuccess, setSaveSuccess] = useState(false)
|
||||
const [invitedPlayers, setInvitedPlayers] = useState<InvitedPlayer[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
if (session?.user?.steamId) {
|
||||
connect(session.user.steamId)
|
||||
}
|
||||
}, [session?.user?.steamId])
|
||||
useWebSocketListener('ws-team-update', () => console.log("yeah?"))
|
||||
|
||||
useEffect(() => {
|
||||
setTeamState(team)
|
||||
@ -105,61 +101,6 @@ export default function TeamMemberView({
|
||||
}
|
||||
}, [team])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!source || !teamState?.id) return
|
||||
|
||||
const handleMessage = (e: MessageEvent) => {
|
||||
try {
|
||||
const data = JSON.parse(e.data)
|
||||
const relevant = [
|
||||
'team-updated',
|
||||
'team-leader-changed',
|
||||
'team-leader-self',
|
||||
'team-member-joined',
|
||||
'team-member-left',
|
||||
'team-kick',
|
||||
'team-kick-other',
|
||||
'team-renamed',
|
||||
'team-logo-updated',
|
||||
]
|
||||
if (data.teamId !== teamState.id || !relevant.includes(data.type)) return
|
||||
|
||||
/* EIN Aufruf genügt – holt Team + Spieler + setzt States */
|
||||
fetch(`/api/team/${encodeURIComponent(data.teamId)}`)
|
||||
.then(r => r.json())
|
||||
.then(({ team }) => {
|
||||
if (!team) return
|
||||
setTeamState(team)
|
||||
setactivePlayers(team.activePlayers.sort((a: Player, b: Player) => a.name.localeCompare(b.name)))
|
||||
setInactivePlayers(team.inactivePlayers.sort((a: Player, b: Player) => a.name.localeCompare(b.name)))
|
||||
setInvitedPlayers(team.invitedPlayers.sort((a: Player, b: Player) => a.name.localeCompare(b.name)))
|
||||
})
|
||||
} catch (err) {
|
||||
console.error('SSE parse error:', err)
|
||||
}
|
||||
}
|
||||
|
||||
const eventNames = [
|
||||
'team-updated',
|
||||
'team-leader-changed',
|
||||
'team-leader-self',
|
||||
'team-member-joined',
|
||||
'team-member-left',
|
||||
'team-kick',
|
||||
'team-kick-other',
|
||||
'team-renamed',
|
||||
'team-logo-updated',
|
||||
]
|
||||
eventNames.forEach(evt => source.addEventListener(evt, handleMessage))
|
||||
source.onmessage = handleMessage
|
||||
|
||||
return () => {
|
||||
eventNames.forEach(evt => source.removeEventListener(evt, handleMessage))
|
||||
source.onmessage = null
|
||||
}
|
||||
}, [source, teamState?.id, reloadTeam])
|
||||
|
||||
const handleDragStart = (event: any) => {
|
||||
const id = event.active.id
|
||||
const item = activePlayers.find(p => p.steamId === id) || inactivePlayers.find(p => p.steamId === id)
|
||||
@ -558,7 +499,7 @@ export default function TeamMemberView({
|
||||
<div className="w-full rounded-lg p-4 transition-colors min-h-[200px] border border-gray-300 dark:border-neutral-700">
|
||||
<div className="grid gap-4 justify-start grid-cols-[repeat(auto-fill,minmax(160px,1fr))]">
|
||||
<AnimatePresence>
|
||||
{invitedPlayers.map((player: Player) => (
|
||||
{invitedPlayers.map((player: InvitedPlayer) => (
|
||||
<motion.div
|
||||
key={player.steamId}
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// useTeamManager.tsx
|
||||
|
||||
import { useEffect, useState, useImperativeHandle } from 'react'
|
||||
import { Player, Team } from '../types/team'
|
||||
import { useSession } from 'next-auth/react'
|
||||
|
||||
@ -8,7 +8,7 @@ import ThemeProvider from "@/theme/theme-provider";
|
||||
import Script from "next/script";
|
||||
import NotificationCenter from './components/NotificationCenter'
|
||||
import Navbar from "./components/Navbar";
|
||||
import SSEManager from "./components/SSEManager";
|
||||
import SSEListener from "./components/SSEListener";
|
||||
|
||||
const geistSans = Geist({
|
||||
variable: "--font-geist-sans",
|
||||
@ -40,7 +40,7 @@ export default function RootLayout({
|
||||
disableTransitionOnChange
|
||||
>
|
||||
<Providers>
|
||||
<SSEManager />
|
||||
<SSEListener />
|
||||
{/* Sidebar und Content direkt nebeneinander */}
|
||||
<Sidebar>
|
||||
{children}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
// sse-server-client.ts
|
||||
|
||||
const host = 'localhost'
|
||||
|
||||
export async function sendServerSSEMessage(message: any) {
|
||||
try {
|
||||
console.log('[SSE Client] Nachricht senden:', message)
|
||||
await fetch(`http://${host}:3001/send`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
|
||||
@ -17,11 +17,22 @@ export const useSSE = create<SSEState>((set, get) => {
|
||||
const source = new EventSource(`http://localhost:3001/events?steamId=${steamId}`)
|
||||
|
||||
source.onopen = () => {
|
||||
console.log('[SSE] Verbunden!')
|
||||
set({ source, isConnected: true })
|
||||
}
|
||||
|
||||
source.onmessage = (event) => {
|
||||
console.log('[SSE] Nachricht:', event.data)
|
||||
try {
|
||||
const data = JSON.parse(event.data)
|
||||
|
||||
// Zentrale Weiterleitung aller Events, die ein "type" haben
|
||||
if (data?.type) {
|
||||
window.dispatchEvent(new CustomEvent(`sse-${data.type}`, { detail: data }))
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[SSE] Ungültige Nachricht:', event.data)
|
||||
}
|
||||
}
|
||||
|
||||
source.addEventListener('notification', (event) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user