fix(responsive): layout 100% width en todas las resoluciones
- Eliminado max-w-[1280px] de todas las apps (mi-dia, landing, cotizador, cobranza, dashboards, alta-clientes) - Kanban: sin restricción de ancho, columnas min-w-[220px] - Grids: xl:grid-cols-4/5 para pantallas grandes - CSS base: -webkit-text-size-adjust + min-h-screen - 6 apps construidas
This commit is contained in:
@@ -10,7 +10,7 @@ interface Props {
|
||||
export default function AppHeader({ titulo, acciones }: Props) {
|
||||
return (
|
||||
<header className="sticky top-0 z-10 border-b border-[#E5E7EB] bg-white/95 backdrop-blur dark:border-[#1E293B] dark:bg-[#1E293B]/95">
|
||||
<div className="mx-auto flex min-h-14 max-w-[1280px] flex-wrap items-center gap-x-3 gap-y-2 px-4 py-2 sm:px-6">
|
||||
<div className="flex min-h-14 flex-wrap items-center gap-x-3 gap-y-2 px-4 py-2 sm:px-6 lg:px-8">
|
||||
<a
|
||||
href="/"
|
||||
className="rounded-lg px-2 py-1.5 text-xs font-medium text-[#64748B] dark:text-[#94A3B8] transition-all duration-100 ease-out hover:bg-[#F9FAFB] hover:text-[#111827] dark:text-[#E2E8F0]"
|
||||
|
||||
@@ -9,8 +9,11 @@
|
||||
}
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
body {
|
||||
@apply bg-[#F8FAFC] text-[#111827] antialiased;
|
||||
@apply min-h-screen bg-[#F8FAFC] text-[#111827] antialiased;
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
|
||||
@@ -338,7 +338,7 @@ export default function AltaClientePage() {
|
||||
if (pantalla === 'cargando') {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#F8FAFC] dark:bg-[#0F172A]">
|
||||
<main className="mx-auto max-w-[1280px] px-4 py-16 sm:px-6">
|
||||
<main className="px-4 py-16 sm:px-6 lg:px-8">
|
||||
<SkeletonCard />
|
||||
</main>
|
||||
</div>
|
||||
@@ -350,7 +350,7 @@ export default function AltaClientePage() {
|
||||
<div className="min-h-screen bg-[#F8FAFC] dark:bg-[#0F172A]">
|
||||
<AppHeader titulo="Alta de Clientes" />
|
||||
<BannerModoLocal />
|
||||
<main className="mx-auto max-w-[1280px] px-4 py-8 sm:px-6 sm:py-12">
|
||||
<main className="px-4 py-8 sm:px-6 sm:py-12 lg:px-8">
|
||||
<div className="mx-auto max-w-4xl">
|
||||
<p className="text-sm text-[#64748B] dark:text-[#94A3B8]">
|
||||
Elige cómo registrar al interesado: captura ligera de afluencia o formato completo de alta.
|
||||
@@ -397,7 +397,7 @@ export default function AltaClientePage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#F8FAFC] dark:bg-[#0F172A]">
|
||||
<AppHeader titulo="Alta Afluencia" />
|
||||
<main className="mx-auto max-w-[1280px] px-4 py-8 sm:px-6 sm:py-10">
|
||||
<main className="px-4 py-8 sm:px-6 sm:py-10 lg:px-8">
|
||||
<div className="mx-auto max-w-3xl">
|
||||
<p className="text-sm text-[#64748B] dark:text-[#94A3B8]">
|
||||
Captura rápida del interesado; entra al embudo de ventas.
|
||||
@@ -423,7 +423,7 @@ export default function AltaClientePage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#F8FAFC] dark:bg-[#0F172A]">
|
||||
<AppHeader titulo="Alta de Clientes" />
|
||||
<main className="mx-auto max-w-[1280px] px-4 py-8 sm:px-6 sm:py-10">
|
||||
<main className="px-4 py-8 sm:px-6 sm:py-10 lg:px-8">
|
||||
<div className="max-w-3xl">
|
||||
{borradores.length > 0 && (
|
||||
<>
|
||||
@@ -514,7 +514,7 @@ export default function AltaClientePage() {
|
||||
}
|
||||
/>
|
||||
|
||||
<main className="mx-auto max-w-[1280px] px-4 py-6 sm:px-6 sm:py-8">
|
||||
<main className="px-4 py-6 sm:px-6 sm:py-8 lg:px-8">
|
||||
<div className="md:grid md:grid-cols-[260px_minmax(0,1fr)] md:gap-8 lg:gap-8">
|
||||
<div className="mb-6 md:sticky md:top-20 md:mb-0 md:self-start">
|
||||
<Stepper pasos={[...PASOS]} pasoActual={paso} onIrAPaso={irAPaso} />
|
||||
|
||||
@@ -6,7 +6,7 @@ export default function Layout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#F8FAFC] dark:bg-[#0F172A] text-[#111827] dark:text-[#E2E8F0]">
|
||||
<header className="sticky top-0 z-10 border-b border-[#E5E7EB] bg-white/95 backdrop-blur dark:border-[#1E293B] dark:bg-[#1E293B]/95">
|
||||
<div className="mx-auto flex h-16 max-w-[1280px] items-center justify-between px-4 sm:px-6">
|
||||
<div className="flex h-16 items-center justify-between px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center gap-3">
|
||||
<a
|
||||
href="/"
|
||||
@@ -43,7 +43,7 @@ export default function Layout({ children }: { children: ReactNode }) {
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<main className="mx-auto max-w-[1280px] px-4 py-8 sm:px-6">{children}</main>
|
||||
<main className="px-4 py-8 sm:px-6 lg:px-8">{children}</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,8 +9,11 @@
|
||||
}
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
body {
|
||||
@apply bg-[#F8FAFC] text-[#111827] antialiased;
|
||||
@apply min-h-screen bg-[#F8FAFC] text-[#111827] antialiased;
|
||||
}
|
||||
|
||||
*:focus-visible {
|
||||
|
||||
@@ -237,7 +237,7 @@ export default function DashboardPage() {
|
||||
)}
|
||||
|
||||
{/* KPIs */}
|
||||
<div className="grid grid-cols-2 gap-4 md:gap-6 lg:grid-cols-4">
|
||||
<div className="grid grid-cols-2 gap-4 md:grid-cols-3 md:gap-6 lg:grid-cols-4 xl:grid-cols-5">
|
||||
<KpiCard titulo="Planes activos" valor={activos.length} />
|
||||
<KpiCard
|
||||
titulo="Al corriente / con atraso"
|
||||
|
||||
@@ -10,8 +10,11 @@
|
||||
}
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
body {
|
||||
@apply bg-[#F8FAFC] text-[#111827] antialiased;
|
||||
@apply min-h-screen bg-[#F8FAFC] text-[#111827] antialiased;
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
|
||||
@@ -306,7 +306,7 @@ export default function CotizadorPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#F8FAFC] dark:bg-[#0F172A]">
|
||||
<BannerModoLocal />
|
||||
<main className="mx-auto max-w-[1280px] px-4 py-8 sm:px-6 lg:py-10">
|
||||
<main className="px-4 py-8 sm:px-6 lg:px-8 lg:py-10">
|
||||
{/* Encabezado de página */}
|
||||
<div className="mb-8 flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
||||
<div>
|
||||
@@ -556,7 +556,7 @@ export default function CotizadorPage() {
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-8">
|
||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
{propuestas.map((p, i) => (
|
||||
<ProposalCard
|
||||
key={p.tipo}
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function MiTablero({ alCambiarAcciones }: { alCambiarAcciones: (a
|
||||
const funnel = resumen ? funnelMisLeads(resumen.misLeads) : []
|
||||
|
||||
return (
|
||||
<main className="mx-auto max-w-[1280px] px-4 py-8 sm:px-6">
|
||||
<main className="px-4 py-8 sm:px-6 lg:px-8">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-xl font-semibold text-[#111827] dark:text-[#E2E8F0]">Mi tablero</h1>
|
||||
{resumen && (
|
||||
@@ -70,7 +70,7 @@ export default function MiTablero({ alCambiarAcciones }: { alCambiarAcciones: (a
|
||||
|
||||
{resumen && (
|
||||
<>
|
||||
<section aria-label="Mis indicadores" className="grid gap-4 grid-cols-2 lg:grid-cols-4">
|
||||
<section aria-label="Mis indicadores" className="grid gap-4 grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
|
||||
<KpiCard
|
||||
titulo="Mis leads activos"
|
||||
valor={resumen.misLeads.length}
|
||||
|
||||
@@ -88,7 +88,7 @@ export default function TableroGeneral({
|
||||
const sinCobranza = resumen !== null && resumen.cobranza.planesAlCorriente + resumen.cobranza.planesConVencidos === 0
|
||||
|
||||
return (
|
||||
<main className="mx-auto max-w-[1280px] px-4 py-8 sm:px-6">
|
||||
<main className="px-4 py-8 sm:px-6 lg:px-8">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-xl font-semibold text-[#111827] dark:text-[#E2E8F0]">Tablero comercial</h1>
|
||||
{resumen && (
|
||||
@@ -109,7 +109,7 @@ export default function TableroGeneral({
|
||||
|
||||
{resumen && (
|
||||
<>
|
||||
<section aria-label="Indicadores clave" className="grid gap-4 grid-cols-2 lg:grid-cols-4">
|
||||
<section aria-label="Indicadores clave" className="grid gap-4 grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
|
||||
<KpiCard
|
||||
titulo="Leads totales"
|
||||
valor={resumen.leads.total}
|
||||
|
||||
@@ -24,8 +24,11 @@
|
||||
}
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
body {
|
||||
@apply bg-[#F8FAFC] text-[#111827] antialiased;
|
||||
@apply min-h-screen bg-[#F8FAFC] text-[#111827] antialiased;
|
||||
}
|
||||
|
||||
*:focus-visible {
|
||||
|
||||
@@ -47,7 +47,7 @@ export default function DashboardPage() {
|
||||
<div>
|
||||
<BannerModoLocal />
|
||||
<header className="sticky top-0 z-10 border-b border-[#E5E7EB] bg-white/95 backdrop-blur dark:border-[#1E293B] dark:bg-[#1E293B]/95">
|
||||
<div className="mx-auto flex min-h-14 max-w-[1280px] flex-wrap items-center justify-between gap-x-4 gap-y-2 px-4 py-2 sm:px-6">
|
||||
<div className="flex min-h-14 flex-wrap items-center justify-between gap-x-4 gap-y-2 px-4 py-2 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center gap-2.5">
|
||||
<a
|
||||
href="/"
|
||||
@@ -100,7 +100,7 @@ export default function DashboardPage() {
|
||||
</div>
|
||||
</header>
|
||||
{vista === null ? (
|
||||
<main className="mx-auto max-w-[1280px] px-4 py-16 sm:px-6">
|
||||
<main className="px-4 py-16 sm:px-6 lg:px-8">
|
||||
<p className="text-sm text-[#64748B] dark:text-[#94A3B8]">Tu rol no tiene tableros asignados por ahora.</p>
|
||||
</main>
|
||||
) : vista === 'mia' ? (
|
||||
|
||||
@@ -90,7 +90,7 @@ export default function App() {
|
||||
<Navbar usuario={usuario} onConfiguraciones={() => setVista('configuraciones')} />
|
||||
<BannerModoLocal />
|
||||
|
||||
<main className="mx-auto w-full max-w-[1280px] flex-1 px-4 sm:px-6">
|
||||
<main className="w-full flex-1 px-4 sm:px-6 lg:px-8">
|
||||
<section aria-labelledby="titulo-hero" className="py-12 sm:py-16">
|
||||
<h1
|
||||
id="titulo-hero"
|
||||
@@ -105,7 +105,7 @@ export default function App() {
|
||||
</section>
|
||||
|
||||
<nav aria-label="Módulos del ecosistema">
|
||||
<ul className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||
<ul className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
{MODULOS.filter((modulo) => esModuloVisible(modulo, permitidos)).map((modulo) => (
|
||||
<TarjetaModulo
|
||||
key={modulo.id}
|
||||
@@ -130,7 +130,7 @@ export default function App() {
|
||||
</main>
|
||||
|
||||
<footer className="mt-16 border-t border-[#E5E7EB] dark:border-[#1E293B]">
|
||||
<div className="mx-auto max-w-[1280px] px-6 py-8">
|
||||
<div className="px-6 py-8 sm:px-6 lg:px-8">
|
||||
<p className="text-xs text-[#64748B] dark:text-[#94A3B8]">Consult (AS) Technology</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -27,7 +27,7 @@ export function Navbar({ usuario, onConfiguraciones }: Props) {
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-10 border-b border-[#E5E7EB] bg-white/95 backdrop-blur dark:border-[#1E293B] dark:bg-[#1E293B]/95">
|
||||
<div className="mx-auto flex h-14 max-w-[1280px] items-center justify-between px-4 sm:px-6">
|
||||
<div className="flex h-14 items-center justify-between px-4 sm:px-6 lg:px-8">
|
||||
<span className="text-base font-semibold tracking-tight text-[#111827] dark:text-[#E2E8F0]">
|
||||
FRASA<span className="text-accent">.</span>
|
||||
</span>
|
||||
|
||||
@@ -69,7 +69,7 @@ export function VistaContactos({ onVolver }: Props) {
|
||||
useEffect(() => cargar(), [cargar])
|
||||
|
||||
return (
|
||||
<main className="mx-auto w-full max-w-[1280px] flex-1 px-4 py-12 sm:px-6 sm:py-16">
|
||||
<main className="w-full flex-1 px-4 py-12 sm:px-6 lg:px-8 sm:py-16">
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -25,7 +25,7 @@ export function ConfigPage({ onVolver }: Props) {
|
||||
const tabs = esAdmin ? [...TABS_BASE, { key: 'auditoria' as const, label: 'Auditoría' }] : TABS_BASE
|
||||
|
||||
return (
|
||||
<main className="mx-auto w-full max-w-[1280px] flex-1 px-6 py-12 sm:py-16">
|
||||
<main className="w-full flex-1 px-6 py-12 sm:px-6 lg:px-8 sm:py-16">
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -9,8 +9,11 @@
|
||||
}
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
body {
|
||||
@apply bg-[#F8FAFC] text-[#111827] antialiased dark:bg-[#0F172A] dark:text-[#E2E8F0];
|
||||
@apply min-h-screen bg-[#F8FAFC] text-[#111827] antialiased dark:bg-[#0F172A] dark:text-[#E2E8F0];
|
||||
}
|
||||
|
||||
/* Foco visible accesible: anillo azul en elementos interactivos */
|
||||
|
||||
@@ -101,7 +101,7 @@ export function CapturaPage({ onVolver }: Props) {
|
||||
const campos = CAMPOS_POR_DEPARTAMENTO[departamento] ?? []
|
||||
|
||||
return (
|
||||
<main className="mx-auto w-full max-w-[1280px] flex-1 px-4 py-12 sm:px-6 sm:py-16">
|
||||
<main className="w-full flex-1 px-4 py-12 sm:px-6 lg:px-8 sm:py-16">
|
||||
{/* Header */}
|
||||
<div className="flex flex-wrap items-center gap-4">
|
||||
<button
|
||||
|
||||
@@ -122,7 +122,7 @@ export function ClientesMaestroPage({ onVolver }: Props) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<main className="mx-auto w-full max-w-[1280px] flex-1 px-4 py-12 sm:px-6 sm:py-16">
|
||||
<main className="w-full flex-1 px-4 py-12 sm:px-6 lg:px-8 sm:py-16">
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -57,15 +57,15 @@ export default function KanbanView({ leads, onCambiarEstado }: KanbanViewProps)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex gap-4 overflow-x-auto pb-4">
|
||||
<div className="flex gap-4 overflow-x-auto scroll-smooth pb-4">
|
||||
{COLUMNAS.map((col) => (
|
||||
<div
|
||||
key={col.id}
|
||||
className={`flex min-w-[260px] flex-1 flex-col rounded-xl border border-[#E5E7EB] bg-[#F8FAFC] dark:border-[#334155] dark:bg-[#0F172A] border-t-4 ${col.color}`}
|
||||
className={`flex min-w-[220px] flex-1 flex-col rounded-xl border border-[#E5E7EB] bg-[#F8FAFC] dark:border-[#334155] dark:bg-[#0F172A] border-t-4 ${col.color}`}
|
||||
onDragOver={onDragOver}
|
||||
onDrop={() => onDrop(col.id)}
|
||||
>
|
||||
<div className="flex items-center justify-between px-4 pt-3 pb-2">
|
||||
<div className="flex items-center justify-between px-3 pt-3 pb-2 sm:px-4">
|
||||
<h4 className="text-xs font-semibold uppercase tracking-wider text-[#64748B] dark:text-[#94A3B8]">
|
||||
{col.titulo}
|
||||
</h4>
|
||||
@@ -83,7 +83,7 @@ export default function KanbanView({ leads, onCambiarEstado }: KanbanViewProps)
|
||||
draggable
|
||||
onDragStart={() => onDragStart(lead.id)}
|
||||
onDragEnd={() => setDragId(null)}
|
||||
className={`rounded-lg border border-[#E5E7EB] bg-white p-3 shadow-sm dark:border-[#1E293B] dark:bg-[#1E293B] cursor-grab transition-opacity ${
|
||||
className={`rounded-lg border border-[#E5E7EB] bg-white p-2.5 shadow-sm dark:border-[#1E293B] dark:bg-[#1E293B] cursor-grab transition-opacity sm:p-3 ${
|
||||
dragId === lead.id ? 'opacity-50' : ''
|
||||
}`}
|
||||
>
|
||||
|
||||
@@ -24,8 +24,11 @@
|
||||
}
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
body {
|
||||
@apply bg-[#F8FAFC] text-[#111827] antialiased;
|
||||
@apply min-h-screen bg-[#F8FAFC] text-[#111827] antialiased;
|
||||
}
|
||||
|
||||
*:focus-visible {
|
||||
|
||||
@@ -828,7 +828,7 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
||||
return (
|
||||
<>
|
||||
<header className="sticky top-0 z-10 border-b border-[#E5E7EB] bg-white/95 backdrop-blur dark:border-[#1E293B] dark:bg-[#1E293B]/95">
|
||||
<div className="mx-auto flex h-14 max-w-[1280px] items-center justify-between gap-4 px-4 sm:px-6">
|
||||
<div className="flex h-14 items-center justify-between gap-4 px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<a
|
||||
href="/"
|
||||
@@ -881,14 +881,14 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
||||
<BannerModoLocal />
|
||||
|
||||
{offline && (
|
||||
<div className="mx-auto max-w-[1280px] px-4 pt-4 sm:px-6">
|
||||
<div className="px-4 pt-4 sm:px-6 lg:px-8">
|
||||
<div className="rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm font-medium text-amber-700">
|
||||
Modo offline{offlineFecha ? ` — datos de ${offlineFecha}` : ''}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<main className="mx-auto max-w-[1280px] px-4 py-8 sm:px-6">
|
||||
<main className={`px-4 py-6 sm:px-6 lg:px-8 ${vistaKanban && tabCrm === 'leads' ? 'w-full' : 'mx-auto max-w-[1280px]'}`}>
|
||||
<div className="mb-6">
|
||||
<h1 className="text-xl font-semibold text-[#111827] dark:text-[#E2E8F0]">{nombreVendedor}</h1>
|
||||
<p className="mt-1 text-sm text-[#64748B] dark:text-[#94A3B8]">{formatoFechaCorta(hoy)}</p>
|
||||
@@ -937,8 +937,8 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
||||
<KpiCard titulo="Leads nuevos esta semana" valor={resumen.conteos.leadsNuevosSemana} />
|
||||
</section>
|
||||
|
||||
<div className="mt-6 flex flex-col gap-6 md:grid md:grid-cols-2 md:gap-6 lg:grid-cols-3">
|
||||
<div className="order-2 flex flex-col gap-6 md:order-1 md:col-span-2 lg:col-span-2">
|
||||
<div className={`mt-6 flex flex-col gap-6 ${vistaKanban && tabCrm === 'leads' ? '' : 'md:grid md:grid-cols-2 md:gap-6 lg:grid-cols-3'}`}>
|
||||
<div className={`order-2 flex flex-col gap-6 ${vistaKanban && tabCrm === 'leads' ? '' : 'md:order-1 md:col-span-2 lg:col-span-2'}`}>
|
||||
<section aria-label="CRM personal">
|
||||
<TabsCrm
|
||||
activa={tabCrm}
|
||||
@@ -1202,7 +1202,7 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<aside className="order-1 flex flex-col gap-6 md:order-2 lg:sticky lg:top-20 lg:self-start">
|
||||
<aside className={`order-1 flex flex-col gap-6 ${vistaKanban && tabCrm === 'leads' ? 'hidden' : 'md:order-2 lg:sticky lg:top-20 lg:self-start'}`}>
|
||||
<section aria-label="Mis actividades">
|
||||
<TituloSeccion>Mis actividades</TituloSeccion>
|
||||
{resumen.misActividadesHoy.length === 0 ? (
|
||||
|
||||
Reference in New Issue
Block a user