diff --git a/frontend/src/app/admin/servicos/[id]/editar/page.tsx b/frontend/src/app/admin/servicos/[id]/editar/page.tsx index 5269c11..55c4dc9 100644 --- a/frontend/src/app/admin/servicos/[id]/editar/page.tsx +++ b/frontend/src/app/admin/servicos/[id]/editar/page.tsx @@ -1,28 +1,79 @@ "use client"; -import { useState, useEffect, use } from 'react'; +import { useState, useEffect, use, useMemo } from 'react'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { useToast } from '@/contexts/ToastContext'; -// Ícones disponíveis do Remix Icon -const ICON_OPTIONS = [ - { value: 'ri-settings-3-line', label: 'Configurações' }, - { value: 'ri-tools-line', label: 'Ferramentas' }, - { value: 'ri-truck-line', label: 'Caminhão' }, - { value: 'ri-bus-line', label: 'Ônibus' }, - { value: 'ri-car-line', label: 'Carro' }, - { value: 'ri-roadster-line', label: 'Veículo Esportivo' }, - { value: 'ri-shield-check-line', label: 'Segurança' }, - { value: 'ri-file-chart-line', label: 'Laudo/Relatório' }, - { value: 'ri-draft-line', label: 'Documento' }, - { value: 'ri-building-2-line', label: 'Empresa' }, - { value: 'ri-home-gear-line', label: 'Manutenção' }, - { value: 'ri-compass-3-line', label: 'Engenharia' }, - { value: 'ri-ruler-line', label: 'Medição' }, - { value: 'ri-flashlight-line', label: 'Inspeção' }, - { value: 'ri-hard-drive-2-line', label: 'Equipamento' }, - { value: 'ri-cpu-line', label: 'Tecnologia' }, +// Lista expandida de ícones do Remix Icon organizados por categoria +const ICON_LIST = [ + // Veículos e Transporte + { value: 'ri-truck-line', label: 'Caminhão', category: 'veiculos' }, + { value: 'ri-truck-fill', label: 'Caminhão Preenchido', category: 'veiculos' }, + { value: 'ri-bus-line', label: 'Ônibus', category: 'veiculos' }, + { value: 'ri-car-line', label: 'Carro', category: 'veiculos' }, + { value: 'ri-roadster-line', label: 'Veículo Esportivo', category: 'veiculos' }, + { value: 'ri-taxi-line', label: 'Táxi', category: 'veiculos' }, + { value: 'ri-caravan-line', label: 'Trailer', category: 'veiculos' }, + + // Ferramentas e Engenharia + { value: 'ri-tools-line', label: 'Ferramentas', category: 'engenharia' }, + { value: 'ri-tools-fill', label: 'Ferramentas Preenchido', category: 'engenharia' }, + { value: 'ri-hammer-line', label: 'Martelo', category: 'engenharia' }, + { value: 'ri-screwdriver-line', label: 'Chave de Fenda', category: 'engenharia' }, + { value: 'ri-settings-3-line', label: 'Configurações', category: 'engenharia' }, + { value: 'ri-settings-4-line', label: 'Engrenagem', category: 'engenharia' }, + { value: 'ri-compass-3-line', label: 'Compasso', category: 'engenharia' }, + { value: 'ri-ruler-line', label: 'Régua', category: 'engenharia' }, + { value: 'ri-ruler-2-line', label: 'Régua 2', category: 'engenharia' }, + { value: 'ri-pencil-ruler-line', label: 'Lápis e Régua', category: 'engenharia' }, + + // Documentos e Laudos + { value: 'ri-draft-line', label: 'Documento', category: 'documentos' }, + { value: 'ri-file-text-line', label: 'Arquivo Texto', category: 'documentos' }, + { value: 'ri-file-chart-line', label: 'Relatório', category: 'documentos' }, + { value: 'ri-file-paper-2-line', label: 'Laudo', category: 'documentos' }, + { value: 'ri-file-list-3-line', label: 'Lista', category: 'documentos' }, + { value: 'ri-clipboard-line', label: 'Prancheta', category: 'documentos' }, + { value: 'ri-survey-line', label: 'Pesquisa', category: 'documentos' }, + { value: 'ri-task-line', label: 'Tarefa', category: 'documentos' }, + + // Segurança + { value: 'ri-shield-check-line', label: 'Escudo Check', category: 'seguranca' }, + { value: 'ri-shield-line', label: 'Escudo', category: 'seguranca' }, + { value: 'ri-shield-star-line', label: 'Escudo Estrela', category: 'seguranca' }, + { value: 'ri-safe-line', label: 'Cofre', category: 'seguranca' }, + { value: 'ri-alarm-warning-line', label: 'Alerta', category: 'seguranca' }, + { value: 'ri-error-warning-line', label: 'Aviso', category: 'seguranca' }, + + // Construção e Equipamentos + { value: 'ri-building-2-line', label: 'Prédio', category: 'construcao' }, + { value: 'ri-building-line', label: 'Edifício', category: 'construcao' }, + { value: 'ri-home-gear-line', label: 'Casa Engrenagem', category: 'construcao' }, + { value: 'ri-home-line', label: 'Casa', category: 'construcao' }, + { value: 'ri-store-2-line', label: 'Loja', category: 'construcao' }, + + // Inspeção e Verificação + { value: 'ri-search-eye-line', label: 'Inspeção', category: 'inspecao' }, + { value: 'ri-flashlight-line', label: 'Lanterna', category: 'inspecao' }, + { value: 'ri-eye-line', label: 'Olho', category: 'inspecao' }, + { value: 'ri-zoom-in-line', label: 'Zoom', category: 'inspecao' }, + { value: 'ri-checkbox-circle-line', label: 'Check Círculo', category: 'inspecao' }, + { value: 'ri-check-double-line', label: 'Duplo Check', category: 'inspecao' }, + + // Geral + { value: 'ri-lightbulb-line', label: 'Lâmpada', category: 'geral' }, + { value: 'ri-cpu-line', label: 'CPU', category: 'geral' }, + { value: 'ri-dashboard-3-line', label: 'Painel', category: 'geral' }, + { value: 'ri-bar-chart-box-line', label: 'Gráfico', category: 'geral' }, + { value: 'ri-pie-chart-line', label: 'Pizza', category: 'geral' }, + { value: 'ri-team-line', label: 'Equipe', category: 'geral' }, + { value: 'ri-user-settings-line', label: 'Usuário Config', category: 'geral' }, + { value: 'ri-customer-service-line', label: 'Suporte', category: 'geral' }, + { value: 'ri-hand-heart-line', label: 'Cuidado', category: 'geral' }, + { value: 'ri-award-line', label: 'Prêmio', category: 'geral' }, + { value: 'ri-medal-line', label: 'Medalha', category: 'geral' }, + { value: 'ri-verified-badge-line', label: 'Verificado', category: 'geral' }, ]; export default function EditService({ params }: { params: Promise<{ id: string }> }) { @@ -31,6 +82,8 @@ export default function EditService({ params }: { params: Promise<{ id: string } const { success, error } = useToast(); const [loadingData, setLoadingData] = useState(true); const [loading, setLoading] = useState(false); + const [iconSearch, setIconSearch] = useState(''); + const [showIconPicker, setShowIconPicker] = useState(false); const [formData, setFormData] = useState({ title: '', icon: 'ri-settings-3-line', @@ -40,6 +93,17 @@ export default function EditService({ params }: { params: Promise<{ id: string } fullDescription: '' }); + // Filtrar ícones pela busca + const filteredIcons = useMemo(() => { + if (!iconSearch) return ICON_LIST; + const search = iconSearch.toLowerCase(); + return ICON_LIST.filter(icon => + icon.label.toLowerCase().includes(search) || + icon.value.toLowerCase().includes(search) || + icon.category.toLowerCase().includes(search) + ); + }, [iconSearch]); + // Carregar dados do serviço useEffect(() => { async function fetchService() { @@ -154,56 +218,103 @@ export default function EditService({ params }: { params: Promise<{ id: string } /> -
- -
+
+ + + {/* Ícone selecionado */} +
setShowIconPicker(!showIconPicker)} + className="flex items-center gap-4 p-4 bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-xl cursor-pointer hover:border-primary transition-colors" + >
- +
+

{ICON_LIST.find(i => i.value === formData.icon)?.label || formData.icon}

+

{formData.icon}

+
+
-

Ou digite manualmente uma classe do Remix Icon

- setFormData({...formData, icon: e.target.value})} - className="mt-2 w-full px-4 py-2 bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-xl text-gray-900 dark:text-white text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary transition-all" - placeholder="ri-icon-name" - /> + + {/* Picker de ícones */} + {showIconPicker && ( +
+ {/* Busca */} +
+ + setIconSearch(e.target.value)} + className="w-full pl-10 pr-4 py-2 bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-lg text-gray-900 dark:text-white focus:outline-none focus:border-primary text-sm" + /> +
+ + {/* Grade de ícones */} +
+ {filteredIcons.map((icon) => ( + + ))} +
+ + {filteredIcons.length === 0 && ( +

Nenhum ícone encontrado

+ )} + + {/* Input manual */} +
+

Ou digite manualmente uma classe do Remix Icon:

+ setFormData({...formData, icon: e.target.value})} + className="w-full px-3 py-2 bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-lg text-gray-900 dark:text-white text-sm focus:outline-none focus:border-primary" + placeholder="ri-icon-name" + /> +
+
+ )}
-
-
- - -
+
+ + +
-
- - setFormData({...formData, order: parseInt(e.target.value) || 0})} - className="w-full px-4 py-3 bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-xl text-gray-900 dark:text-white focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary transition-all" - min="0" - /> -

Menor número = aparece primeiro

-
+
+ + setFormData({...formData, order: parseInt(e.target.value) || 0})} + className="w-full px-4 py-3 bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-xl text-gray-900 dark:text-white focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary transition-all" + min="0" + /> +

Menor número = aparece primeiro

diff --git a/frontend/src/app/admin/servicos/novo/page.tsx b/frontend/src/app/admin/servicos/novo/page.tsx index 779bfff..b3a1eae 100644 --- a/frontend/src/app/admin/servicos/novo/page.tsx +++ b/frontend/src/app/admin/servicos/novo/page.tsx @@ -1,14 +1,87 @@ "use client"; -import { useState } from 'react'; +import { useState, useMemo } from 'react'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { useToast } from '@/contexts/ToastContext'; +// Lista expandida de ícones do Remix Icon organizados por categoria +const ICON_LIST = [ + // Veículos e Transporte + { value: 'ri-truck-line', label: 'Caminhão', category: 'veiculos' }, + { value: 'ri-truck-fill', label: 'Caminhão Preenchido', category: 'veiculos' }, + { value: 'ri-bus-line', label: 'Ônibus', category: 'veiculos' }, + { value: 'ri-car-line', label: 'Carro', category: 'veiculos' }, + { value: 'ri-roadster-line', label: 'Veículo Esportivo', category: 'veiculos' }, + { value: 'ri-taxi-line', label: 'Táxi', category: 'veiculos' }, + { value: 'ri-caravan-line', label: 'Trailer', category: 'veiculos' }, + + // Ferramentas e Engenharia + { value: 'ri-tools-line', label: 'Ferramentas', category: 'engenharia' }, + { value: 'ri-tools-fill', label: 'Ferramentas Preenchido', category: 'engenharia' }, + { value: 'ri-hammer-line', label: 'Martelo', category: 'engenharia' }, + { value: 'ri-screwdriver-line', label: 'Chave de Fenda', category: 'engenharia' }, + { value: 'ri-settings-3-line', label: 'Configurações', category: 'engenharia' }, + { value: 'ri-settings-4-line', label: 'Engrenagem', category: 'engenharia' }, + { value: 'ri-compass-3-line', label: 'Compasso', category: 'engenharia' }, + { value: 'ri-ruler-line', label: 'Régua', category: 'engenharia' }, + { value: 'ri-ruler-2-line', label: 'Régua 2', category: 'engenharia' }, + { value: 'ri-pencil-ruler-line', label: 'Lápis e Régua', category: 'engenharia' }, + + // Documentos e Laudos + { value: 'ri-draft-line', label: 'Documento', category: 'documentos' }, + { value: 'ri-file-text-line', label: 'Arquivo Texto', category: 'documentos' }, + { value: 'ri-file-chart-line', label: 'Relatório', category: 'documentos' }, + { value: 'ri-file-paper-2-line', label: 'Laudo', category: 'documentos' }, + { value: 'ri-file-list-3-line', label: 'Lista', category: 'documentos' }, + { value: 'ri-clipboard-line', label: 'Prancheta', category: 'documentos' }, + { value: 'ri-survey-line', label: 'Pesquisa', category: 'documentos' }, + { value: 'ri-task-line', label: 'Tarefa', category: 'documentos' }, + + // Segurança + { value: 'ri-shield-check-line', label: 'Escudo Check', category: 'seguranca' }, + { value: 'ri-shield-line', label: 'Escudo', category: 'seguranca' }, + { value: 'ri-shield-star-line', label: 'Escudo Estrela', category: 'seguranca' }, + { value: 'ri-safe-line', label: 'Cofre', category: 'seguranca' }, + { value: 'ri-alarm-warning-line', label: 'Alerta', category: 'seguranca' }, + { value: 'ri-error-warning-line', label: 'Aviso', category: 'seguranca' }, + + // Construção e Equipamentos + { value: 'ri-building-2-line', label: 'Prédio', category: 'construcao' }, + { value: 'ri-building-line', label: 'Edifício', category: 'construcao' }, + { value: 'ri-home-gear-line', label: 'Casa Engrenagem', category: 'construcao' }, + { value: 'ri-home-line', label: 'Casa', category: 'construcao' }, + { value: 'ri-store-2-line', label: 'Loja', category: 'construcao' }, + + // Inspeção e Verificação + { value: 'ri-search-eye-line', label: 'Inspeção', category: 'inspecao' }, + { value: 'ri-flashlight-line', label: 'Lanterna', category: 'inspecao' }, + { value: 'ri-eye-line', label: 'Olho', category: 'inspecao' }, + { value: 'ri-zoom-in-line', label: 'Zoom', category: 'inspecao' }, + { value: 'ri-checkbox-circle-line', label: 'Check Círculo', category: 'inspecao' }, + { value: 'ri-check-double-line', label: 'Duplo Check', category: 'inspecao' }, + + // Geral + { value: 'ri-lightbulb-line', label: 'Lâmpada', category: 'geral' }, + { value: 'ri-cpu-line', label: 'CPU', category: 'geral' }, + { value: 'ri-dashboard-3-line', label: 'Painel', category: 'geral' }, + { value: 'ri-bar-chart-box-line', label: 'Gráfico', category: 'geral' }, + { value: 'ri-pie-chart-line', label: 'Pizza', category: 'geral' }, + { value: 'ri-team-line', label: 'Equipe', category: 'geral' }, + { value: 'ri-user-settings-line', label: 'Usuário Config', category: 'geral' }, + { value: 'ri-customer-service-line', label: 'Suporte', category: 'geral' }, + { value: 'ri-hand-heart-line', label: 'Cuidado', category: 'geral' }, + { value: 'ri-award-line', label: 'Prêmio', category: 'geral' }, + { value: 'ri-medal-line', label: 'Medalha', category: 'geral' }, + { value: 'ri-verified-badge-line', label: 'Verificado', category: 'geral' }, +]; + export default function NewService() { const router = useRouter(); const { success, error } = useToast(); const [loading, setLoading] = useState(false); + const [iconSearch, setIconSearch] = useState(''); + const [showIconPicker, setShowIconPicker] = useState(false); const [formData, setFormData] = useState({ title: '', icon: 'ri-settings-3-line', @@ -18,6 +91,17 @@ export default function NewService() { fullDescription: '' }); + // Filtrar ícones pela busca + const filteredIcons = useMemo(() => { + if (!iconSearch) return ICON_LIST; + const search = iconSearch.toLowerCase(); + return ICON_LIST.filter(icon => + icon.label.toLowerCase().includes(search) || + icon.value.toLowerCase().includes(search) || + icon.category.toLowerCase().includes(search) + ); + }, [iconSearch]); + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); @@ -92,24 +176,79 @@ export default function NewService() { />
-
- -
-
- +
+ + + {/* Ícone selecionado */} +
setShowIconPicker(!showIconPicker)} + className="flex items-center gap-4 p-4 bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-xl cursor-pointer hover:border-primary transition-colors" + > +
+
- setFormData({...formData, icon: e.target.value})} - className="w-full px-4 py-3 bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-xl text-gray-900 dark:text-white focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary transition-all" - placeholder="Ex: ri-truck-line" - required - /> +
+

{ICON_LIST.find(i => i.value === formData.icon)?.label || formData.icon}

+

{formData.icon}

+
+
-

- Consulte a lista de ícones em remixicon.com -

+ + {/* Picker de ícones */} + {showIconPicker && ( +
+ {/* Busca */} +
+ + setIconSearch(e.target.value)} + className="w-full pl-10 pr-4 py-2 bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-lg text-gray-900 dark:text-white focus:outline-none focus:border-primary text-sm" + /> +
+ + {/* Grade de ícones */} +
+ {filteredIcons.map((icon) => ( + + ))} +
+ + {filteredIcons.length === 0 && ( +

Nenhum ícone encontrado

+ )} + + {/* Input manual */} +
+

Ou digite manualmente uma classe do Remix Icon:

+ setFormData({...formData, icon: e.target.value})} + className="w-full px-3 py-2 bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-lg text-gray-900 dark:text-white text-sm focus:outline-none focus:border-primary" + placeholder="ri-icon-name" + /> +
+
+ )}