ironie-nextjs/src/app/[locale]/components/CreateTeamButton.tsx
2025-09-23 15:27:42 +02:00

165 lines
5.4 KiB
TypeScript

'use client'
import { useState, forwardRef } from 'react'
import { useSession } from 'next-auth/react'
import Modal from './Modal'
import Button from './Button'
type CreateTeamButtonProps = {
/** Optional: Parent kann damit eine Liste refreshen */
setRefetchKey?: (key: string) => void
}
const CreateTeamButton = forwardRef<HTMLDivElement, CreateTeamButtonProps>(
({ setRefetchKey }, ref) => {
const { data: session } = useSession()
const [teamname, setTeamname] = useState('')
const [showModal, setShowModal] = useState(false)
const [status, setStatus] = useState<'idle' | 'success' | 'error'>('idle')
const [message, setMessage] = useState('')
// Modal schließen + Backdrop sicher entfernen
const closeCreateModalAndCleanup = () => {
const modalEl = document.getElementById('modal-create-team')
if (modalEl && (window as any).HSOverlay?.close) {
;(window as any).HSOverlay.close(modalEl)
}
setShowModal(false)
requestAnimationFrame(() => {
document.querySelectorAll('.hs-overlay-backdrop').forEach(el => el.remove())
document.querySelectorAll('.hs-overlay[aria-hidden="true"]').forEach(el => {
(el as HTMLElement).style.pointerEvents = 'none'
;(el as HTMLElement).style.display = 'none'
})
document.body.classList.remove('overflow-hidden')
})
}
const handleSubmit = async () => {
setStatus('idle')
setMessage('')
if (!teamname.trim()) {
setStatus('error')
setMessage('Bitte gib einen Teamnamen ein.')
return
}
try {
const res = await fetch('/api/team/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ teamname, leader: session?.user?.steamId }),
})
const result = await res.json()
if (!res.ok) throw new Error(result.message || 'Fehler beim Erstellen')
setStatus('success')
setMessage(`Team "${result.team.name}" wurde erfolgreich erstellt!`)
setTeamname('')
// Nach kurzer Bestätigung Modal schließen, aufräumen und optional Parent refreshen
setTimeout(() => {
closeCreateModalAndCleanup()
requestAnimationFrame(() => {
// Nur aufrufen, wenn vom Parent übergeben
setRefetchKey?.(Date.now().toString())
})
}, 800)
} catch (err: any) {
setStatus('error')
setMessage(err.message || 'Fehler beim Erstellen des Teams')
}
}
return (
<div ref={ref}>
<Button onClick={() => setShowModal(true)} color="blue" variant="solid" size="sm">
Neues Team erstellen
</Button>
<Modal
id="modal-create-team"
title="Neues Team erstellen"
show={showModal}
onClose={() => {
setShowModal(false)
closeCreateModalAndCleanup()
}}
onSave={handleSubmit}
closeButtonTitle="Team erstellen"
>
<div className="max-w-sm space-y-2 relative">
<label htmlFor="teamname" className="block text-sm font-medium mb-2 dark:text-white">
Teamname
</label>
<input
id="teamname"
type="text"
value={teamname}
onChange={(e) => {
setTeamname(e.target.value)
setStatus('idle')
setMessage('')
}}
placeholder="Gebe einen Teamnamen ein..."
className={`
py-2.5 sm:py-3 px-4 block w-full rounded-lg sm:text-sm
dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600
${
status === 'error'
? 'border-red-500 focus:border-red-500 focus:ring-red-500'
: status === 'success'
? 'border-teal-500 focus:border-teal-500 focus:ring-teal-500'
: 'border-gray-300 focus:border-blue-500 focus:ring-blue-500'
}
`}
required
name="teamname"
aria-describedby="teamname-feedback"
/>
{status !== 'idle' && (
<div className="absolute right-3 top-10 flex items-center pointer-events-none">
<svg
className={`size-4 ${status === 'error' ? 'text-red-500' : 'text-teal-500'}`}
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}
>
{status === 'error' ? (
<>
<circle cx="12" cy="12" r="10" />
<line x1="12" x2="12" y1="8" y2="12" />
<line x1="12" x2="12.01" y1="16" y2="16" />
</>
) : (
<polyline points="20 6 9 17 4 12" />
)}
</svg>
</div>
)}
{message && (
<p id="teamname-feedback" className={`text-sm mt-1 ${status === 'error' ? 'text-red-600' : 'text-teal-600'}`}>
{message}
</p>
)}
</div>
</Modal>
</div>
)
}
)
CreateTeamButton.displayName = 'CreateTeamButton'
export default CreateTeamButton