Compare commits
12 Commits
master
...
fix/templa
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b1d739ab9 | |||
| 78ffe430be | |||
| 8f84ce5a41 | |||
| d508df2afb | |||
| 0928d8d0d3 | |||
| faa03f80cf | |||
| d5e35b11ad | |||
| aed077f344 | |||
| e2e3e626c4 | |||
| 1d0e5f27d7 | |||
| 02f7955d67 | |||
| 873a586d0c |
@ -1,24 +1,71 @@
|
|||||||
name: Deploy Dev
|
name: Deploy Dev — Frontend
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- dev
|
- dev
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
runs-on: self-hosted
|
name: Deploy para VM Dev
|
||||||
|
runs-on: omnichannel-uat
|
||||||
|
env:
|
||||||
|
DEPLOY_PATH: /opt/omnichannel
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Atualizar código na VM Dev
|
- name: Checkout
|
||||||
run: |
|
uses: actions/checkout@v4
|
||||||
cd /opt/omnichannel/frontend
|
|
||||||
git pull origin dev
|
|
||||||
|
|
||||||
- name: Copiar env
|
- name: Preflight
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cp /home/desenvolvimento/.envs/omnichannel/frontend.env.development /opt/omnichannel/frontend/.env.development
|
set -euo pipefail
|
||||||
|
echo "Runner: $(hostname)"
|
||||||
|
docker --version
|
||||||
|
docker compose version
|
||||||
|
|
||||||
- name: Rebuild container
|
- name: Verificar secrets obrigatórios
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
ENV_DEV: ${{ secrets.ENV_DEV }}
|
||||||
run: |
|
run: |
|
||||||
cd /opt/omnichannel
|
set -euo pipefail
|
||||||
docker compose up -d --build frontend
|
if [ -z "${ENV_DEV:-}" ]; then
|
||||||
|
echo "Secret ENV_DEV não configurado. Adicione o conteúdo completo do .env.development em Settings > Actions > Secrets."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Escrever .env.development
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
ENV_DEV: ${{ secrets.ENV_DEV }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
printf '%s\n' "$ENV_DEV" > "$DEPLOY_PATH/frontend/.env.development"
|
||||||
|
chmod 600 "$DEPLOY_PATH/frontend/.env.development"
|
||||||
|
|
||||||
|
- name: Sync código
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
LOCK="/tmp/omnichannel-frontend-dev.lock"
|
||||||
|
(
|
||||||
|
flock -n 9 || { echo "Deploy já em andamento. Tente novamente em instantes."; exit 1; }
|
||||||
|
|
||||||
|
rsync -az --delete \
|
||||||
|
--exclude='.git/' \
|
||||||
|
--exclude='.gitea/' \
|
||||||
|
--exclude='.env*' \
|
||||||
|
--exclude='node_modules/' \
|
||||||
|
--exclude='dist/' \
|
||||||
|
./ "$DEPLOY_PATH/frontend/"
|
||||||
|
) 9>"$LOCK"
|
||||||
|
|
||||||
|
- name: Build e reiniciar container
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cd "$DEPLOY_PATH"
|
||||||
|
docker compose build frontend
|
||||||
|
docker compose up -d frontend
|
||||||
|
|||||||
71
.gitea/workflows/deploy-prod.yml
Normal file
71
.gitea/workflows/deploy-prod.yml
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
name: Deploy Prod — Frontend
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
name: Deploy para VM Prod
|
||||||
|
runs-on: self-hosted-prod
|
||||||
|
env:
|
||||||
|
DEPLOY_PATH: /opt/omnichannel
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Preflight
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
echo "Runner: $(hostname)"
|
||||||
|
docker --version
|
||||||
|
docker compose version
|
||||||
|
|
||||||
|
- name: Verificar secrets obrigatórios
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
ENV_PROD: ${{ secrets.ENV_PROD }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
if [ -z "${ENV_PROD:-}" ]; then
|
||||||
|
echo "Secret ENV_PROD não configurado."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Escrever .env.production
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
ENV_PROD: ${{ secrets.ENV_PROD }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
printf '%s\n' "$ENV_PROD" > "$DEPLOY_PATH/frontend/.env.production"
|
||||||
|
chmod 600 "$DEPLOY_PATH/frontend/.env.production"
|
||||||
|
|
||||||
|
- name: Sync código
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
LOCK="/tmp/omnichannel-frontend-prod.lock"
|
||||||
|
(
|
||||||
|
flock -n 9 || { echo "Deploy já em andamento. Tente novamente em instantes."; exit 1; }
|
||||||
|
|
||||||
|
rsync -az --delete \
|
||||||
|
--exclude='.git/' \
|
||||||
|
--exclude='.gitea/' \
|
||||||
|
--exclude='.env*' \
|
||||||
|
--exclude='node_modules/' \
|
||||||
|
--exclude='dist/' \
|
||||||
|
./ "$DEPLOY_PATH/frontend/"
|
||||||
|
) 9>"$LOCK"
|
||||||
|
|
||||||
|
- name: Build e reiniciar container
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cd "$DEPLOY_PATH"
|
||||||
|
docker compose build frontend
|
||||||
|
docker compose up -d frontend
|
||||||
@ -8,7 +8,7 @@ export function RecentContactsList({
|
|||||||
style={{
|
style={{
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gap: '0.9rem',
|
gap: '0.9rem',
|
||||||
@ -34,7 +34,7 @@ export function RecentContactsList({
|
|||||||
border: '1px solid',
|
border: '1px solid',
|
||||||
borderColor: isActive ? 'rgba(0, 164, 183, 0.26)' : 'var(--color-border)',
|
borderColor: isActive ? 'rgba(0, 164, 183, 0.26)' : 'var(--color-border)',
|
||||||
background: isActive ? 'rgba(0, 164, 183, 0.08)' : '#fff',
|
background: isActive ? 'rgba(0, 164, 183, 0.08)' : '#fff',
|
||||||
borderRadius: '20px',
|
borderRadius: '15px',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
textAlign: 'left',
|
textAlign: 'left',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -71,7 +71,7 @@ export function RecentContactsList({
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: 'rgba(0, 49, 80, 0.04)',
|
background: 'rgba(0, 49, 80, 0.04)',
|
||||||
color: 'var(--color-text-soft)',
|
color: 'var(--color-text-soft)',
|
||||||
|
|||||||
@ -40,7 +40,7 @@ export function AgentNewAttendancePage() {
|
|||||||
width: 'min(1680px, calc(100vw - 3rem))',
|
width: 'min(1680px, calc(100vw - 3rem))',
|
||||||
margin: '0 auto',
|
margin: '0 auto',
|
||||||
background: 'var(--color-surface-strong)',
|
background: 'var(--color-surface-strong)',
|
||||||
borderRadius: '32px',
|
borderRadius: '24px',
|
||||||
boxShadow: 'var(--shadow-lg)',
|
boxShadow: 'var(--shadow-lg)',
|
||||||
padding: '1.5rem',
|
padding: '1.5rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -60,7 +60,7 @@ export function AgentNewAttendancePage() {
|
|||||||
style={{
|
style={{
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
padding: '1.5rem',
|
padding: '1.5rem',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -81,7 +81,7 @@ export function AgentNewAttendancePage() {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
padding: '1.1rem 1.25rem',
|
padding: '1.1rem 1.25rem',
|
||||||
borderRadius: '22px',
|
borderRadius: '16px',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
}}
|
}}
|
||||||
@ -100,7 +100,7 @@ export function AgentNewAttendancePage() {
|
|||||||
justifySelf: isMobile ? 'stretch' : 'end',
|
justifySelf: isMobile ? 'stretch' : 'end',
|
||||||
justifyContent: isMobile ? 'space-between' : 'flex-end',
|
justifyContent: isMobile ? 'space-between' : 'flex-end',
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
borderRadius: '22px',
|
borderRadius: '16px',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
}}
|
}}
|
||||||
@ -116,7 +116,7 @@ export function AgentNewAttendancePage() {
|
|||||||
style={{
|
style={{
|
||||||
width: 48,
|
width: 48,
|
||||||
height: 48,
|
height: 48,
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
placeItems: 'center',
|
placeItems: 'center',
|
||||||
background: 'linear-gradient(135deg, var(--color-accent), var(--color-primary))',
|
background: 'linear-gradient(135deg, var(--color-accent), var(--color-primary))',
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { Link, useNavigate } from 'react-router-dom';
|
import { Link, useNavigate } from 'react-router-dom';
|
||||||
import { BrandMark } from '../../../shared/components/BrandMark';
|
import { BrandMark } from '../../../shared/components/BrandMark';
|
||||||
import { useViewport } from '../../../shared/hooks/useViewport';
|
import { useViewport } from '../../../shared/hooks/useViewport';
|
||||||
@ -369,7 +369,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
style={{
|
style={{
|
||||||
justifySelf: isMobile ? 'stretch' : 'center',
|
justifySelf: isMobile ? 'stretch' : 'center',
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
background: 'rgba(0, 49, 80, 0.06)',
|
background: 'rgba(0, 49, 80, 0.06)',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
fontWeight: 700,
|
fontWeight: 700,
|
||||||
@ -382,7 +382,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
to="/home"
|
to="/home"
|
||||||
style={{
|
style={{
|
||||||
justifySelf: isMobile ? 'stretch' : 'end',
|
justifySelf: isMobile ? 'stretch' : 'end',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
background: 'var(--color-primary)',
|
background: 'var(--color-primary)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -407,7 +407,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
style={{
|
style={{
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
padding: '1.5rem',
|
padding: '1.5rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gap: '1.25rem',
|
gap: '1.25rem',
|
||||||
@ -443,7 +443,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
style={{
|
style={{
|
||||||
border: '1px solid',
|
border: '1px solid',
|
||||||
borderColor: isActive ? `${channel.accent}44` : 'var(--color-border)',
|
borderColor: isActive ? `${channel.accent}44` : 'var(--color-border)',
|
||||||
borderRadius: '22px',
|
borderRadius: '16px',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: isActive ? `${channel.accent}12` : '#fff',
|
background: isActive ? `${channel.accent}12` : '#fff',
|
||||||
textAlign: 'left',
|
textAlign: 'left',
|
||||||
@ -485,7 +485,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -508,7 +508,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
placeholder={selectedCountry.placeholder}
|
placeholder={selectedCountry.placeholder}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -525,7 +525,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
placeholder="Nome para salvar na agenda"
|
placeholder="Nome para salvar na agenda"
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -550,7 +550,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
placeholder="Ex: Departamento, vaga ou conta vinculada"
|
placeholder="Ex: Departamento, vaga ou conta vinculada"
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -565,7 +565,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
onChange={(event) => setSelectedTemplateId(event.target.value)}
|
onChange={(event) => setSelectedTemplateId(event.target.value)}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -597,7 +597,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
placeholder="Ex: 26/05/2026"
|
placeholder="Ex: 26/05/2026"
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -613,7 +613,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
placeholder="https://..."
|
placeholder="https://..."
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -629,7 +629,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
placeholder="Valor livre"
|
placeholder="Valor livre"
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -642,7 +642,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid rgba(0, 49, 80, 0.08)',
|
border: '1px solid rgba(0, 49, 80, 0.08)',
|
||||||
borderRadius: '22px',
|
borderRadius: '16px',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: 'linear-gradient(180deg, #e8f3ee, #dcefe8)',
|
background: 'linear-gradient(180deg, #e8f3ee, #dcefe8)',
|
||||||
minHeight: 220,
|
minHeight: 220,
|
||||||
@ -695,7 +695,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
placeholder="Contexto inicial deste atendimento."
|
placeholder="Contexto inicial deste atendimento."
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -716,7 +716,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
>
|
>
|
||||||
<article
|
<article
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '24px',
|
borderRadius: '18px',
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
background:
|
background:
|
||||||
'linear-gradient(135deg, rgba(0, 49, 80, 0.98), rgba(11, 90, 134, 0.94))',
|
'linear-gradient(135deg, rgba(0, 49, 80, 0.98), rgba(11, 90, 134, 0.94))',
|
||||||
@ -754,7 +754,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
|
|
||||||
<article
|
<article
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '24px',
|
borderRadius: '18px',
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
@ -773,7 +773,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
onClick={clearSelection}
|
onClick={clearSelection}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '1rem 1.1rem',
|
padding: '1rem 1.1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
@ -789,7 +789,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
disabled={!canStartAttendance || isStarting}
|
disabled={!canStartAttendance || isStarting}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '1rem 1.1rem',
|
padding: '1rem 1.1rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -808,7 +808,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
<article
|
<article
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 24,
|
borderRadius: 18,
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -829,7 +829,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
placeholder="Buscar por nome, telefone ou etiqueta"
|
placeholder="Buscar por nome, telefone ou etiqueta"
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
padding: '0.85rem 0.9rem',
|
padding: '0.85rem 0.9rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -849,7 +849,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
style={{
|
style={{
|
||||||
border: '1px solid',
|
border: '1px solid',
|
||||||
borderColor: isSelected ? 'rgba(0, 164, 183, 0.36)' : 'var(--color-border)',
|
borderColor: isSelected ? 'rgba(0, 164, 183, 0.36)' : 'var(--color-border)',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.78rem',
|
padding: '0.78rem',
|
||||||
background: isSelected ? 'rgba(0, 164, 183, 0.08)' : '#fff',
|
background: isSelected ? 'rgba(0, 164, 183, 0.08)' : '#fff',
|
||||||
textAlign: 'left',
|
textAlign: 'left',
|
||||||
@ -896,7 +896,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
onClick={clearSelection}
|
onClick={clearSelection}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.75rem',
|
padding: '0.75rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
@ -911,7 +911,7 @@ export function NewAttendancePage({ embedded = false }) {
|
|||||||
<article
|
<article
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid rgba(0, 164, 183, 0.24)',
|
border: '1px solid rgba(0, 164, 183, 0.24)',
|
||||||
borderRadius: 24,
|
borderRadius: 18,
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: 'rgba(0, 164, 183, 0.06)',
|
background: 'rgba(0, 164, 183, 0.06)',
|
||||||
color: 'var(--color-text-soft)',
|
color: 'var(--color-text-soft)',
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useLogin } from '../hooks/useLogin';
|
|||||||
const fieldStyle = {
|
const fieldStyle = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text)',
|
color: 'var(--color-text)',
|
||||||
@ -14,7 +14,7 @@ const fieldStyle = {
|
|||||||
const primaryButtonStyle = {
|
const primaryButtonStyle = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
border: 'none',
|
border: 'none',
|
||||||
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -25,7 +25,7 @@ const primaryButtonStyle = {
|
|||||||
const secondaryButtonStyle = {
|
const secondaryButtonStyle = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
border: '1px solid rgba(0, 49, 80, 0.16)',
|
border: '1px solid rgba(0, 49, 80, 0.16)',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
@ -95,7 +95,7 @@ export function LoginForm() {
|
|||||||
role="alert"
|
role="alert"
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid rgba(180, 35, 24, 0.24)',
|
border: '1px solid rgba(180, 35, 24, 0.24)',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
background: 'rgba(180, 35, 24, 0.08)',
|
background: 'rgba(180, 35, 24, 0.08)',
|
||||||
color: '#b42318',
|
color: '#b42318',
|
||||||
@ -111,7 +111,7 @@ export function LoginForm() {
|
|||||||
role="alert"
|
role="alert"
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text-soft)',
|
color: 'var(--color-text-soft)',
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export function LoginPage() {
|
|||||||
background:
|
background:
|
||||||
'linear-gradient(180deg, rgba(0, 49, 80, 0.98) 0%, rgba(11, 90, 134, 0.95) 100%)',
|
'linear-gradient(180deg, rgba(0, 49, 80, 0.98) 0%, rgba(11, 90, 134, 0.95) 100%)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
borderRadius: '32px',
|
borderRadius: '24px',
|
||||||
padding: '2.5rem',
|
padding: '2.5rem',
|
||||||
boxShadow: 'var(--shadow-lg)',
|
boxShadow: 'var(--shadow-lg)',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
@ -99,7 +99,7 @@ export function LoginPage() {
|
|||||||
key={item.label}
|
key={item.label}
|
||||||
style={{
|
style={{
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
borderRadius: '20px',
|
borderRadius: '15px',
|
||||||
background: 'rgba(255, 255, 255, 0.1)',
|
background: 'rgba(255, 255, 255, 0.1)',
|
||||||
backdropFilter: 'blur(10px)',
|
backdropFilter: 'blur(10px)',
|
||||||
}}
|
}}
|
||||||
@ -116,7 +116,7 @@ export function LoginPage() {
|
|||||||
background: 'var(--color-surface)',
|
background: 'var(--color-surface)',
|
||||||
backdropFilter: 'blur(12px)',
|
backdropFilter: 'blur(12px)',
|
||||||
border: '1px solid rgba(255, 255, 255, 0.65)',
|
border: '1px solid rgba(255, 255, 255, 0.65)',
|
||||||
borderRadius: '32px',
|
borderRadius: '24px',
|
||||||
padding: '2.5rem',
|
padding: '2.5rem',
|
||||||
boxShadow: 'var(--shadow-lg)',
|
boxShadow: 'var(--shadow-lg)',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
|
|||||||
@ -78,7 +78,7 @@ export function CallControls({ controls, isMobile = false }) {
|
|||||||
type="button"
|
type="button"
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid rgba(255, 255, 255, 0.12)',
|
border: '1px solid rgba(255, 255, 255, 0.12)',
|
||||||
borderRadius: '24px',
|
borderRadius: '18px',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: 'rgba(255, 255, 255, 0.06)',
|
background: 'rgba(255, 255, 255, 0.06)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -93,7 +93,7 @@ export function CallControls({ controls, isMobile = false }) {
|
|||||||
style={{
|
style={{
|
||||||
width: 48,
|
width: 48,
|
||||||
height: 48,
|
height: 48,
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
background: 'rgba(255, 255, 255, 0.1)',
|
background: 'rgba(255, 255, 255, 0.1)',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
placeItems: 'center',
|
placeItems: 'center',
|
||||||
|
|||||||
@ -41,7 +41,7 @@ export function CallHeader({ isMobile = false }) {
|
|||||||
to="/home"
|
to="/home"
|
||||||
style={{
|
style={{
|
||||||
justifySelf: isMobile ? 'stretch' : 'end',
|
justifySelf: isMobile ? 'stretch' : 'end',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
background: 'rgba(255, 255, 255, 0.08)',
|
background: 'rgba(255, 255, 255, 0.08)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
|
|||||||
@ -74,7 +74,7 @@ export function CallPage() {
|
|||||||
style={{
|
style={{
|
||||||
width: isMobile ? 110 : 132,
|
width: isMobile ? 110 : 132,
|
||||||
height: isMobile ? 110 : 132,
|
height: isMobile ? 110 : 132,
|
||||||
borderRadius: '32px',
|
borderRadius: '24px',
|
||||||
background: 'linear-gradient(135deg, #0d3d5d, #00a4b7)',
|
background: 'linear-gradient(135deg, #0d3d5d, #00a4b7)',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
placeItems: 'center',
|
placeItems: 'center',
|
||||||
@ -105,7 +105,7 @@ export function CallPage() {
|
|||||||
<article
|
<article
|
||||||
key={item.label}
|
key={item.label}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '22px',
|
borderRadius: '16px',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: 'rgba(255, 255, 255, 0.05)',
|
background: 'rgba(255, 255, 255, 0.05)',
|
||||||
}}
|
}}
|
||||||
@ -128,7 +128,7 @@ export function CallPage() {
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '32px',
|
borderRadius: '24px',
|
||||||
padding: isMobile ? '1.5rem' : '2.25rem',
|
padding: isMobile ? '1.5rem' : '2.25rem',
|
||||||
background:
|
background:
|
||||||
'radial-gradient(circle at top right, rgba(229, 162, 42, 0.2), transparent 28%), rgba(255, 255, 255, 0.04)',
|
'radial-gradient(circle at top right, rgba(229, 162, 42, 0.2), transparent 28%), rgba(255, 255, 255, 0.04)',
|
||||||
@ -181,7 +181,7 @@ export function CallPage() {
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '24px',
|
borderRadius: '18px',
|
||||||
padding: '1rem 1.15rem',
|
padding: '1rem 1.15rem',
|
||||||
background: 'rgba(255, 255, 255, 0.05)',
|
background: 'rgba(255, 255, 255, 0.05)',
|
||||||
color: 'rgba(255, 255, 255, 0.72)',
|
color: 'rgba(255, 255, 255, 0.72)',
|
||||||
@ -191,7 +191,7 @@ export function CallPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '24px',
|
borderRadius: '18px',
|
||||||
padding: '1rem 1.15rem',
|
padding: '1rem 1.15rem',
|
||||||
background: 'rgba(255, 255, 255, 0.05)',
|
background: 'rgba(255, 255, 255, 0.05)',
|
||||||
color: 'rgba(255, 255, 255, 0.72)',
|
color: 'rgba(255, 255, 255, 0.72)',
|
||||||
@ -203,7 +203,7 @@ export function CallPage() {
|
|||||||
type="button"
|
type="button"
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '24px',
|
borderRadius: '18px',
|
||||||
padding: '1rem 1.4rem',
|
padding: '1rem 1.4rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-secondary), #d43a3a)',
|
background: 'linear-gradient(135deg, var(--color-secondary), #d43a3a)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
|
|||||||
@ -157,7 +157,7 @@ export function ChatConversationList({
|
|||||||
style={{
|
style={{
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateRows: 'auto minmax(0, 1fr)',
|
gridTemplateRows: 'auto minmax(0, 1fr)',
|
||||||
@ -204,7 +204,7 @@ export function ChatConversationList({
|
|||||||
border: '1px solid',
|
border: '1px solid',
|
||||||
borderColor: isActive ? 'rgba(0, 164, 183, 0.26)' : 'var(--color-border)',
|
borderColor: isActive ? 'rgba(0, 164, 183, 0.26)' : 'var(--color-border)',
|
||||||
background: isActive ? 'rgba(0, 164, 183, 0.08)' : '#fff',
|
background: isActive ? 'rgba(0, 164, 183, 0.08)' : '#fff',
|
||||||
borderRadius: '20px',
|
borderRadius: '15px',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
textAlign: 'left',
|
textAlign: 'left',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -239,7 +239,7 @@ export function ChatConversationList({
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: 'rgba(0, 49, 80, 0.04)',
|
background: 'rgba(0, 49, 80, 0.04)',
|
||||||
color: 'var(--color-text-soft)',
|
color: 'var(--color-text-soft)',
|
||||||
|
|||||||
@ -19,7 +19,7 @@ export function ChatTransferPanel({
|
|||||||
const fieldStyle = {
|
const fieldStyle = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
padding: '0.9rem 1rem',
|
padding: '0.9rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -30,7 +30,7 @@ export function ChatTransferPanel({
|
|||||||
style={{
|
style={{
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gap: '1rem',
|
gap: '1rem',
|
||||||
@ -112,7 +112,7 @@ export function ChatTransferPanel({
|
|||||||
onClick={onSubmit}
|
onClick={onSubmit}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
|
|||||||
@ -91,28 +91,21 @@ function DateSeparator({ label }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MediaRenderer({ message, contactId, onLoadMedia, isAgent }) {
|
function MediaRenderer({ message, isAgent }) {
|
||||||
const mediaUrl = useMemo(() => getMediaUrl(message.media), [message.media]);
|
const mediaUrl = message.mediaUrl || useMemo(() => getMediaUrl(message.media), [message.media]);
|
||||||
const mimetype = message.media?.mimetype || '';
|
const mimetype = message.mediaMimeType || message.media?.mimetype || '';
|
||||||
const filename = message.media?.filename || 'arquivo';
|
const filename = message.media?.filename || 'arquivo';
|
||||||
|
|
||||||
useEffect(() => {
|
if (!message.hasMedia && !mediaUrl) return null;
|
||||||
if (!message.hasMedia || message.media?.data || message.mediaLoading || message.mediaError) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
onLoadMedia?.(contactId, message.id);
|
|
||||||
}, [contactId, message, onLoadMedia]);
|
|
||||||
|
|
||||||
if (!message.hasMedia && !message.media) return null;
|
if (!mediaUrl) {
|
||||||
|
|
||||||
if (message.mediaLoading || (!message.media?.data && !message.mediaError)) {
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
width: 260,
|
width: 260,
|
||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
height: 150,
|
height: 150,
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
background: isAgent ? 'rgba(255,255,255,0.18)' : 'rgba(0,49,80,0.08)',
|
background: isAgent ? 'rgba(255,255,255,0.18)' : 'rgba(0,49,80,0.08)',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
placeItems: 'center',
|
placeItems: 'center',
|
||||||
@ -125,14 +118,6 @@ function MediaRenderer({ message, contactId, onLoadMedia, isAgent }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.mediaError) {
|
|
||||||
return (
|
|
||||||
<span style={{ color: isAgent ? '#fff' : 'var(--color-text-soft)', fontWeight: 700 }}>
|
|
||||||
Não foi possível carregar a mídia.
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mimetype.startsWith('image/')) {
|
if (mimetype.startsWith('image/')) {
|
||||||
return (
|
return (
|
||||||
<a href={mediaUrl} target="_blank" rel="noreferrer" style={{ display: 'block' }}>
|
<a href={mediaUrl} target="_blank" rel="noreferrer" style={{ display: 'block' }}>
|
||||||
@ -145,7 +130,7 @@ function MediaRenderer({ message, contactId, onLoadMedia, isAgent }) {
|
|||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
maxHeight: 340,
|
maxHeight: 340,
|
||||||
objectFit: 'cover',
|
objectFit: 'cover',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
boxShadow: '0 14px 30px rgba(0,0,0,0.18)',
|
boxShadow: '0 14px 30px rgba(0,0,0,0.18)',
|
||||||
transition: 'transform 160ms ease',
|
transition: 'transform 160ms ease',
|
||||||
}}
|
}}
|
||||||
@ -168,7 +153,7 @@ function MediaRenderer({ message, contactId, onLoadMedia, isAgent }) {
|
|||||||
style={{
|
style={{
|
||||||
width: 320,
|
width: 320,
|
||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
background: '#111',
|
background: '#111',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -189,7 +174,7 @@ function MediaRenderer({ message, contactId, onLoadMedia, isAgent }) {
|
|||||||
gap: '0.75rem',
|
gap: '0.75rem',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
padding: '0.85rem',
|
padding: '0.85rem',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
background: isAgent ? 'rgba(255,255,255,0.16)' : '#fff',
|
background: isAgent ? 'rgba(255,255,255,0.16)' : '#fff',
|
||||||
color: isAgent ? '#fff' : 'var(--color-primary)',
|
color: isAgent ? '#fff' : 'var(--color-primary)',
|
||||||
fontWeight: 700,
|
fontWeight: 700,
|
||||||
@ -209,7 +194,7 @@ function AttachmentPreview({ file, onRemove }) {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.75rem',
|
padding: '0.75rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateColumns: 'auto 1fr auto',
|
gridTemplateColumns: 'auto 1fr auto',
|
||||||
@ -222,14 +207,14 @@ function AttachmentPreview({ file, onRemove }) {
|
|||||||
<img
|
<img
|
||||||
src={mediaUrl}
|
src={mediaUrl}
|
||||||
alt={file.name}
|
alt={file.name}
|
||||||
style={{ width: 54, height: 54, objectFit: 'cover', borderRadius: 12 }}
|
style={{ width: 54, height: 54, objectFit: 'cover', borderRadius: 9 }}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
width: 54,
|
width: 54,
|
||||||
height: 54,
|
height: 54,
|
||||||
borderRadius: 12,
|
borderRadius: 9,
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
placeItems: 'center',
|
placeItems: 'center',
|
||||||
background: 'rgba(0,49,80,0.08)',
|
background: 'rgba(0,49,80,0.08)',
|
||||||
@ -251,7 +236,7 @@ function AttachmentPreview({ file, onRemove }) {
|
|||||||
title="Remover anexo"
|
title="Remover anexo"
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 12,
|
borderRadius: 9,
|
||||||
width: 36,
|
width: 36,
|
||||||
height: 36,
|
height: 36,
|
||||||
background: 'rgba(214, 40, 40, 0.1)',
|
background: 'rgba(214, 40, 40, 0.1)',
|
||||||
@ -349,7 +334,7 @@ export function ChatWindow({
|
|||||||
style={{
|
style={{
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateRows: 'auto minmax(0, 1fr)',
|
gridTemplateRows: 'auto minmax(0, 1fr)',
|
||||||
@ -382,7 +367,7 @@ export function ChatWindow({
|
|||||||
style={{
|
style={{
|
||||||
maxWidth: 460,
|
maxWidth: 460,
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 20,
|
borderRadius: 15,
|
||||||
padding: '1.2rem',
|
padding: '1.2rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text-soft)',
|
color: 'var(--color-text-soft)',
|
||||||
@ -404,7 +389,7 @@ export function ChatWindow({
|
|||||||
style={{
|
style={{
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateRows: 'auto minmax(0, 1fr) auto',
|
gridTemplateRows: 'auto minmax(0, 1fr) auto',
|
||||||
@ -442,7 +427,7 @@ export function ChatWindow({
|
|||||||
disabled
|
disabled
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
padding: '0.8rem 0.95rem',
|
padding: '0.8rem 0.95rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
@ -459,7 +444,7 @@ export function ChatWindow({
|
|||||||
onClick={() => onAssumeChat?.()}
|
onClick={() => onAssumeChat?.()}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
padding: '0.8rem 1rem',
|
padding: '0.8rem 1rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -476,7 +461,7 @@ export function ChatWindow({
|
|||||||
onClick={onReleaseChat}
|
onClick={onReleaseChat}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
padding: '0.8rem 1rem',
|
padding: '0.8rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
@ -490,7 +475,7 @@ export function ChatWindow({
|
|||||||
onClick={onCloseChat}
|
onClick={onCloseChat}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
padding: '0.8rem 1rem',
|
padding: '0.8rem 1rem',
|
||||||
background: 'rgba(181, 31, 31, 0.1)',
|
background: 'rgba(181, 31, 31, 0.1)',
|
||||||
color: 'var(--color-secondary)',
|
color: 'var(--color-secondary)',
|
||||||
@ -507,7 +492,7 @@ export function ChatWindow({
|
|||||||
disabled={!canReply}
|
disabled={!canReply}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
padding: '0.8rem 1rem',
|
padding: '0.8rem 1rem',
|
||||||
background: 'rgba(0, 49, 80, 0.08)',
|
background: 'rgba(0, 49, 80, 0.08)',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
@ -523,7 +508,7 @@ export function ChatWindow({
|
|||||||
style={{
|
style={{
|
||||||
gridColumn: '1 / -1',
|
gridColumn: '1 / -1',
|
||||||
border: '1px solid rgba(0, 164, 183, 0.24)',
|
border: '1px solid rgba(0, 164, 183, 0.24)',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
background: 'rgba(0, 164, 183, 0.07)',
|
background: 'rgba(0, 164, 183, 0.07)',
|
||||||
color: 'var(--color-text)',
|
color: 'var(--color-text)',
|
||||||
@ -600,8 +585,6 @@ export function ChatWindow({
|
|||||||
>
|
>
|
||||||
<MediaRenderer
|
<MediaRenderer
|
||||||
message={message}
|
message={message}
|
||||||
contactId={safeContact.id}
|
|
||||||
onLoadMedia={onLoadMedia}
|
|
||||||
isAgent={isAgent}
|
isAgent={isAgent}
|
||||||
/>
|
/>
|
||||||
{parsedText.senderLabel ? (
|
{parsedText.senderLabel ? (
|
||||||
@ -652,7 +635,7 @@ export function ChatWindow({
|
|||||||
style={{
|
style={{
|
||||||
justifySelf: 'center',
|
justifySelf: 'center',
|
||||||
padding: '0.8rem 1rem',
|
padding: '0.8rem 1rem',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
background: 'rgba(0,49,80,0.06)',
|
background: 'rgba(0,49,80,0.06)',
|
||||||
color: 'var(--color-text-soft)',
|
color: 'var(--color-text-soft)',
|
||||||
fontWeight: 700,
|
fontWeight: 700,
|
||||||
@ -694,7 +677,7 @@ export function ChatWindow({
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.8rem 1rem',
|
padding: '0.8rem 1rem',
|
||||||
background: 'rgba(0, 49, 80, 0.04)',
|
background: 'rgba(0, 49, 80, 0.04)',
|
||||||
color: 'var(--color-text-soft)',
|
color: 'var(--color-text-soft)',
|
||||||
@ -727,7 +710,7 @@ export function ChatWindow({
|
|||||||
title="Anexar arquivo"
|
title="Anexar arquivo"
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
width: 48,
|
width: 48,
|
||||||
height: 48,
|
height: 48,
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -774,7 +757,7 @@ export function ChatWindow({
|
|||||||
}
|
}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -788,7 +771,7 @@ export function ChatWindow({
|
|||||||
disabled={!safeContact.id || !canReply}
|
disabled={!safeContact.id || !canReply}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1.2rem',
|
padding: '0.95rem 1.2rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
|
|||||||
@ -70,7 +70,7 @@ export function ContactProfilePanel({ isOpen, contact, onClose, onSaved }) {
|
|||||||
const fieldStyle = {
|
const fieldStyle = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
padding: '0.9rem 1rem',
|
padding: '0.9rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -103,7 +103,7 @@ export function ContactProfilePanel({ isOpen, contact, onClose, onSaved }) {
|
|||||||
style={{
|
style={{
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gap: '1rem',
|
gap: '1rem',
|
||||||
@ -182,7 +182,7 @@ export function ContactProfilePanel({ isOpen, contact, onClose, onSaved }) {
|
|||||||
disabled={isSaving}
|
disabled={isSaving}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
|
|||||||
@ -96,14 +96,18 @@ function normalizeChat(chat) {
|
|||||||
function normalizeMessage(message) {
|
function normalizeMessage(message) {
|
||||||
const id = getSerializedId(message.id) || message.id || `msg-${Date.now()}`;
|
const id = getSerializedId(message.id) || message.id || `msg-${Date.now()}`;
|
||||||
const sender = message.sender || (message.fromMe ? 'agent' : 'customer');
|
const sender = message.sender || (message.fromMe ? 'agent' : 'customer');
|
||||||
|
const mediaUrl = message.mediaUrl || message.media_path || null;
|
||||||
|
const mediaMimeType = message.mediaMimeType || message.media_mime_type || null;
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
chatId: message.from || message.to || message.chatId,
|
chatId: message.from || message.to || message.chatId,
|
||||||
sender,
|
sender,
|
||||||
text: message.body ?? message.text ?? '',
|
text: message.body ?? message.text ?? '',
|
||||||
timestamp: message.timestamp,
|
timestamp: message.timestamp,
|
||||||
hasMedia: Boolean(message.hasMedia || message.media),
|
hasMedia: Boolean(message.hasMedia || message.media || mediaUrl),
|
||||||
media: message.media || null,
|
media: message.media || null,
|
||||||
|
mediaUrl,
|
||||||
|
mediaMimeType,
|
||||||
mediaLoading: false,
|
mediaLoading: false,
|
||||||
mediaError: null,
|
mediaError: null,
|
||||||
};
|
};
|
||||||
@ -295,7 +299,7 @@ export function useChat() {
|
|||||||
activeAssignment?.status === 'queued' &&
|
activeAssignment?.status === 'queued' &&
|
||||||
(isAdminUser || !activeAssignment.area_nome || currentUserAreas.includes(activeAssignment.area_nome)),
|
(isAdminUser || !activeAssignment.area_nome || currentUserAreas.includes(activeAssignment.area_nome)),
|
||||||
);
|
);
|
||||||
const canAssumeChat = Boolean(!isPaused && activeContact?.id?.includes('@') && currentUserId && isQueuedForUserArea);
|
const canAssumeChat = Boolean(!isPaused && activeContact?.id && currentUserId && isQueuedForUserArea);
|
||||||
const canReply = Boolean(!isPaused && isAssignedToCurrentUser && !isWaitingCustomerReply);
|
const canReply = Boolean(!isPaused && isAssignedToCurrentUser && !isWaitingCustomerReply);
|
||||||
const assignmentLabel = activeAssignment?.user_id
|
const assignmentLabel = activeAssignment?.user_id
|
||||||
? isWaitingCustomerReply
|
? isWaitingCustomerReply
|
||||||
@ -460,7 +464,7 @@ export function useChat() {
|
|||||||
let isMounted = true;
|
let isMounted = true;
|
||||||
|
|
||||||
async function loadMessages() {
|
async function loadMessages() {
|
||||||
if (!activeContactId.includes('@')) return;
|
if (!activeContactId) return;
|
||||||
setIsLoadingMessages(true);
|
setIsLoadingMessages(true);
|
||||||
try {
|
try {
|
||||||
const data = await listWhatsappMessages(activeContactId);
|
const data = await listWhatsappMessages(activeContactId);
|
||||||
@ -628,7 +632,7 @@ export function useChat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function assumeChat(contactId = activeContactId) {
|
async function assumeChat(contactId = activeContactId) {
|
||||||
if (!contactId?.includes('@') || !currentUserId) return null;
|
if (!contactId || !currentUserId) return null;
|
||||||
const targetContact = contacts.find((contact) => contact.id === contactId) || activeContact;
|
const targetContact = contacts.find((contact) => contact.id === contactId) || activeContact;
|
||||||
const targetAssignment = targetContact?.assignment || null;
|
const targetAssignment = targetContact?.assignment || null;
|
||||||
const areaId = targetContact?.areaId || targetAssignment?.area_id || areaOptions.find((area) => currentUserAreas.includes(area.nome))?.id;
|
const areaId = targetContact?.areaId || targetAssignment?.area_id || areaOptions.find((area) => currentUserAreas.includes(area.nome))?.id;
|
||||||
@ -636,7 +640,7 @@ export function useChat() {
|
|||||||
const assignment = await assignWhatsappChat({
|
const assignment = await assignWhatsappChat({
|
||||||
chatId: contactId,
|
chatId: contactId,
|
||||||
userId: String(currentUserId),
|
userId: String(currentUserId),
|
||||||
areaId,
|
areaId: areaId != null ? String(areaId) : undefined,
|
||||||
});
|
});
|
||||||
updateContact(contactId, (contact) => ({
|
updateContact(contactId, (contact) => ({
|
||||||
...contact,
|
...contact,
|
||||||
@ -653,7 +657,7 @@ export function useChat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function releaseChat() {
|
async function releaseChat() {
|
||||||
if (!activeContactId?.includes('@')) return;
|
if (!activeContactId) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const assignment = await releaseWhatsappChat(activeContactId);
|
const assignment = await releaseWhatsappChat(activeContactId);
|
||||||
@ -670,7 +674,7 @@ export function useChat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function closeChat() {
|
async function closeChat() {
|
||||||
if (!activeContactId?.includes('@')) return;
|
if (!activeContactId) return;
|
||||||
|
|
||||||
const confirmed = window.confirm('Tem certeza que deseja encerrar este atendimento?');
|
const confirmed = window.confirm('Tem certeza que deseja encerrar este atendimento?');
|
||||||
if (!confirmed) return;
|
if (!confirmed) return;
|
||||||
@ -786,7 +790,7 @@ export function useChat() {
|
|||||||
}
|
}
|
||||||
setAttachedFile(null);
|
setAttachedFile(null);
|
||||||
|
|
||||||
if (!contactId.includes('@')) return;
|
if (!contactId) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await sendWhatsappMessage({
|
await sendWhatsappMessage({
|
||||||
|
|||||||
@ -87,7 +87,7 @@ export function ChatPage() {
|
|||||||
width: 'min(1680px, calc(100vw - 3rem))',
|
width: 'min(1680px, calc(100vw - 3rem))',
|
||||||
margin: '0 auto',
|
margin: '0 auto',
|
||||||
background: 'var(--color-surface-strong)',
|
background: 'var(--color-surface-strong)',
|
||||||
borderRadius: '32px',
|
borderRadius: '24px',
|
||||||
boxShadow: 'var(--shadow-lg)',
|
boxShadow: 'var(--shadow-lg)',
|
||||||
padding: '1.5rem',
|
padding: '1.5rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -107,7 +107,7 @@ export function ChatPage() {
|
|||||||
style={{
|
style={{
|
||||||
justifySelf: isMobile ? 'stretch' : 'center',
|
justifySelf: isMobile ? 'stretch' : 'center',
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
background: 'rgba(0, 49, 80, 0.06)',
|
background: 'rgba(0, 49, 80, 0.06)',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
fontWeight: 700,
|
fontWeight: 700,
|
||||||
@ -120,7 +120,7 @@ export function ChatPage() {
|
|||||||
to="/home"
|
to="/home"
|
||||||
style={{
|
style={{
|
||||||
justifySelf: isMobile ? 'stretch' : 'end',
|
justifySelf: isMobile ? 'stretch' : 'end',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
background: 'var(--color-primary)',
|
background: 'var(--color-primary)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -197,7 +197,7 @@ export function ChatPage() {
|
|||||||
disabled={isPaused}
|
disabled={isPaused}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
|
|||||||
@ -45,7 +45,7 @@ export function AttendantOpsPanel({
|
|||||||
<article
|
<article
|
||||||
style={{
|
style={{
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
borderRadius: '24px',
|
borderRadius: '18px',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
background: 'linear-gradient(145deg, #ffffff, #f8fafc)',
|
background: 'linear-gradient(145deg, #ffffff, #f8fafc)',
|
||||||
boxShadow: 'var(--shadow-sm)',
|
boxShadow: 'var(--shadow-sm)',
|
||||||
@ -77,7 +77,7 @@ export function AttendantOpsPanel({
|
|||||||
<article
|
<article
|
||||||
style={{
|
style={{
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
borderRadius: '24px',
|
borderRadius: '18px',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
background: 'linear-gradient(145deg, #ffffff, #f8fafc)',
|
background: 'linear-gradient(145deg, #ffffff, #f8fafc)',
|
||||||
boxShadow: 'var(--shadow-sm)',
|
boxShadow: 'var(--shadow-sm)',
|
||||||
@ -99,7 +99,7 @@ export function AttendantOpsPanel({
|
|||||||
<article
|
<article
|
||||||
style={{
|
style={{
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
borderRadius: '24px',
|
borderRadius: '18px',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
background: 'linear-gradient(145deg, #ffffff, #f8fafc)',
|
background: 'linear-gradient(145deg, #ffffff, #f8fafc)',
|
||||||
boxShadow: 'var(--shadow-sm)',
|
boxShadow: 'var(--shadow-sm)',
|
||||||
@ -116,7 +116,7 @@ export function AttendantOpsPanel({
|
|||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
border: 'none',
|
border: 'none',
|
||||||
background: isPaused ? 'rgba(16, 185, 129, 0.1)' : 'rgba(239, 68, 68, 0.1)',
|
background: isPaused ? 'rgba(16, 185, 129, 0.1)' : 'rgba(239, 68, 68, 0.1)',
|
||||||
color: isPaused ? '#10b981' : '#ef4444',
|
color: isPaused ? '#10b981' : '#ef4444',
|
||||||
|
|||||||
@ -35,7 +35,7 @@ export function CallsWorkspace({ calls, isWideDesktop = false, isDesktop = false
|
|||||||
onClick={() => navigate('/call')}
|
onClick={() => navigate('/call')}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1.1rem',
|
padding: '0.95rem 1.1rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -51,7 +51,7 @@ export function CallsWorkspace({ calls, isWideDesktop = false, isDesktop = false
|
|||||||
<article
|
<article
|
||||||
key={call.id}
|
key={call.id}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '22px',
|
borderRadius: '16px',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
padding: '1rem 1.1rem',
|
padding: '1rem 1.1rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -78,7 +78,7 @@ export function CallsWorkspace({ calls, isWideDesktop = false, isDesktop = false
|
|||||||
onClick={() => navigate('/call')}
|
onClick={() => navigate('/call')}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
padding: '0.7rem 0.95rem',
|
padding: '0.7rem 0.95rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
|
|||||||
@ -9,7 +9,7 @@ export function HomeSidebar({ items, activeItem, isMobile = false }) {
|
|||||||
style={{
|
style={{
|
||||||
background: 'linear-gradient(180deg, rgba(0, 49, 80, 0.98), rgba(7, 64, 98, 0.96))',
|
background: 'linear-gradient(180deg, rgba(0, 49, 80, 0.98), rgba(7, 64, 98, 0.96))',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
padding: '1.5rem',
|
padding: '1.5rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gap: '1.25rem',
|
gap: '1.25rem',
|
||||||
@ -21,7 +21,7 @@ export function HomeSidebar({ items, activeItem, isMobile = false }) {
|
|||||||
onClick={() => navigate('/home')}
|
onClick={() => navigate('/home')}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '20px',
|
borderRadius: '15px',
|
||||||
padding: '1rem 1.15rem',
|
padding: '1rem 1.15rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-highlight), #f3b94d)',
|
background: 'linear-gradient(135deg, var(--color-highlight), #f3b94d)',
|
||||||
color: '#132534',
|
color: '#132534',
|
||||||
@ -49,7 +49,7 @@ export function HomeSidebar({ items, activeItem, isMobile = false }) {
|
|||||||
onClick={() => item.route && navigate(item.route)}
|
onClick={() => item.route && navigate(item.route)}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.9rem 1rem',
|
padding: '0.9rem 1rem',
|
||||||
background: isActive ? 'rgba(255, 255, 255, 0.14)' : 'transparent',
|
background: isActive ? 'rgba(255, 255, 255, 0.14)' : 'transparent',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -87,7 +87,7 @@ export function HomeSidebar({ items, activeItem, isMobile = false }) {
|
|||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid rgba(255, 255, 255, 0.2)',
|
border: '1px solid rgba(255, 255, 255, 0.2)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.9rem 1rem',
|
padding: '0.9rem 1rem',
|
||||||
background: 'transparent',
|
background: 'transparent',
|
||||||
color: '#ef4444',
|
color: '#ef4444',
|
||||||
|
|||||||
@ -57,7 +57,7 @@ export function HomeTopbar({
|
|||||||
style={{
|
style={{
|
||||||
display: 'inline-flex',
|
display: 'inline-flex',
|
||||||
padding: '0.35rem',
|
padding: '0.35rem',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
background: 'rgba(0, 49, 80, 0.06)',
|
background: 'rgba(0, 49, 80, 0.06)',
|
||||||
gap: '0.35rem',
|
gap: '0.35rem',
|
||||||
width: isMobile ? '100%' : 'fit-content',
|
width: isMobile ? '100%' : 'fit-content',
|
||||||
@ -75,7 +75,7 @@ export function HomeTopbar({
|
|||||||
onClick={() => onTabChange(tab.id)}
|
onClick={() => onTabChange(tab.id)}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
padding: '0.8rem 1rem',
|
padding: '0.8rem 1rem',
|
||||||
background: isActive ? 'var(--color-primary)' : 'transparent',
|
background: isActive ? 'var(--color-primary)' : 'transparent',
|
||||||
color: isActive ? '#fff' : 'var(--color-primary)',
|
color: isActive ? '#fff' : 'var(--color-primary)',
|
||||||
@ -91,7 +91,7 @@ export function HomeTopbar({
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
padding: '0.9rem 1.1rem',
|
padding: '0.9rem 1.1rem',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
color: 'var(--color-text-soft)',
|
color: 'var(--color-text-soft)',
|
||||||
@ -115,7 +115,7 @@ export function HomeTopbar({
|
|||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -145,7 +145,7 @@ export function HomeTopbar({
|
|||||||
style={{
|
style={{
|
||||||
width: 48,
|
width: 48,
|
||||||
height: 48,
|
height: 48,
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
placeItems: 'center',
|
placeItems: 'center',
|
||||||
background: 'linear-gradient(135deg, var(--color-accent), var(--color-primary))',
|
background: 'linear-gradient(135deg, var(--color-accent), var(--color-primary))',
|
||||||
|
|||||||
@ -370,7 +370,7 @@ export function MessagesWorkspace({
|
|||||||
style={{
|
style={{
|
||||||
border: '1px solid',
|
border: '1px solid',
|
||||||
borderColor: isActive ? 'rgba(0, 164, 183, 0.26)' : 'var(--color-border)',
|
borderColor: isActive ? 'rgba(0, 164, 183, 0.26)' : 'var(--color-border)',
|
||||||
borderRadius: '20px',
|
borderRadius: '15px',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: isActive ? 'rgba(0, 164, 183, 0.08)' : '#fff',
|
background: isActive ? 'rgba(0, 164, 183, 0.08)' : '#fff',
|
||||||
textAlign: 'left',
|
textAlign: 'left',
|
||||||
@ -417,7 +417,7 @@ export function MessagesWorkspace({
|
|||||||
disabled={isPaused}
|
disabled={isPaused}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
@ -471,7 +471,7 @@ export function MessagesWorkspace({
|
|||||||
disabled={isPaused}
|
disabled={isPaused}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
padding: '0.7rem 0.9rem',
|
padding: '0.7rem 0.9rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
@ -486,7 +486,7 @@ export function MessagesWorkspace({
|
|||||||
type="button"
|
type="button"
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
padding: '0.7rem 0.9rem',
|
padding: '0.7rem 0.9rem',
|
||||||
background: 'rgba(0, 49, 80, 0.08)',
|
background: 'rgba(0, 49, 80, 0.08)',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
@ -602,7 +602,7 @@ export function MessagesWorkspace({
|
|||||||
disabled={isPaused}
|
disabled={isPaused}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
fontWeight: 900,
|
fontWeight: 900,
|
||||||
@ -618,7 +618,7 @@ export function MessagesWorkspace({
|
|||||||
disabled={isPaused}
|
disabled={isPaused}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid rgba(0, 164, 183, 0.32)',
|
border: '1px solid rgba(0, 164, 183, 0.32)',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
padding: '0.75rem 0.9rem',
|
padding: '0.75rem 0.9rem',
|
||||||
background: 'rgba(0, 164, 183, 0.07)',
|
background: 'rgba(0, 164, 183, 0.07)',
|
||||||
color: 'var(--color-text)',
|
color: 'var(--color-text)',
|
||||||
@ -642,7 +642,7 @@ export function MessagesWorkspace({
|
|||||||
title="Próxima resposta"
|
title="Próxima resposta"
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
fontWeight: 900,
|
fontWeight: 900,
|
||||||
@ -685,7 +685,7 @@ export function MessagesWorkspace({
|
|||||||
<article
|
<article
|
||||||
key={message.id}
|
key={message.id}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem',
|
padding: '0.95rem',
|
||||||
background: 'rgba(0, 49, 80, 0.04)',
|
background: 'rgba(0, 49, 80, 0.04)',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -708,7 +708,7 @@ export function MessagesWorkspace({
|
|||||||
rows={4}
|
rows={4}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
padding: '0.85rem 0.9rem',
|
padding: '0.85rem 0.9rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text)',
|
color: 'var(--color-text)',
|
||||||
@ -725,7 +725,7 @@ export function MessagesWorkspace({
|
|||||||
disabled={!currentUserId}
|
disabled={!currentUserId}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -747,7 +747,7 @@ export function MessagesWorkspace({
|
|||||||
key={note.id}
|
key={note.id}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
padding: '0.8rem',
|
padding: '0.8rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
|
|||||||
@ -71,7 +71,7 @@ export function AgentMassMessagePage() {
|
|||||||
width: 'min(1680px, calc(100vw - 3rem))',
|
width: 'min(1680px, calc(100vw - 3rem))',
|
||||||
margin: '0 auto',
|
margin: '0 auto',
|
||||||
background: 'var(--color-surface-strong)',
|
background: 'var(--color-surface-strong)',
|
||||||
borderRadius: '32px',
|
borderRadius: '24px',
|
||||||
boxShadow: 'var(--shadow-lg)',
|
boxShadow: 'var(--shadow-lg)',
|
||||||
padding: '1.5rem',
|
padding: '1.5rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -91,7 +91,7 @@ export function AgentMassMessagePage() {
|
|||||||
style={{
|
style={{
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
padding: '1.5rem',
|
padding: '1.5rem',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -112,7 +112,7 @@ export function AgentMassMessagePage() {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
padding: '1.1rem 1.25rem',
|
padding: '1.1rem 1.25rem',
|
||||||
borderRadius: '22px',
|
borderRadius: '16px',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
}}
|
}}
|
||||||
@ -131,7 +131,7 @@ export function AgentMassMessagePage() {
|
|||||||
justifySelf: isMobile ? 'stretch' : 'end',
|
justifySelf: isMobile ? 'stretch' : 'end',
|
||||||
justifyContent: isMobile ? 'space-between' : 'flex-end',
|
justifyContent: isMobile ? 'space-between' : 'flex-end',
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
borderRadius: '22px',
|
borderRadius: '16px',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
}}
|
}}
|
||||||
@ -147,7 +147,7 @@ export function AgentMassMessagePage() {
|
|||||||
style={{
|
style={{
|
||||||
width: 48,
|
width: 48,
|
||||||
height: 48,
|
height: 48,
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
placeItems: 'center',
|
placeItems: 'center',
|
||||||
background: 'linear-gradient(135deg, var(--color-accent), var(--color-primary))',
|
background: 'linear-gradient(135deg, var(--color-accent), var(--color-primary))',
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { sidebarItems } from '../services/homeMocks';
|
|||||||
const inputStyle = {
|
const inputStyle = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.85rem 0.9rem',
|
padding: '0.85rem 0.9rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text)',
|
color: 'var(--color-text)',
|
||||||
@ -158,7 +158,7 @@ export function ContactsPanel({ embedded = false }) {
|
|||||||
<aside
|
<aside
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 24,
|
borderRadius: 18,
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -177,7 +177,7 @@ export function ContactsPanel({ embedded = false }) {
|
|||||||
onClick={startNewContact}
|
onClick={startNewContact}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.7rem 0.85rem',
|
padding: '0.7rem 0.85rem',
|
||||||
background: 'var(--color-highlight)',
|
background: 'var(--color-highlight)',
|
||||||
color: '#132534',
|
color: '#132534',
|
||||||
@ -206,7 +206,7 @@ export function ContactsPanel({ embedded = false }) {
|
|||||||
style={{
|
style={{
|
||||||
border: '1px solid',
|
border: '1px solid',
|
||||||
borderColor: isSelected ? 'rgba(0, 164, 183, 0.36)' : 'var(--color-border)',
|
borderColor: isSelected ? 'rgba(0, 164, 183, 0.36)' : 'var(--color-border)',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.8rem',
|
padding: '0.8rem',
|
||||||
background: isSelected ? 'rgba(0, 164, 183, 0.08)' : '#fff',
|
background: isSelected ? 'rgba(0, 164, 183, 0.08)' : '#fff',
|
||||||
textAlign: 'left',
|
textAlign: 'left',
|
||||||
@ -238,7 +238,7 @@ export function ContactsPanel({ embedded = false }) {
|
|||||||
onSubmit={handleSave}
|
onSubmit={handleSave}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 24,
|
borderRadius: 18,
|
||||||
padding: '1.2rem',
|
padding: '1.2rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -324,7 +324,7 @@ export function ContactsPanel({ embedded = false }) {
|
|||||||
disabled={isSaving}
|
disabled={isSaving}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -349,7 +349,7 @@ export function ContactsPanel({ embedded = false }) {
|
|||||||
width: 'min(1680px, calc(100vw - 3rem))',
|
width: 'min(1680px, calc(100vw - 3rem))',
|
||||||
margin: '0 auto',
|
margin: '0 auto',
|
||||||
background: 'var(--color-surface-strong)',
|
background: 'var(--color-surface-strong)',
|
||||||
borderRadius: '32px',
|
borderRadius: '24px',
|
||||||
boxShadow: 'var(--shadow-lg)',
|
boxShadow: 'var(--shadow-lg)',
|
||||||
padding: '1.5rem',
|
padding: '1.5rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -369,7 +369,7 @@ export function ContactsPanel({ embedded = false }) {
|
|||||||
style={{
|
style={{
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
padding: '1.5rem',
|
padding: '1.5rem',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -390,7 +390,7 @@ export function ContactsPanel({ embedded = false }) {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
padding: '1.1rem 1.25rem',
|
padding: '1.1rem 1.25rem',
|
||||||
borderRadius: '22px',
|
borderRadius: '16px',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
}}
|
}}
|
||||||
@ -409,7 +409,7 @@ export function ContactsPanel({ embedded = false }) {
|
|||||||
justifySelf: isMobile ? 'stretch' : 'end',
|
justifySelf: isMobile ? 'stretch' : 'end',
|
||||||
justifyContent: isMobile ? 'space-between' : 'flex-end',
|
justifyContent: isMobile ? 'space-between' : 'flex-end',
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
borderRadius: '22px',
|
borderRadius: '16px',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
}}
|
}}
|
||||||
@ -425,7 +425,7 @@ export function ContactsPanel({ embedded = false }) {
|
|||||||
style={{
|
style={{
|
||||||
width: 48,
|
width: 48,
|
||||||
height: 48,
|
height: 48,
|
||||||
borderRadius: '16px',
|
borderRadius: '12px',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
placeItems: 'center',
|
placeItems: 'center',
|
||||||
background: 'linear-gradient(135deg, var(--color-accent), var(--color-primary))',
|
background: 'linear-gradient(135deg, var(--color-accent), var(--color-primary))',
|
||||||
|
|||||||
@ -106,7 +106,7 @@ export function HomePage() {
|
|||||||
width: 'min(1680px, calc(100vw - 3rem))',
|
width: 'min(1680px, calc(100vw - 3rem))',
|
||||||
margin: '0 auto',
|
margin: '0 auto',
|
||||||
background: 'var(--color-surface-strong)',
|
background: 'var(--color-surface-strong)',
|
||||||
borderRadius: '32px',
|
borderRadius: '24px',
|
||||||
boxShadow: 'var(--shadow-lg)',
|
boxShadow: 'var(--shadow-lg)',
|
||||||
padding: '1.5rem',
|
padding: '1.5rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -131,7 +131,7 @@ export function HomePage() {
|
|||||||
style={{
|
style={{
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
padding: '1.5rem',
|
padding: '1.5rem',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -170,7 +170,7 @@ export function HomePage() {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 18,
|
borderRadius: 14,
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text-soft)',
|
color: 'var(--color-text-soft)',
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export function UnassignedHomePage() {
|
|||||||
width: 'min(760px, 100%)',
|
width: 'min(760px, 100%)',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '32px',
|
borderRadius: '24px',
|
||||||
boxShadow: 'var(--shadow-lg)',
|
boxShadow: 'var(--shadow-lg)',
|
||||||
padding: '2rem',
|
padding: '2rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -56,7 +56,7 @@ export function UnassignedHomePage() {
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '24px',
|
borderRadius: '18px',
|
||||||
background: 'rgba(0, 49, 80, 0.04)',
|
background: 'rgba(0, 49, 80, 0.04)',
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -75,7 +75,7 @@ export function UnassignedHomePage() {
|
|||||||
onClick={handleLogout}
|
onClick={handleLogout}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.95rem 1.15rem',
|
padding: '0.95rem 1.15rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export function DataPanel({ title, description, actionLabel, onAction, children
|
|||||||
onClick={onAction}
|
onClick={onAction}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.9rem 1rem',
|
padding: '0.9rem 1rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import {
|
|||||||
const fieldStyle = {
|
const fieldStyle = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.78rem 0.9rem',
|
padding: '0.78rem 0.9rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text)',
|
color: 'var(--color-text)',
|
||||||
@ -21,7 +21,7 @@ const fieldStyle = {
|
|||||||
|
|
||||||
const primaryButton = {
|
const primaryButton = {
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.78rem 1rem',
|
padding: '0.78rem 1rem',
|
||||||
background: 'var(--color-primary)',
|
background: 'var(--color-primary)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -30,7 +30,7 @@ const primaryButton = {
|
|||||||
|
|
||||||
const ghostButton = {
|
const ghostButton = {
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.72rem 0.9rem',
|
padding: '0.72rem 0.9rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text)',
|
color: 'var(--color-text)',
|
||||||
@ -109,7 +109,7 @@ function WhatsAppPreview({ message }) {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
background: '#e7f5ef',
|
background: '#e7f5ef',
|
||||||
borderRadius: 18,
|
borderRadius: 14,
|
||||||
padding: '0.85rem',
|
padding: '0.85rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gap: '0.45rem',
|
gap: '0.45rem',
|
||||||
@ -172,7 +172,7 @@ function FlowNode({ node, areasById, onAdd, onEdit, onDelete, level = 0, parentT
|
|||||||
width: nodeWidth,
|
width: nodeWidth,
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderTop: `5px solid ${accentColor}`,
|
borderTop: `5px solid ${accentColor}`,
|
||||||
borderRadius: 18,
|
borderRadius: 14,
|
||||||
background: isRoot
|
background: isRoot
|
||||||
? 'linear-gradient(180deg, #fff, rgba(0,164,183,0.09))'
|
? 'linear-gradient(180deg, #fff, rgba(0,164,183,0.09))'
|
||||||
: isAgent
|
: isAgent
|
||||||
@ -220,7 +220,7 @@ function FlowNode({ node, areasById, onAdd, onEdit, onDelete, level = 0, parentT
|
|||||||
style={{
|
style={{
|
||||||
width: 34,
|
width: 34,
|
||||||
height: 34,
|
height: 34,
|
||||||
borderRadius: 12,
|
borderRadius: 9,
|
||||||
border: 'none',
|
border: 'none',
|
||||||
background: 'var(--color-highlight)',
|
background: 'var(--color-highlight)',
|
||||||
color: '#132534',
|
color: '#132534',
|
||||||
@ -414,7 +414,7 @@ function NodeModal({ mode, node, parent, areas, draft, onDraftChange, onClose, o
|
|||||||
width: 'min(760px, calc(100vw - 2rem))',
|
width: 'min(760px, calc(100vw - 2rem))',
|
||||||
maxHeight: 'calc(100vh - 2rem)',
|
maxHeight: 'calc(100vh - 2rem)',
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
borderRadius: 24,
|
borderRadius: 18,
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
boxShadow: 'var(--shadow-lg)',
|
boxShadow: 'var(--shadow-lg)',
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
@ -447,7 +447,7 @@ function NodeModal({ mode, node, parent, areas, draft, onDraftChange, onClose, o
|
|||||||
onClick={() => change('nodeType', type)}
|
onClick={() => change('nodeType', type)}
|
||||||
style={{
|
style={{
|
||||||
border: `1px solid ${draft.nodeType === type ? 'var(--color-primary)' : 'var(--color-border)'}`,
|
border: `1px solid ${draft.nodeType === type ? 'var(--color-primary)' : 'var(--color-border)'}`,
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.9rem',
|
padding: '0.9rem',
|
||||||
background: draft.nodeType === type ? 'rgba(0,164,183,0.08)' : '#fff',
|
background: draft.nodeType === type ? 'rgba(0,164,183,0.08)' : '#fff',
|
||||||
color: 'var(--color-text)',
|
color: 'var(--color-text)',
|
||||||
@ -743,7 +743,7 @@ export function KnowledgeBasePanel({ areas, mode = 'admin', isMobile = false })
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid rgba(241,184,42,0.45)',
|
border: '1px solid rgba(241,184,42,0.45)',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
background: 'rgba(241,184,42,0.12)',
|
background: 'rgba(241,184,42,0.12)',
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
color: 'var(--color-text)',
|
color: 'var(--color-text)',
|
||||||
@ -763,7 +763,7 @@ export function KnowledgeBasePanel({ areas, mode = 'admin', isMobile = false })
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 22,
|
borderRadius: 16,
|
||||||
background:
|
background:
|
||||||
'linear-gradient(180deg, #fff, rgba(0,49,80,0.03)), radial-gradient(circle at 1px 1px, rgba(0,49,80,0.08) 1px, transparent 0)',
|
'linear-gradient(180deg, #fff, rgba(0,49,80,0.03)), radial-gradient(circle at 1px 1px, rgba(0,49,80,0.08) 1px, transparent 0)',
|
||||||
backgroundSize: 'auto, 22px 22px',
|
backgroundSize: 'auto, 22px 22px',
|
||||||
@ -800,7 +800,7 @@ export function KnowledgeBasePanel({ areas, mode = 'admin', isMobile = false })
|
|||||||
{status ? (
|
{status ? (
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.75rem 0.85rem',
|
padding: '0.75rem 0.85rem',
|
||||||
background:
|
background:
|
||||||
statusTone === 'error'
|
statusTone === 'error'
|
||||||
@ -828,7 +828,7 @@ export function KnowledgeBasePanel({ areas, mode = 'admin', isMobile = false })
|
|||||||
key={version.id}
|
key={version.id}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.75rem 0.85rem',
|
padding: '0.75rem 0.85rem',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
|
|||||||
@ -64,45 +64,52 @@ export function ManagementLayout({
|
|||||||
<main style={{ minHeight: '100vh', padding: '1.5rem' }}>
|
<main style={{ minHeight: '100vh', padding: '1.5rem' }}>
|
||||||
<section
|
<section
|
||||||
style={{
|
style={{
|
||||||
width: 'min(1680px, calc(100vw - 3rem))',
|
width: 'min(1600px, calc(100vw - 3rem))',
|
||||||
margin: '0 auto',
|
margin: '0 auto',
|
||||||
background: 'var(--color-surface-strong)',
|
background: 'var(--color-surface-strong)',
|
||||||
borderRadius: '32px',
|
borderRadius: '24px',
|
||||||
boxShadow: 'var(--shadow-lg)',
|
boxShadow: 'var(--shadow-lg)',
|
||||||
padding: '1.5rem',
|
padding: '1.5rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gap: '1.5rem',
|
gap: '1.5rem',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{/* Grid plano de 4 zonas: col1=sidebar(270px) col2=conteúdo(1fr), row1=topo row2=corpo */}
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateColumns: isDesktop ? 'minmax(300px, 360px) minmax(0, 1fr)' : '1fr',
|
gridTemplateColumns: isDesktop ? '270px 1fr' : '1fr',
|
||||||
gap: '1.5rem',
|
columnGap: '1.5rem',
|
||||||
alignItems: 'start',
|
rowGap: '1.25rem',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: 'grid', gap: '1.25rem' }}>
|
{/* Zona 1 — BrandMark card: col1 row1 */}
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
padding: '1.5rem',
|
padding: '0.85rem 1rem',
|
||||||
|
overflow: 'hidden',
|
||||||
|
minWidth: 0,
|
||||||
|
...(isDesktop ? { gridColumn: 1, gridRow: 1 } : {}),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<BrandMark size="lg" />
|
<BrandMark size="md" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Zona 2 — Aside/menu: col1 row2 */}
|
||||||
<aside
|
<aside
|
||||||
style={{
|
style={{
|
||||||
background: 'linear-gradient(180deg, rgba(0, 49, 80, 0.98), rgba(7, 64, 98, 0.96))',
|
background: 'linear-gradient(180deg, rgba(0, 49, 80, 0.98), rgba(7, 64, 98, 0.96))',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
borderRadius: '28px',
|
borderRadius: '20px',
|
||||||
padding: '1.5rem',
|
padding: '1.5rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gap: '1.25rem',
|
gap: '1.25rem',
|
||||||
alignContent: 'start',
|
alignContent: 'start',
|
||||||
|
alignSelf: 'start',
|
||||||
|
...(isDesktop ? { gridColumn: 1, gridRow: 2 } : {}),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
@ -117,7 +124,7 @@ export function ManagementLayout({
|
|||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '20px',
|
borderRadius: '15px',
|
||||||
padding: '1rem 1.15rem',
|
padding: '1rem 1.15rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-highlight), #f3b94d)',
|
background: 'linear-gradient(135deg, var(--color-highlight), #f3b94d)',
|
||||||
color: '#132534',
|
color: '#132534',
|
||||||
@ -164,7 +171,7 @@ export function ManagementLayout({
|
|||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.9rem 1rem',
|
padding: '0.9rem 1rem',
|
||||||
background: isActive ? 'rgba(255, 255, 255, 0.14)' : 'transparent',
|
background: isActive ? 'rgba(255, 255, 255, 0.14)' : 'transparent',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -201,7 +208,7 @@ export function ManagementLayout({
|
|||||||
onClick={handleLogout}
|
onClick={handleLogout}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid rgba(255, 255, 255, 0.18)',
|
border: '1px solid rgba(255, 255, 255, 0.18)',
|
||||||
borderRadius: '18px',
|
borderRadius: '14px',
|
||||||
padding: '0.9rem 1rem',
|
padding: '0.9rem 1rem',
|
||||||
background: 'transparent',
|
background: 'transparent',
|
||||||
color: '#ef4444',
|
color: '#ef4444',
|
||||||
@ -212,28 +219,31 @@ export function ManagementLayout({
|
|||||||
Sair
|
Sair
|
||||||
</button>
|
</button>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ display: 'grid', gap: '1.25rem', minWidth: 0 }}>
|
{/* Zona 3 — Header: col2 row1 — mesma linha do BrandMark card */}
|
||||||
<header
|
<header
|
||||||
style={{
|
style={{
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateColumns: isMobile ? '1fr' : 'minmax(0, 1fr) auto',
|
gridTemplateColumns: isMobile ? '1fr' : 'minmax(0, 1fr) auto',
|
||||||
gap: '1rem',
|
gap: '1rem',
|
||||||
alignItems: 'center',
|
alignItems: 'stretch',
|
||||||
|
...(isDesktop ? { gridColumn: 2, gridRow: 1 } : {}),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
padding: '1.1rem 1.25rem',
|
padding: '0.75rem 1.1rem',
|
||||||
borderRadius: '22px',
|
borderRadius: '16px',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
minWidth: 0,
|
minWidth: 0,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'center',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<h1 style={{ margin: 0, fontSize: '1.65rem' }}>{title}</h1>
|
<h1 style={{ margin: 0, fontSize: '1.4rem' }}>{title}</h1>
|
||||||
<p style={{ margin: '0.45rem 0 0', color: 'var(--color-text-soft)' }}>
|
<p style={{ margin: '0.3rem 0 0', color: 'var(--color-text-soft)' }}>
|
||||||
{subtitle}
|
{subtitle}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -245,8 +255,8 @@ export function ManagementLayout({
|
|||||||
gap: '0.9rem',
|
gap: '0.9rem',
|
||||||
justifySelf: isMobile ? 'stretch' : 'end',
|
justifySelf: isMobile ? 'stretch' : 'end',
|
||||||
justifyContent: isMobile ? 'space-between' : 'flex-end',
|
justifyContent: isMobile ? 'space-between' : 'flex-end',
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.6rem 0.85rem',
|
||||||
borderRadius: '22px',
|
borderRadius: '16px',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
}}
|
}}
|
||||||
@ -260,9 +270,9 @@ export function ManagementLayout({
|
|||||||
<div
|
<div
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
style={{
|
style={{
|
||||||
width: 48,
|
width: 40,
|
||||||
height: 48,
|
height: 40,
|
||||||
borderRadius: '16px',
|
borderRadius: '10px',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
placeItems: 'center',
|
placeItems: 'center',
|
||||||
background: 'linear-gradient(135deg, var(--color-accent), var(--color-primary))',
|
background: 'linear-gradient(135deg, var(--color-accent), var(--color-primary))',
|
||||||
@ -275,6 +285,16 @@ export function ManagementLayout({
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
{/* Zona 4 — Conteúdo: col2 row2 */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'grid',
|
||||||
|
gap: '1.25rem',
|
||||||
|
alignContent: 'start',
|
||||||
|
minWidth: 0,
|
||||||
|
...(isDesktop ? { gridColumn: 2, gridRow: 2 } : {}),
|
||||||
|
}}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -23,7 +23,7 @@ export function ManagementTable({ columns, rows, getRowId, isMobile = false }) {
|
|||||||
<article
|
<article
|
||||||
key={getRowId(row)}
|
key={getRowId(row)}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '20px',
|
borderRadius: '15px',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { listTemplates } from '../services/templateService';
|
|||||||
const inputStyle = {
|
const inputStyle = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.85rem 0.9rem',
|
padding: '0.85rem 0.9rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text)',
|
color: 'var(--color-text)',
|
||||||
@ -347,7 +347,7 @@ export function MassMessagePanel({
|
|||||||
disabled={isSending}
|
disabled={isSending}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.95rem 1rem',
|
padding: '0.95rem 1rem',
|
||||||
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -365,7 +365,7 @@ export function MassMessagePanel({
|
|||||||
<article
|
<article
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 18,
|
borderRadius: 14,
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -395,7 +395,7 @@ export function MassMessagePanel({
|
|||||||
style={{
|
style={{
|
||||||
border: '1px solid',
|
border: '1px solid',
|
||||||
borderColor: isSelected ? 'rgba(0, 164, 183, 0.36)' : 'var(--color-border)',
|
borderColor: isSelected ? 'rgba(0, 164, 183, 0.36)' : 'var(--color-border)',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.7rem',
|
padding: '0.7rem',
|
||||||
background: isSelected ? 'rgba(0, 164, 183, 0.08)' : '#fff',
|
background: isSelected ? 'rgba(0, 164, 183, 0.08)' : '#fff',
|
||||||
textAlign: 'left',
|
textAlign: 'left',
|
||||||
@ -422,7 +422,7 @@ export function MassMessagePanel({
|
|||||||
onClick={clearSelectedContacts}
|
onClick={clearSelectedContacts}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.75rem',
|
padding: '0.75rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
@ -437,7 +437,7 @@ export function MassMessagePanel({
|
|||||||
<article
|
<article
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid rgba(0, 164, 183, 0.24)',
|
border: '1px solid rgba(0, 164, 183, 0.24)',
|
||||||
borderRadius: 18,
|
borderRadius: 14,
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: 'rgba(0, 164, 183, 0.06)',
|
background: 'rgba(0, 164, 183, 0.06)',
|
||||||
lineHeight: 1.5,
|
lineHeight: 1.5,
|
||||||
@ -454,7 +454,7 @@ export function MassMessagePanel({
|
|||||||
<article
|
<article
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 18,
|
borderRadius: 14,
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text-soft)',
|
color: 'var(--color-text-soft)',
|
||||||
@ -470,7 +470,7 @@ export function MassMessagePanel({
|
|||||||
key={`${result.number}-${result.status}`}
|
key={`${result.number}-${result.status}`}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.75rem',
|
padding: '0.75rem',
|
||||||
background: result.status === 'enviado' ? 'rgba(16,185,129,0.08)' : 'rgba(181,31,31,0.08)',
|
background: result.status === 'enviado' ? 'rgba(16,185,129,0.08)' : 'rgba(181,31,31,0.08)',
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export function MetricGrid({ metrics, minCardWidth = '180px' }) {
|
|||||||
key={item.label}
|
key={item.label}
|
||||||
style={{
|
style={{
|
||||||
padding: '1.15rem',
|
padding: '1.15rem',
|
||||||
borderRadius: '22px',
|
borderRadius: '16px',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { MetricGrid } from './MetricGrid';
|
|||||||
const selectStyle = {
|
const selectStyle = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
padding: '0.75rem 0.85rem',
|
padding: '0.75rem 0.85rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text)',
|
color: 'var(--color-text)',
|
||||||
@ -237,7 +237,7 @@ export function OperationalDashboard({ isDesktop, isMobile }) {
|
|||||||
key={item.id}
|
key={item.id}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.8rem',
|
padding: '0.8rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -258,7 +258,7 @@ export function OperationalDashboard({ isDesktop, isMobile }) {
|
|||||||
onClick={() => setAssignmentTarget(item)}
|
onClick={() => setAssignmentTarget(item)}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 12,
|
borderRadius: 9,
|
||||||
padding: '0.65rem 0.8rem',
|
padding: '0.65rem 0.8rem',
|
||||||
background: 'var(--color-primary)',
|
background: 'var(--color-primary)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -291,7 +291,7 @@ export function OperationalDashboard({ isDesktop, isMobile }) {
|
|||||||
zIndex: 20,
|
zIndex: 20,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ width: 'min(460px, 100%)', background: '#fff', borderRadius: 22, padding: '1.25rem', boxShadow: 'var(--shadow-lg)', display: 'grid', gap: '1rem' }}>
|
<div style={{ width: 'min(460px, 100%)', background: '#fff', borderRadius: 16, padding: '1.25rem', boxShadow: 'var(--shadow-lg)', display: 'grid', gap: '1rem' }}>
|
||||||
<div>
|
<div>
|
||||||
<h2 style={{ margin: 0, fontSize: '1.2rem' }}>Atribuir atendimento</h2>
|
<h2 style={{ margin: 0, fontSize: '1.2rem' }}>Atribuir atendimento</h2>
|
||||||
<p style={{ margin: '0.35rem 0 0', color: 'var(--color-text-soft)' }}>
|
<p style={{ margin: '0.35rem 0 0', color: 'var(--color-text-soft)' }}>
|
||||||
@ -306,7 +306,7 @@ export function OperationalDashboard({ isDesktop, isMobile }) {
|
|||||||
onClick={() => setAssignmentTarget(null)}
|
onClick={() => setAssignmentTarget(null)}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.8rem 0.9rem',
|
padding: '0.8rem 0.9rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text)',
|
color: 'var(--color-text)',
|
||||||
@ -325,7 +325,7 @@ export function OperationalDashboard({ isDesktop, isMobile }) {
|
|||||||
onClick={() => setAssignmentTarget(null)}
|
onClick={() => setAssignmentTarget(null)}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.8rem 1rem',
|
padding: '0.8rem 1rem',
|
||||||
background: 'rgba(0, 49, 80, 0.08)',
|
background: 'rgba(0, 49, 80, 0.08)',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
403
src/modules/management/components/WhatsappConfigModal.jsx
Normal file
403
src/modules/management/components/WhatsappConfigModal.jsx
Normal file
@ -0,0 +1,403 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import {
|
||||||
|
getWhatsappConfig,
|
||||||
|
saveWhatsappConfig,
|
||||||
|
} from '../services/whatsappConfigService';
|
||||||
|
|
||||||
|
const fieldStyle = {
|
||||||
|
width: '100%',
|
||||||
|
border: '1px solid var(--color-border)',
|
||||||
|
borderRadius: 9,
|
||||||
|
padding: '0.7rem 0.85rem',
|
||||||
|
background: '#fff',
|
||||||
|
color: 'var(--color-text)',
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: '0.92rem',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
};
|
||||||
|
|
||||||
|
const labelStyle = {
|
||||||
|
display: 'block',
|
||||||
|
fontSize: '0.8rem',
|
||||||
|
fontWeight: 800,
|
||||||
|
color: 'var(--color-text-soft)',
|
||||||
|
marginBottom: '0.35rem',
|
||||||
|
letterSpacing: '0.03em',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
};
|
||||||
|
|
||||||
|
export function WhatsappConfigModal({ onClose }) {
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [currentConfig, setCurrentConfig] = useState(null);
|
||||||
|
const [saving, setSaving] = useState(false);
|
||||||
|
const [validating, setValidating] = useState(false);
|
||||||
|
const [validation, setValidation] = useState(null);
|
||||||
|
const [saveSuccess, setSaveSuccess] = useState(false);
|
||||||
|
const [error, setError] = useState('');
|
||||||
|
|
||||||
|
const [form, setForm] = useState({
|
||||||
|
access_token: '',
|
||||||
|
phone_number_id: '',
|
||||||
|
api_version: 'v25.0',
|
||||||
|
webhook_token: '',
|
||||||
|
waba_id: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getWhatsappConfig()
|
||||||
|
.then((data) => {
|
||||||
|
setCurrentConfig(data);
|
||||||
|
setForm((f) => ({
|
||||||
|
...f,
|
||||||
|
phone_number_id: data.phone_number_id || '',
|
||||||
|
api_version: data.api_version || 'v25.0',
|
||||||
|
webhook_token: data.webhook_token || '',
|
||||||
|
waba_id: data.waba_id || '',
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
.catch(() => setError('Não foi possível carregar a configuração atual.'))
|
||||||
|
.finally(() => setLoading(false));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function handleChange(field, value) {
|
||||||
|
setValidation(null);
|
||||||
|
setSaveSuccess(false);
|
||||||
|
setError('');
|
||||||
|
setForm((f) => ({ ...f, [field]: value }));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleValidate() {
|
||||||
|
if (!form.access_token || !form.phone_number_id) return;
|
||||||
|
setValidating(true);
|
||||||
|
setValidation(null);
|
||||||
|
const apiVersion = form.api_version || 'v25.0';
|
||||||
|
const url =
|
||||||
|
`https://graph.facebook.com/${apiVersion}/${form.phone_number_id}` +
|
||||||
|
`?access_token=${encodeURIComponent(form.access_token)}&fields=display_phone_number,verified_name,quality_rating`;
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
const data = await response.json();
|
||||||
|
if (!response.ok) {
|
||||||
|
setValidation({
|
||||||
|
valid: false,
|
||||||
|
error: data?.error?.message || 'Credenciais inválidas',
|
||||||
|
code: data?.error?.code,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setValidation({
|
||||||
|
valid: true,
|
||||||
|
phone_number: data.display_phone_number,
|
||||||
|
verified_name: data.verified_name,
|
||||||
|
quality_rating: data.quality_rating,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
setValidation({ valid: false, error: 'Sem acesso à internet para validar' });
|
||||||
|
} finally {
|
||||||
|
setValidating(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleSave() {
|
||||||
|
setSaving(true);
|
||||||
|
setSaveSuccess(false);
|
||||||
|
setError('');
|
||||||
|
try {
|
||||||
|
await saveWhatsappConfig(form);
|
||||||
|
setSaveSuccess(true);
|
||||||
|
setTimeout(onClose, 1200);
|
||||||
|
} catch (err) {
|
||||||
|
const msg = err?.message || '';
|
||||||
|
setError(`Erro ao salvar${msg ? `: ${msg}` : '. Verifique se a migration 025 foi executada no banco.'}`);
|
||||||
|
} finally {
|
||||||
|
setSaving(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const canValidate = !!(form.access_token && form.phone_number_id);
|
||||||
|
const canSave = !!(form.access_token || form.phone_number_id) && !saving;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="wa-config-title"
|
||||||
|
style={{
|
||||||
|
position: 'fixed',
|
||||||
|
inset: 0,
|
||||||
|
background: 'rgba(0, 20, 32, 0.42)',
|
||||||
|
display: 'grid',
|
||||||
|
placeItems: 'center',
|
||||||
|
padding: '1rem',
|
||||||
|
zIndex: 50,
|
||||||
|
}}
|
||||||
|
onClick={onClose}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
style={{
|
||||||
|
width: 'min(540px, 100%)',
|
||||||
|
borderRadius: 16,
|
||||||
|
border: '1px solid var(--color-border)',
|
||||||
|
background: '#fff',
|
||||||
|
padding: '1.4rem',
|
||||||
|
display: 'grid',
|
||||||
|
gap: '1rem',
|
||||||
|
boxShadow: 'var(--shadow-lg)',
|
||||||
|
maxHeight: '90vh',
|
||||||
|
overflowY: 'auto',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Header */}
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '0.85rem' }}>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
style={{
|
||||||
|
width: 46,
|
||||||
|
height: 46,
|
||||||
|
borderRadius: 10,
|
||||||
|
display: 'grid',
|
||||||
|
placeItems: 'center',
|
||||||
|
background: '#20a45b',
|
||||||
|
color: '#fff',
|
||||||
|
fontWeight: 900,
|
||||||
|
fontSize: '1rem',
|
||||||
|
flexShrink: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
WA
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong id="wa-config-title" style={{ display: 'block', fontSize: '1.05rem' }}>
|
||||||
|
Configurar WhatsApp
|
||||||
|
</strong>
|
||||||
|
<span style={{ color: 'var(--color-text-soft)', fontWeight: 700, fontSize: '0.88rem' }}>
|
||||||
|
Meta Cloud API
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
aria-label="Fechar"
|
||||||
|
onClick={onClose}
|
||||||
|
style={{
|
||||||
|
marginLeft: 'auto',
|
||||||
|
border: 'none',
|
||||||
|
background: 'none',
|
||||||
|
fontSize: '1.3rem',
|
||||||
|
cursor: 'pointer',
|
||||||
|
color: 'var(--color-text-soft)',
|
||||||
|
lineHeight: 1,
|
||||||
|
padding: '0.2rem 0.4rem',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Status atual */}
|
||||||
|
{!loading && currentConfig && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
borderRadius: 9,
|
||||||
|
padding: '0.7rem 0.9rem',
|
||||||
|
background: currentConfig.is_configured ? '#f0faf4' : '#fff8f0',
|
||||||
|
border: `1px solid ${currentConfig.is_configured ? '#b6e8c8' : '#f5d9a8'}`,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: '0.6rem',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span style={{ fontSize: '1.1rem' }}>{currentConfig.is_configured ? '✅' : '⚠️'}</span>
|
||||||
|
<div>
|
||||||
|
<strong style={{ fontSize: '0.88rem', color: currentConfig.is_configured ? '#1a7a44' : '#a05a00' }}>
|
||||||
|
{currentConfig.is_configured ? 'Integração configurada' : 'Configuração incompleta'}
|
||||||
|
</strong>
|
||||||
|
{currentConfig.is_configured && (
|
||||||
|
<span style={{ display: 'block', fontSize: '0.8rem', color: 'var(--color-text-soft)', fontWeight: 600 }}>
|
||||||
|
Token via {currentConfig.token_source === 'database' ? 'banco de dados' : 'variável de ambiente'}
|
||||||
|
{currentConfig.phone_number_id ? ` · ID: ${currentConfig.phone_number_id}` : ''}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{!currentConfig.is_configured && (
|
||||||
|
<span style={{ display: 'block', fontSize: '0.8rem', color: 'var(--color-text-soft)', fontWeight: 600 }}>
|
||||||
|
Preencha o Token e o Phone Number ID abaixo
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{loading && (
|
||||||
|
<p style={{ margin: 0, color: 'var(--color-text-soft)', fontWeight: 700, fontSize: '0.9rem' }}>
|
||||||
|
Carregando configuração atual…
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Formulário */}
|
||||||
|
<div style={{ display: 'grid', gap: '0.75rem' }}>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="wa-token" style={labelStyle}>
|
||||||
|
Access Token{currentConfig?.has_token ? ' (deixe vazio para manter o atual)' : ''}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="wa-token"
|
||||||
|
type="password"
|
||||||
|
autoComplete="off"
|
||||||
|
placeholder={currentConfig?.has_token ? '•••••••• (configurado)' : 'EAAxxxxxxx...'}
|
||||||
|
value={form.access_token}
|
||||||
|
onChange={(e) => handleChange('access_token', e.target.value)}
|
||||||
|
style={fieldStyle}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label htmlFor="wa-phone-id" style={labelStyle}>
|
||||||
|
Phone Number ID
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="wa-phone-id"
|
||||||
|
type="text"
|
||||||
|
placeholder="ex: 123456789012345"
|
||||||
|
value={form.phone_number_id}
|
||||||
|
onChange={(e) => handleChange('phone_number_id', e.target.value)}
|
||||||
|
style={fieldStyle}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label htmlFor="wa-waba-id" style={labelStyle}>
|
||||||
|
WABA ID (WhatsApp Business Account ID)
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="wa-waba-id"
|
||||||
|
type="text"
|
||||||
|
placeholder="ex: 123456789012345"
|
||||||
|
value={form.waba_id}
|
||||||
|
onChange={(e) => handleChange('waba_id', e.target.value)}
|
||||||
|
style={fieldStyle}
|
||||||
|
/>
|
||||||
|
<p style={{ margin: '0.2rem 0 0', fontSize: '0.75rem', color: 'var(--color-text-soft)', fontWeight: 600 }}>
|
||||||
|
Necessário para criar e sincronizar templates HSM.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0.65rem' }}>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="wa-api-version" style={labelStyle}>
|
||||||
|
Versão da API
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="wa-api-version"
|
||||||
|
type="text"
|
||||||
|
placeholder="v25.0"
|
||||||
|
value={form.api_version}
|
||||||
|
onChange={(e) => handleChange('api_version', e.target.value)}
|
||||||
|
style={fieldStyle}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="wa-webhook-token" style={labelStyle}>
|
||||||
|
Webhook Verify Token
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="wa-webhook-token"
|
||||||
|
type="text"
|
||||||
|
placeholder="token de verificação"
|
||||||
|
value={form.webhook_token}
|
||||||
|
onChange={(e) => handleChange('webhook_token', e.target.value)}
|
||||||
|
style={fieldStyle}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Resultado da validação */}
|
||||||
|
{validation && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
borderRadius: 9,
|
||||||
|
padding: '0.7rem 0.9rem',
|
||||||
|
background: validation.valid ? '#f0faf4' : '#fff2f2',
|
||||||
|
border: `1px solid ${validation.valid ? '#b6e8c8' : '#f5c6c6'}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{validation.valid ? (
|
||||||
|
<>
|
||||||
|
<strong style={{ color: '#1a7a44', fontSize: '0.88rem' }}>
|
||||||
|
✅ Credenciais válidas
|
||||||
|
</strong>
|
||||||
|
<span style={{ display: 'block', color: 'var(--color-text-soft)', fontSize: '0.82rem', fontWeight: 600, marginTop: '0.2rem' }}>
|
||||||
|
{validation.verified_name && `Conta: ${validation.verified_name}`}
|
||||||
|
{validation.phone_number && ` · ${validation.phone_number}`}
|
||||||
|
{validation.quality_rating && ` · Qualidade: ${validation.quality_rating}`}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<strong style={{ color: '#b00020', fontSize: '0.88rem' }}>
|
||||||
|
❌ Credenciais inválidas
|
||||||
|
</strong>
|
||||||
|
<span style={{ display: 'block', color: 'var(--color-text-soft)', fontSize: '0.82rem', fontWeight: 600, marginTop: '0.2rem' }}>
|
||||||
|
{validation.error || 'Verifique o Token e o Phone Number ID'}
|
||||||
|
{validation.code ? ` (código ${validation.code})` : ''}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Feedback de erro geral */}
|
||||||
|
{error && (
|
||||||
|
<p style={{ margin: 0, color: '#b00020', fontWeight: 700, fontSize: '0.88rem' }}>
|
||||||
|
{error}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Feedback de sucesso */}
|
||||||
|
{saveSuccess && (
|
||||||
|
<p style={{ margin: 0, color: '#1a7a44', fontWeight: 700, fontSize: '0.88rem' }}>
|
||||||
|
✅ Configuração salva com sucesso!
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Ações */}
|
||||||
|
<div style={{ display: 'flex', gap: '0.65rem', justifyContent: 'flex-end', flexWrap: 'wrap' }}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleValidate}
|
||||||
|
disabled={!canValidate || validating}
|
||||||
|
style={{
|
||||||
|
border: '1px solid #20a45b44',
|
||||||
|
borderRadius: 10,
|
||||||
|
padding: '0.65rem 0.9rem',
|
||||||
|
background: '#fff',
|
||||||
|
color: canValidate ? '#20a45b' : 'var(--color-text-soft)',
|
||||||
|
fontWeight: 800,
|
||||||
|
cursor: canValidate && !validating ? 'pointer' : 'not-allowed',
|
||||||
|
opacity: canValidate && !validating ? 1 : 0.6,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{validating ? 'Validando…' : 'Validar credenciais'}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleSave}
|
||||||
|
disabled={!canSave}
|
||||||
|
style={{
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: 10,
|
||||||
|
padding: '0.65rem 1rem',
|
||||||
|
background: canSave ? 'var(--color-primary)' : 'var(--color-border)',
|
||||||
|
color: '#fff',
|
||||||
|
fontWeight: 800,
|
||||||
|
cursor: canSave ? 'pointer' : 'not-allowed',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{saving ? 'Salvando…' : 'Salvar'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -31,11 +31,12 @@ import {
|
|||||||
} from '../services/adminAccessService';
|
} from '../services/adminAccessService';
|
||||||
import { useViewport } from '../../../shared/hooks/useViewport';
|
import { useViewport } from '../../../shared/hooks/useViewport';
|
||||||
import { getCurrentUserDisplay } from '../../auth/services/sessionService';
|
import { getCurrentUserDisplay } from '../../auth/services/sessionService';
|
||||||
|
import { WhatsappConfigModal } from '../components/WhatsappConfigModal';
|
||||||
|
|
||||||
const selectStyle = {
|
const selectStyle = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
padding: '0.75rem 0.85rem',
|
padding: '0.75rem 0.85rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text)',
|
color: 'var(--color-text)',
|
||||||
@ -44,7 +45,7 @@ const selectStyle = {
|
|||||||
|
|
||||||
const compactSelectStyle = {
|
const compactSelectStyle = {
|
||||||
...selectStyle,
|
...selectStyle,
|
||||||
borderRadius: '10px',
|
borderRadius: '8px',
|
||||||
padding: '0.45rem 0.55rem',
|
padding: '0.45rem 0.55rem',
|
||||||
fontSize: '0.82rem',
|
fontSize: '0.82rem',
|
||||||
};
|
};
|
||||||
@ -183,7 +184,7 @@ export function AdminAttendanceWorkspace({ isWideDesktop, isDesktop, isTablet, i
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 18,
|
borderRadius: 14,
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: 'var(--color-text-soft)',
|
color: 'var(--color-text-soft)',
|
||||||
@ -256,6 +257,7 @@ export function AdminPage() {
|
|||||||
const [authConfigModal, setAuthConfigModal] = useState(null);
|
const [authConfigModal, setAuthConfigModal] = useState(null);
|
||||||
const [integrationNotice, setIntegrationNotice] = useState('');
|
const [integrationNotice, setIntegrationNotice] = useState('');
|
||||||
const [configurationModal, setConfigurationModal] = useState(null);
|
const [configurationModal, setConfigurationModal] = useState(null);
|
||||||
|
const [whatsappConfigModal, setWhatsappConfigModal] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let isMounted = true;
|
let isMounted = true;
|
||||||
@ -658,7 +660,7 @@ export function AdminPage() {
|
|||||||
onClick={() => openUserEditor(row)}
|
onClick={() => openUserEditor(row)}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.7rem 0.9rem',
|
padding: '0.7rem 0.9rem',
|
||||||
background: 'var(--color-primary)',
|
background: 'var(--color-primary)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -721,7 +723,7 @@ export function AdminPage() {
|
|||||||
onClick={() => openAreaEditor(row)}
|
onClick={() => openAreaEditor(row)}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 12,
|
borderRadius: 9,
|
||||||
padding: '0.55rem 0.7rem',
|
padding: '0.55rem 0.7rem',
|
||||||
background: 'var(--color-primary)',
|
background: 'var(--color-primary)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -735,7 +737,7 @@ export function AdminPage() {
|
|||||||
onClick={() => handleDeleteArea(row)}
|
onClick={() => handleDeleteArea(row)}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 12,
|
borderRadius: 9,
|
||||||
padding: '0.55rem 0.7rem',
|
padding: '0.55rem 0.7rem',
|
||||||
background: 'rgba(181, 31, 31, 0.1)',
|
background: 'rgba(181, 31, 31, 0.1)',
|
||||||
color: 'var(--color-secondary)',
|
color: 'var(--color-secondary)',
|
||||||
@ -920,7 +922,7 @@ export function AdminPage() {
|
|||||||
<div style={{ display: 'grid', gridTemplateColumns: isDesktop ? 'minmax(0, 1fr) minmax(320px, 0.8fr)' : '1fr', gap: '1rem' }}>
|
<div style={{ display: 'grid', gridTemplateColumns: isDesktop ? 'minmax(0, 1fr) minmax(320px, 0.8fr)' : '1fr', gap: '1rem' }}>
|
||||||
<div style={{ display: 'grid', gap: '0.75rem' }}>
|
<div style={{ display: 'grid', gap: '0.75rem' }}>
|
||||||
{notices.map((notice) => (
|
{notices.map((notice) => (
|
||||||
<article key={notice.id} style={{ border: '1px solid var(--color-border)', borderRadius: 18, padding: '0.9rem 1rem', background: '#fff' }}>
|
<article key={notice.id} style={{ border: '1px solid var(--color-border)', borderRadius: 14, padding: '0.9rem 1rem', background: '#fff' }}>
|
||||||
{notice.text}
|
{notice.text}
|
||||||
</article>
|
</article>
|
||||||
))}
|
))}
|
||||||
@ -933,7 +935,7 @@ export function AdminPage() {
|
|||||||
placeholder="Digite um aviso para o time..."
|
placeholder="Digite um aviso para o time..."
|
||||||
style={{ ...selectStyle, resize: 'vertical', lineHeight: 1.45 }}
|
style={{ ...selectStyle, resize: 'vertical', lineHeight: 1.45 }}
|
||||||
/>
|
/>
|
||||||
<button type="button" onClick={sendNotice} style={{ border: 'none', borderRadius: 16, padding: '0.95rem 1rem', background: 'var(--color-primary)', color: '#fff', fontWeight: 800 }}>
|
<button type="button" onClick={sendNotice} style={{ border: 'none', borderRadius: 12, padding: '0.95rem 1rem', background: 'var(--color-primary)', color: '#fff', fontWeight: 800 }}>
|
||||||
Enviar aviso
|
Enviar aviso
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -992,7 +994,7 @@ export function AdminPage() {
|
|||||||
style={{
|
style={{
|
||||||
width: 'min(560px, 100%)',
|
width: 'min(560px, 100%)',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
borderRadius: 24,
|
borderRadius: 18,
|
||||||
boxShadow: 'var(--shadow-lg)',
|
boxShadow: 'var(--shadow-lg)',
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -1040,7 +1042,7 @@ export function AdminPage() {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.85rem',
|
padding: '0.85rem',
|
||||||
background: 'rgba(0, 164, 183, 0.08)',
|
background: 'rgba(0, 164, 183, 0.08)',
|
||||||
color: 'var(--color-primary)',
|
color: 'var(--color-primary)',
|
||||||
@ -1070,7 +1072,7 @@ export function AdminPage() {
|
|||||||
disabled={!specialtyToAdd}
|
disabled={!specialtyToAdd}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.75rem 0.95rem',
|
padding: '0.75rem 0.95rem',
|
||||||
background: specialtyToAdd ? 'var(--color-primary)' : 'rgba(0, 49, 80, 0.12)',
|
background: specialtyToAdd ? 'var(--color-primary)' : 'rgba(0, 49, 80, 0.12)',
|
||||||
color: specialtyToAdd ? '#fff' : 'var(--color-text-soft)',
|
color: specialtyToAdd ? '#fff' : 'var(--color-text-soft)',
|
||||||
@ -1087,7 +1089,7 @@ export function AdminPage() {
|
|||||||
key={specialty.id}
|
key={specialty.id}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.75rem',
|
padding: '0.75rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateColumns: isMobile ? '1fr' : 'minmax(0, 1fr) 140px auto',
|
gridTemplateColumns: isMobile ? '1fr' : 'minmax(0, 1fr) 140px auto',
|
||||||
@ -1109,7 +1111,7 @@ export function AdminPage() {
|
|||||||
onClick={() => removeSpecialtyFromEdit(specialty.id)}
|
onClick={() => removeSpecialtyFromEdit(specialty.id)}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 12,
|
borderRadius: 9,
|
||||||
padding: '0.55rem 0.7rem',
|
padding: '0.55rem 0.7rem',
|
||||||
background: 'rgba(181, 31, 31, 0.1)',
|
background: 'rgba(181, 31, 31, 0.1)',
|
||||||
color: 'var(--color-secondary)',
|
color: 'var(--color-secondary)',
|
||||||
@ -1133,7 +1135,7 @@ export function AdminPage() {
|
|||||||
onClick={submitUserEditor}
|
onClick={submitUserEditor}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.9rem 1rem',
|
padding: '0.9rem 1rem',
|
||||||
background: 'var(--color-primary)',
|
background: 'var(--color-primary)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -1163,7 +1165,7 @@ export function AdminPage() {
|
|||||||
onClick={handleCreateArea}
|
onClick={handleCreateArea}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '14px',
|
borderRadius: '10px',
|
||||||
padding: '0.75rem 0.95rem',
|
padding: '0.75rem 0.95rem',
|
||||||
background: 'var(--color-primary)',
|
background: 'var(--color-primary)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -1193,7 +1195,7 @@ export function AdminPage() {
|
|||||||
style={{
|
style={{
|
||||||
width: 'min(520px, 100%)',
|
width: 'min(520px, 100%)',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
borderRadius: 24,
|
borderRadius: 18,
|
||||||
boxShadow: 'var(--shadow-lg)',
|
boxShadow: 'var(--shadow-lg)',
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -1245,7 +1247,7 @@ export function AdminPage() {
|
|||||||
onClick={submitAreaEditor}
|
onClick={submitAreaEditor}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.9rem 1rem',
|
padding: '0.9rem 1rem',
|
||||||
background: 'var(--color-primary)',
|
background: 'var(--color-primary)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -1377,7 +1379,7 @@ export function AdminPage() {
|
|||||||
onClick={() => removeAiContent(row.id)}
|
onClick={() => removeAiContent(row.id)}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 12,
|
borderRadius: 9,
|
||||||
padding: '0.55rem 0.7rem',
|
padding: '0.55rem 0.7rem',
|
||||||
background: 'rgba(181, 31, 31, 0.1)',
|
background: 'rgba(181, 31, 31, 0.1)',
|
||||||
color: 'var(--color-secondary)',
|
color: 'var(--color-secondary)',
|
||||||
@ -1437,7 +1439,7 @@ export function AdminPage() {
|
|||||||
type="submit"
|
type="submit"
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.9rem 1rem',
|
padding: '0.9rem 1rem',
|
||||||
background: 'var(--color-primary)',
|
background: 'var(--color-primary)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -1468,7 +1470,7 @@ export function AdminPage() {
|
|||||||
type="submit"
|
type="submit"
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
background: 'var(--color-primary)',
|
background: 'var(--color-primary)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -1486,7 +1488,7 @@ export function AdminPage() {
|
|||||||
key={`${rule}-${index}`}
|
key={`${rule}-${index}`}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.85rem 0.9rem',
|
padding: '0.85rem 0.9rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -1503,7 +1505,7 @@ export function AdminPage() {
|
|||||||
onClick={() => setAiGuardrails((current) => current.filter((_, itemIndex) => itemIndex !== index))}
|
onClick={() => setAiGuardrails((current) => current.filter((_, itemIndex) => itemIndex !== index))}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 12,
|
borderRadius: 9,
|
||||||
padding: '0.45rem 0.65rem',
|
padding: '0.45rem 0.65rem',
|
||||||
background: 'rgba(181, 31, 31, 0.1)',
|
background: 'rgba(181, 31, 31, 0.1)',
|
||||||
color: 'var(--color-secondary)',
|
color: 'var(--color-secondary)',
|
||||||
@ -1563,7 +1565,7 @@ export function AdminPage() {
|
|||||||
key={item.label}
|
key={item.label}
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 18,
|
borderRadius: 14,
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: '#f8fbfc',
|
background: '#f8fbfc',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -1581,7 +1583,7 @@ export function AdminPage() {
|
|||||||
role="alert"
|
role="alert"
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid rgba(216, 137, 28, 0.32)',
|
border: '1px solid rgba(216, 137, 28, 0.32)',
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
padding: '0.85rem 1rem',
|
padding: '0.85rem 1rem',
|
||||||
background: 'rgba(216, 137, 28, 0.08)',
|
background: 'rgba(216, 137, 28, 0.08)',
|
||||||
color: '#7a4a08',
|
color: '#7a4a08',
|
||||||
@ -1608,7 +1610,7 @@ export function AdminPage() {
|
|||||||
key={item.id}
|
key={item.id}
|
||||||
style={{
|
style={{
|
||||||
border: `1px solid ${isEnabled ? `${item.color}55` : 'var(--color-border)'}`,
|
border: `1px solid ${isEnabled ? `${item.color}55` : 'var(--color-border)'}`,
|
||||||
borderRadius: 22,
|
borderRadius: 16,
|
||||||
padding: '1.1rem',
|
padding: '1.1rem',
|
||||||
background: isEnabled ? `${item.color}0f` : '#fff',
|
background: isEnabled ? `${item.color}0f` : '#fff',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -1623,7 +1625,7 @@ export function AdminPage() {
|
|||||||
style={{
|
style={{
|
||||||
width: 52,
|
width: 52,
|
||||||
height: 52,
|
height: 52,
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
placeItems: 'center',
|
placeItems: 'center',
|
||||||
background: item.color,
|
background: item.color,
|
||||||
@ -1709,7 +1711,7 @@ export function AdminPage() {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (item.id === 'whatsapp') {
|
if (item.id === 'whatsapp') {
|
||||||
navigate('/admin/whatsapp');
|
setWhatsappConfigModal(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1717,7 +1719,7 @@ export function AdminPage() {
|
|||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
border: `1px solid ${item.color}44`,
|
border: `1px solid ${item.color}44`,
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.65rem 0.8rem',
|
padding: '0.65rem 0.8rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: item.color,
|
color: item.color,
|
||||||
@ -1732,6 +1734,10 @@ export function AdminPage() {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{whatsappConfigModal && (
|
||||||
|
<WhatsappConfigModal onClose={() => setWhatsappConfigModal(false)} />
|
||||||
|
)}
|
||||||
|
|
||||||
{configurationModal ? (
|
{configurationModal ? (
|
||||||
<div
|
<div
|
||||||
role="dialog"
|
role="dialog"
|
||||||
@ -1752,7 +1758,7 @@ export function AdminPage() {
|
|||||||
onClick={(event) => event.stopPropagation()}
|
onClick={(event) => event.stopPropagation()}
|
||||||
style={{
|
style={{
|
||||||
width: 'min(460px, 100%)',
|
width: 'min(460px, 100%)',
|
||||||
borderRadius: 22,
|
borderRadius: 16,
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
@ -1767,7 +1773,7 @@ export function AdminPage() {
|
|||||||
style={{
|
style={{
|
||||||
width: 44,
|
width: 44,
|
||||||
height: 44,
|
height: 44,
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
placeItems: 'center',
|
placeItems: 'center',
|
||||||
background: configurationModal.color,
|
background: configurationModal.color,
|
||||||
@ -1797,7 +1803,7 @@ export function AdminPage() {
|
|||||||
onClick={() => setConfigurationModal(null)}
|
onClick={() => setConfigurationModal(null)}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.75rem 0.95rem',
|
padding: '0.75rem 0.95rem',
|
||||||
background: 'var(--color-primary)',
|
background: 'var(--color-primary)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -1817,7 +1823,7 @@ export function AdminPage() {
|
|||||||
function renderPlaceholder(title, description) {
|
function renderPlaceholder(title, description) {
|
||||||
return (
|
return (
|
||||||
<DataPanel title={title} description={description}>
|
<DataPanel title={title} description={description}>
|
||||||
<div style={{ border: '1px solid var(--color-border)', borderRadius: 18, padding: '1rem', background: '#fff', color: 'var(--color-text-soft)', fontWeight: 700 }}>
|
<div style={{ border: '1px solid var(--color-border)', borderRadius: 14, padding: '1rem', background: '#fff', color: 'var(--color-text-soft)', fontWeight: 700 }}>
|
||||||
Seção em preparação.
|
Seção em preparação.
|
||||||
</div>
|
</div>
|
||||||
</DataPanel>
|
</DataPanel>
|
||||||
@ -1843,7 +1849,7 @@ export function AdminPage() {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 18,
|
borderRadius: 14,
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: '#f8fbfc',
|
background: '#f8fbfc',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -1856,7 +1862,7 @@ export function AdminPage() {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
borderRadius: 18,
|
borderRadius: 14,
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
background: '#f8fbfc',
|
background: '#f8fbfc',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -1884,7 +1890,7 @@ export function AdminPage() {
|
|||||||
key={item.id}
|
key={item.id}
|
||||||
style={{
|
style={{
|
||||||
border: `1px solid ${isEnabled ? `${item.color}55` : 'var(--color-border)'}`,
|
border: `1px solid ${isEnabled ? `${item.color}55` : 'var(--color-border)'}`,
|
||||||
borderRadius: 22,
|
borderRadius: 16,
|
||||||
padding: '1.1rem',
|
padding: '1.1rem',
|
||||||
background: isEnabled ? `${item.color}0f` : '#fff',
|
background: isEnabled ? `${item.color}0f` : '#fff',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -1899,7 +1905,7 @@ export function AdminPage() {
|
|||||||
style={{
|
style={{
|
||||||
width: 52,
|
width: 52,
|
||||||
height: 52,
|
height: 52,
|
||||||
borderRadius: 16,
|
borderRadius: 12,
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
placeItems: 'center',
|
placeItems: 'center',
|
||||||
background: item.color,
|
background: item.color,
|
||||||
@ -1988,7 +1994,7 @@ export function AdminPage() {
|
|||||||
onClick={() => setAuthConfigModal(item)}
|
onClick={() => setAuthConfigModal(item)}
|
||||||
style={{
|
style={{
|
||||||
border: `1px solid ${item.color}44`,
|
border: `1px solid ${item.color}44`,
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.65rem 0.8rem',
|
padding: '0.65rem 0.8rem',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
color: item.color,
|
color: item.color,
|
||||||
@ -2023,7 +2029,7 @@ export function AdminPage() {
|
|||||||
onClick={(event) => event.stopPropagation()}
|
onClick={(event) => event.stopPropagation()}
|
||||||
style={{
|
style={{
|
||||||
width: 'min(460px, 100%)',
|
width: 'min(460px, 100%)',
|
||||||
borderRadius: 22,
|
borderRadius: 16,
|
||||||
border: '1px solid var(--color-border)',
|
border: '1px solid var(--color-border)',
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
padding: '1.25rem',
|
padding: '1.25rem',
|
||||||
@ -2044,7 +2050,7 @@ export function AdminPage() {
|
|||||||
onClick={() => setAuthConfigModal(null)}
|
onClick={() => setAuthConfigModal(null)}
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 14,
|
borderRadius: 10,
|
||||||
padding: '0.75rem 0.95rem',
|
padding: '0.75rem 0.95rem',
|
||||||
background: 'var(--color-primary)',
|
background: 'var(--color-primary)',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -2104,6 +2110,8 @@ export function AdminPage() {
|
|||||||
? 'Conteúdos da IA'
|
? 'Conteúdos da IA'
|
||||||
: activeAdminSection === 'knowledge'
|
: activeAdminSection === 'knowledge'
|
||||||
? 'Fluxo do Bot'
|
? 'Fluxo do Bot'
|
||||||
|
: activeAdminSection === 'templates'
|
||||||
|
? 'Templates HSM'
|
||||||
: 'Painel administrativo';
|
: 'Painel administrativo';
|
||||||
|
|
||||||
const pageSubtitle = activeAdminSection === 'home'
|
const pageSubtitle = activeAdminSection === 'home'
|
||||||
@ -2126,6 +2134,8 @@ export function AdminPage() {
|
|||||||
? 'Base de documentos que será consultada pela IA em fase de testes.'
|
? 'Base de documentos que será consultada pela IA em fase de testes.'
|
||||||
: activeAdminSection === 'knowledge'
|
: activeAdminSection === 'knowledge'
|
||||||
? 'Árvore de decisão configurável para roteamento do Agente Virtual Sothis.'
|
? 'Árvore de decisão configurável para roteamento do Agente Virtual Sothis.'
|
||||||
|
: activeAdminSection === 'templates'
|
||||||
|
? 'Modelos de mensagens predefinidas e aprovados pela Meta para iniciar conversas.'
|
||||||
: 'Controle operacional e configurações administrativas.';
|
: 'Controle operacional e configurações administrativas.';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -51,7 +51,7 @@ export function SupervisorPage() {
|
|||||||
function renderPlaceholder(title, description) {
|
function renderPlaceholder(title, description) {
|
||||||
return (
|
return (
|
||||||
<DataPanel title={title} description={description}>
|
<DataPanel title={title} description={description}>
|
||||||
<div style={{ border: '1px solid var(--color-border)', borderRadius: 18, padding: '1rem', background: '#fff', color: 'var(--color-text-soft)', fontWeight: 700 }}>
|
<div style={{ border: '1px solid var(--color-border)', borderRadius: 14, padding: '1rem', background: '#fff', color: 'var(--color-text-soft)', fontWeight: 700 }}>
|
||||||
Secao em preparacao.
|
Secao em preparacao.
|
||||||
</div>
|
</div>
|
||||||
</DataPanel>
|
</DataPanel>
|
||||||
|
|||||||
@ -25,14 +25,14 @@ export function updateTemplate(id, payload) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function approveTemplateByAdmin(id) {
|
export function submitTemplateToMeta(id) {
|
||||||
return request(`/whatsapp/templates/approve-admin/${id}`, {
|
return request(`/whatsapp/templates/${id}/submit-meta`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function rejectTemplateByAdmin(id) {
|
export function syncTemplatesFromMeta() {
|
||||||
return request(`/whatsapp/templates/reject-admin/${id}`, {
|
return request('/whatsapp/templates/sync-meta', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
30
src/modules/management/services/whatsappConfigService.js
Normal file
30
src/modules/management/services/whatsappConfigService.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { apiRequest } from '../../../shared/services/apiClient';
|
||||||
|
|
||||||
|
export async function getWhatsappConfig() {
|
||||||
|
return apiRequest('/admin/whatsapp-config', {
|
||||||
|
fallbackMessage: 'Falha ao carregar configuração do WhatsApp',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function saveWhatsappConfig(fields) {
|
||||||
|
const body = {};
|
||||||
|
if (fields.access_token) body.access_token = fields.access_token;
|
||||||
|
if (fields.phone_number_id) body.phone_number_id = fields.phone_number_id;
|
||||||
|
if (fields.api_version) body.api_version = fields.api_version;
|
||||||
|
if (fields.webhook_token) body.webhook_token = fields.webhook_token;
|
||||||
|
if (fields.waba_id) body.waba_id = fields.waba_id;
|
||||||
|
|
||||||
|
return apiRequest('/admin/whatsapp-config', {
|
||||||
|
method: 'PUT',
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
fallbackMessage: 'Falha ao salvar configuração do WhatsApp',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function validateWhatsappConfig({ access_token, phone_number_id, api_version }) {
|
||||||
|
return apiRequest('/admin/whatsapp-config/validate', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ access_token, phone_number_id, api_version }),
|
||||||
|
fallbackMessage: 'Falha ao validar credenciais',
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user