minor fixes
This commit is contained in:
@@ -1,12 +1,38 @@
|
||||
import React, { useRef, useState } from 'react'
|
||||
import React, { useMemo, useRef, useState } from 'react'
|
||||
import { router, usePage } from '@inertiajs/react'
|
||||
import StudioLayout from '../../Layouts/StudioLayout'
|
||||
import GroupStudioPromoCard from '../../components/groups/GroupStudioPromoCard'
|
||||
|
||||
function slugifyGroupValue(value) {
|
||||
return String(value || '')
|
||||
.normalize('NFKD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/^-+|-+$/g, '')
|
||||
.slice(0, 90)
|
||||
}
|
||||
|
||||
function resolveMediaPreviewUrl(path, filesCdnUrl) {
|
||||
const trimmed = String(path || '').trim()
|
||||
|
||||
if (!trimmed) {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (trimmed.startsWith('blob:') || trimmed.startsWith('data:') || trimmed.startsWith('http://') || trimmed.startsWith('https://')) {
|
||||
return trimmed
|
||||
}
|
||||
|
||||
return `${String(filesCdnUrl || '').replace(/\/$/, '')}/${trimmed.replace(/^\/+/, '')}`
|
||||
}
|
||||
|
||||
export default function StudioGroupCreate() {
|
||||
const { props } = usePage()
|
||||
const filesCdnUrl = props?.cdn?.files_url || ''
|
||||
const avatarInputRef = useRef(null)
|
||||
const bannerInputRef = useRef(null)
|
||||
const [slugManuallyEdited, setSlugManuallyEdited] = useState(false)
|
||||
const [form, setForm] = useState({
|
||||
name: '',
|
||||
slug: '',
|
||||
@@ -25,6 +51,8 @@ export default function StudioGroupCreate() {
|
||||
})
|
||||
const [avatarPreview, setAvatarPreview] = useState('')
|
||||
const [bannerPreview, setBannerPreview] = useState('')
|
||||
const resolvedAvatarPreview = useMemo(() => avatarPreview || resolveMediaPreviewUrl(form.avatar_path, filesCdnUrl), [avatarPreview, form.avatar_path, filesCdnUrl])
|
||||
const resolvedBannerPreview = useMemo(() => bannerPreview || resolveMediaPreviewUrl(form.banner_path, filesCdnUrl), [bannerPreview, form.banner_path, filesCdnUrl])
|
||||
|
||||
const updateLink = (index, key, value) => {
|
||||
setForm((current) => ({
|
||||
@@ -72,6 +100,23 @@ export default function StudioGroupCreate() {
|
||||
}
|
||||
}
|
||||
|
||||
const handleNameChange = (event) => {
|
||||
const nextName = event.target.value
|
||||
|
||||
setForm((current) => ({
|
||||
...current,
|
||||
name: nextName,
|
||||
slug: slugManuallyEdited ? current.slug : slugifyGroupValue(nextName),
|
||||
}))
|
||||
}
|
||||
|
||||
const handleSlugChange = (event) => {
|
||||
const nextSlug = slugifyGroupValue(event.target.value)
|
||||
|
||||
setSlugManuallyEdited(nextSlug !== '')
|
||||
setForm((current) => ({ ...current, slug: nextSlug }))
|
||||
}
|
||||
|
||||
return (
|
||||
<StudioLayout title={props.title} subtitle={props.description}>
|
||||
<div className="mx-auto mb-6 max-w-5xl">
|
||||
@@ -94,11 +139,11 @@ export default function StudioGroupCreate() {
|
||||
<div className="grid gap-5">
|
||||
<label className="grid gap-2 text-sm text-slate-200">
|
||||
<span>Name</span>
|
||||
<input value={form.name} onChange={(event) => setForm((current) => ({ ...current, name: event.target.value, slug: current.slug || event.target.value.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') }))} className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3 text-white outline-none" />
|
||||
<input value={form.name} onChange={handleNameChange} className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3 text-white outline-none" />
|
||||
</label>
|
||||
<label className="grid gap-2 text-sm text-slate-200">
|
||||
<span>Slug</span>
|
||||
<input value={form.slug} onChange={(event) => setForm((current) => ({ ...current, slug: event.target.value }))} className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3 text-white outline-none" />
|
||||
<input value={form.slug} onChange={handleSlugChange} className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3 text-white outline-none" />
|
||||
</label>
|
||||
<label className="grid gap-2 text-sm text-slate-200">
|
||||
<span>Short description</span>
|
||||
@@ -126,7 +171,7 @@ export default function StudioGroupCreate() {
|
||||
<div className="grid gap-3 rounded-[24px] border border-white/10 bg-black/20 p-4 text-sm text-slate-200">
|
||||
<span className="text-sm font-semibold text-white">Avatar / logo</span>
|
||||
<div className="flex h-28 w-28 items-center justify-center overflow-hidden rounded-[24px] border border-white/10 bg-white/[0.04]">
|
||||
{avatarPreview || form.avatar_path ? <img src={avatarPreview || form.avatar_path} alt="Avatar preview" className="h-full w-full object-cover" /> : <i className="fa-solid fa-image text-slate-500" />}
|
||||
{resolvedAvatarPreview ? <img src={resolvedAvatarPreview} alt="Avatar preview" className="h-full w-full object-cover" /> : <i className="fa-solid fa-image text-slate-500" />}
|
||||
</div>
|
||||
<input ref={avatarInputRef} type="file" accept="image/png,image/jpeg,image/webp" onChange={handleFileSelected('avatar_file', setAvatarPreview)} className="hidden" />
|
||||
<div className="flex flex-wrap gap-2">
|
||||
@@ -141,7 +186,7 @@ export default function StudioGroupCreate() {
|
||||
<div className="grid gap-3 rounded-[24px] border border-white/10 bg-black/20 p-4 text-sm text-slate-200">
|
||||
<span className="text-sm font-semibold text-white">Cover image</span>
|
||||
<div className="flex h-28 w-full items-center justify-center overflow-hidden rounded-[24px] border border-white/10 bg-white/[0.04]">
|
||||
{bannerPreview || form.banner_path ? <img src={bannerPreview || form.banner_path} alt="Cover preview" className="h-full w-full object-cover" /> : <i className="fa-solid fa-panorama text-slate-500" />}
|
||||
{resolvedBannerPreview ? <img src={resolvedBannerPreview} alt="Cover preview" className="h-full w-full object-cover" /> : <i className="fa-solid fa-panorama text-slate-500" />}
|
||||
</div>
|
||||
<input ref={bannerInputRef} type="file" accept="image/png,image/jpeg,image/webp" onChange={handleFileSelected('banner_file', setBannerPreview)} className="hidden" />
|
||||
<div className="flex flex-wrap gap-2">
|
||||
|
||||
Reference in New Issue
Block a user