165 lines
5.4 KiB
TypeScript
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
|