Skip to content

Commit 4e0649a

Browse files
committed
feat: acoes rapidas de start/stop/restart na lista de resources
Cada item da lista ganha botoes de Iniciar (se parado) ou Reiniciar/Parar (se rodando), sem precisar selecionar o resource antes. Gated por qadmin.action.change_resource, com loading por item e stopPropagation pra nao abrir o file browser ao clicar na acao. - handleResourceAction passa a aceitar o nome do resource (default: selecionado) - novo estado actingResource para o loading por item - card vira div com role=button (acessivel via teclado) pra aninhar os botoes
1 parent ee99f57 commit 4e0649a

4 files changed

Lines changed: 70 additions & 14 deletions

File tree

web/build/assets/script.js

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/build/assets/styles3.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/build/assets/vendor.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/src/pages/Resources/Resources.tsx

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ export default function Resources() {
185185
const [savingFile, setSavingFile] = useState(false)
186186
const [refreshingResources, setRefreshingResources] = useState(false)
187187
const [resourceAction, setResourceAction] = useState<ResourceAction | null>(null)
188+
const [actingResource, setActingResource] = useState('')
188189
const [message, setMessage] = useState<FlashMessage>(null)
189190
const [createKind, setCreateKind] = useState<'file' | 'folder'>('file')
190191
const [createName, setCreateName] = useState('')
@@ -481,13 +482,14 @@ export default function Resources() {
481482
}
482483
}
483484

484-
const handleResourceAction = async (action: ResourceAction) => {
485-
if (!selectedResource || !canChangeResource) return
485+
const handleResourceAction = async (action: ResourceAction, resourceName: string = selectedResource) => {
486+
if (!resourceName || !canChangeResource || actingResource) return
486487

487-
setResourceAction(action)
488+
setActingResource(resourceName)
489+
if (resourceName === selectedResource) setResourceAction(action)
488490

489491
try {
490-
const response = await sendNui<ResourceItem[]>('setResourceState', { name: selectedResource, state: action })
492+
const response = await sendNui<ResourceItem[]>('setResourceState', { name: resourceName, state: action })
491493
if (response) {
492494
setGameData((previous: any) => ({ ...previous, resources: response }))
493495
}
@@ -496,6 +498,7 @@ export default function Resources() {
496498
} catch (error: any) {
497499
showMessage('error', error?.message || 'Falha ao alterar o estado do recurso.')
498500
} finally {
501+
setActingResource('')
499502
setResourceAction(null)
500503
}
501504
}
@@ -729,17 +732,27 @@ export default function Resources() {
729732
{filteredResources.map((resource) => {
730733
const active = selectedResource === resource.name
731734
const tone = getResourceTone(resource.resourceState)
735+
const acting = actingResource === resource.name
736+
const isStarted = resource.resourceState === 'started'
732737

733738
return (
734-
<button
739+
<div
735740
key={resource.name}
741+
role="button"
742+
tabIndex={0}
736743
className={cn(
737-
'w-full rounded-2xl border p-3 text-left transition-all',
744+
'w-full cursor-pointer rounded-2xl border p-3 text-left transition-all',
738745
active
739746
? 'border-primary/50 bg-primary/10 shadow-[inset_0_0_0_1px_rgba(59,130,246,0.15)]'
740747
: 'border-border bg-muted/20 hover:border-border/80 hover:bg-muted/40'
741748
)}
742749
onClick={() => void handleResourceSelect(resource.name)}
750+
onKeyDown={(event) => {
751+
if (event.key === 'Enter' || event.key === ' ') {
752+
event.preventDefault()
753+
void handleResourceSelect(resource.name)
754+
}
755+
}}
743756
>
744757
<div className="flex items-start justify-between gap-3">
745758
<div className="min-w-0">
@@ -760,7 +773,50 @@ export default function Resources() {
760773
<p className="mt-2 line-clamp-2 text-[11px] leading-relaxed text-muted-foreground">
761774
{resource.description || 'Sem descricao no fxmanifest.'}
762775
</p>
763-
</button>
776+
777+
{canChangeResource && (
778+
<div
779+
className="mt-2.5 flex items-center gap-1.5 border-t border-border/60 pt-2.5"
780+
onClick={(event) => event.stopPropagation()}
781+
>
782+
{isStarted ? (
783+
<>
784+
<button
785+
type="button"
786+
title="Reiniciar"
787+
disabled={acting}
788+
onClick={() => void handleResourceAction('restart', resource.name)}
789+
className="inline-flex items-center gap-1 rounded-lg border border-border bg-muted/30 px-2 py-1 text-[11px] font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-50"
790+
>
791+
<RotateCw className={cn('h-3.5 w-3.5', acting && 'animate-spin')} />
792+
Reiniciar
793+
</button>
794+
<button
795+
type="button"
796+
title="Parar"
797+
disabled={acting}
798+
onClick={() => void handleResourceAction('stop', resource.name)}
799+
className="inline-flex items-center gap-1 rounded-lg border border-rose-500/30 bg-rose-500/10 px-2 py-1 text-[11px] font-medium text-rose-300 transition-colors hover:bg-rose-500/20 disabled:opacity-50"
800+
>
801+
<Square className="h-3.5 w-3.5" />
802+
Parar
803+
</button>
804+
</>
805+
) : (
806+
<button
807+
type="button"
808+
title="Iniciar"
809+
disabled={acting}
810+
onClick={() => void handleResourceAction('start', resource.name)}
811+
className="inline-flex items-center gap-1 rounded-lg border border-emerald-500/30 bg-emerald-500/10 px-2 py-1 text-[11px] font-medium text-emerald-300 transition-colors hover:bg-emerald-500/20 disabled:opacity-50"
812+
>
813+
<Play className={cn('h-3.5 w-3.5', acting && 'animate-spin')} />
814+
Iniciar
815+
</button>
816+
)}
817+
</div>
818+
)}
819+
</div>
764820
)
765821
})}
766822

0 commit comments

Comments
 (0)