From 251cbe56a41591ccc09852a21440e1bdba36ee00 Mon Sep 17 00:00:00 2001 From: Ricardo Carneiro Date: Tue, 21 Oct 2025 22:45:52 -0300 Subject: [PATCH] feat: fale conosco --- Controllers/SupportController.cs | 15 + Resources/SharedResource.es-PY.resx | 59 +- Resources/SharedResource.es.resx | 1948 +++++++++++------------ Resources/SharedResource.pt-BR.resx | 59 +- Resources/SharedResource.resx | 71 +- Views/Shared/_Layout.cshtml | 9 +- Views/Shared/_TelegramPremiumFab.cshtml | 127 +- Views/Support/PremiumContact.cshtml | 82 + appsettings.Development.json | 4 + appsettings.Production.json | 10 +- appsettings.json | 14 +- wwwroot/css/telegram-fab.css | 159 +- wwwroot/js/telegram-fab.js | 357 +---- 13 files changed, 1492 insertions(+), 1422 deletions(-) create mode 100644 Controllers/SupportController.cs create mode 100644 Views/Support/PremiumContact.cshtml diff --git a/Controllers/SupportController.cs b/Controllers/SupportController.cs new file mode 100644 index 0000000..2747c22 --- /dev/null +++ b/Controllers/SupportController.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace QRRapidoApp.Controllers +{ + [Authorize] + public class SupportController : Controller + { + [HttpGet] + public IActionResult PremiumContact() + { + return View(); + } + } +} diff --git a/Resources/SharedResource.es-PY.resx b/Resources/SharedResource.es-PY.resx index 9325daa..8067577 100644 --- a/Resources/SharedResource.es-PY.resx +++ b/Resources/SharedResource.es-PY.resx @@ -1184,6 +1184,63 @@ Soporte Premium (usuarios pagos) + + ¡Quiero hablar con ustedes! + + + Elegí cómo hablar con nuestro equipo: + + + Hablar por Telegram + + + Enviar formulario + + + Contacto con Soporte Premium + + + Hablá con nuestro equipo premium + + + Completá tus datos y te responderemos lo antes posible. + + + Tu nombre + + + ¿Cómo debemos llamarte? + + + Tu correo + + + vos@ejemplo.com + + + Tu mensaje + + + Contanos cómo podemos ayudarte… + + + Canal de contacto preferido + + + Telegram + + + Correo + + + Teléfono / WhatsApp + + + Enviar mensaje + + + Usamos tus datos solo para responder la consulta. Los mensajes se procesan vía Formspree. + Servicios Profesionales @@ -2063,4 +2120,4 @@ Los códigos QR estáticos son ideales para información permanente como WiFi, tarjetas de visita, URLs de sitios web y contactos. - \ No newline at end of file + diff --git a/Resources/SharedResource.es.resx b/Resources/SharedResource.es.resx index 064c8ad..621ee8a 100644 --- a/Resources/SharedResource.es.resx +++ b/Resources/SharedResource.es.resx @@ -1,976 +1,974 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ¡Japo código QR pya'épe! (Genera códigos QR en segundos) - - - Japo Código QR (Generar) - - - Mba'éichapa código QR (Tipo) - - - Mba'e oĩva (Contenido) - - - URL/Enlace - - - Texto Simple - - - WiFi ñanduti - - - Tarjeta mba'eichaguáva (de Visita) - - - SMS - - - Email - - - QR Dinamico (Premium) - - - Estilo pya'e (Rápido) - - - Ymave (Clásico) - - - Ko'ãgagua (Moderno) - - - Sa'ygua (Colorido) - - - Emoĩ ne código QR mba'e ko'ápe... (Ingrese el contenido aquí) - - - Ñemohenda porãve (Personalización Avanzada) - - - Sa'y tuichavéva (Color Principal) - - - Sa'y hugua (Color de Fondo) - - - Tuicha (Tamaño) - - - Opa'ĩ (Margen) - - - Ta'anga/Ícono - - - Estilo de Esquinas - - - Japo Código QR pya'épe (Generar Rápidamente) - - - Hecha tenondegua (Vista Previa) - - - Ne código QR ojekuaa ko'ápe segundos pype (aparecerá aquí en segundos) - - - Generacion ultra-rapida garantizada - - - Descargar PNG - - - Descargar SVG (Vectorial) - - - Descargar PDF - - - Guardar en Historial - - - Inicie sesion para guardar en el historial - - - QR Rápido Premium (Porã) - - - Ñe'ẽ pya'épe (Consejos para QR Más Rápidos) - - - URLs cortas se generan mas rapido - - - Menos texto = mayor velocidad - - - Colores solidos optimizan el proceso - - - Tamanos menores aceleran la descarga - - - Iniciar Sesion - - - Iniciar con - - - Google - - - Microsoft - - - Desbloquea todas las funciones premium! - - - Jeporu porã! (Oferta Premium!) - - - Elimina anuncios, accede a analisis detallados y mucho mas por solo $12.90/mes o $129.00/ano. Inicia sesion y suscribete ahora! - - - Politica de Privacidad - - - Volver al generador - - - Generado en - - - s - - - Generacion ultra rapida! - - - Generacion rapida! - - - Generacion normal - - - Osẽ vai - Ha'e jéy (Error - Inténtalo de nuevo) - - - Ñongatu porã! Código QR guardado en el historial! - - - Crear Codigo QR Rapidamente - - - Usuario Premium Activo - - - Sin Anuncios • Historial • QR Ilimitado - - - Ilimitado hoy - - - Codigos QR restantes - - - Tipo de Codigo QR - - - Seleccionar tipo - - - URL/Enlace - - - Texto Simple - - - Tarjeta de Visita - - - QR Dinamico (Premium) - - - Ingrese el contenido de su codigo QR aqui... - - - Sugerencias de contenido - - - Clasico - - - Moderno - - - Colorido - - - Rede WPA (a mais comum) - - - WEP (muito antigo) - - - Sin contrasenha - - - Acelera tu productividad con el generador de QR más rápido del mundo - - - 3x más rápido que la competencia - - - Estado Actual - - - Tienes - - - días restantes sin anuncios. - - - ¡Actualiza ahora y ten acceso premium para siempre! - - - días restantes - - - El plan más popular - - - por mes - - - Códigos QR ilimitados - - - Generación ultra-rápida (0.4s) - - - Sin anuncios para siempre - - - Códigos QR dinámicos - - - Analítica en tiempo real - - - Soporte prioritario - - - API para desarrolladores - - - Actualizar Ahora - - - Pago seguro via Stripe - - - Cancela cuando quieras - - - Comparación de Planes - - - Función - - - Códigos QR por día - - - Ilimitado - - - Velocidad de generación - - - Anuncios - - - Sin anuncios - - - Analítica detallada - - - Demostración de Velocidad - - - Competidores - - - Tiempo promedio - - - ¡11x más rápido! - - - Preguntas Frecuentes - - - ¿Puedo cancelar en cualquier momento? - - - ¡Sí! Puedes cancelar tu suscripción en cualquier momento. No hay tarifas de cancelación y mantendrás el acceso premium hasta el final del período ya pagado. - - - ¿Qué son los códigos QR dinámicos? - - - Los códigos QR dinámicos te permiten cambiar el contenido del QR después de que haya sido creado, sin necesidad de generar un nuevo código. Perfecto para campañas de marketing y uso empresarial. - - - ¿Cómo funciona el soporte prioritario? - - - Los usuarios premium reciben respuesta en hasta 2 horas hábiles por email, acceso al chat directo y soporte técnico especializado. - - - Error al procesar el pago: - - - Error al procesar el pago. Inténtalo de nuevo. - - - Publicidad - - - ✨ Usuario Premium - ¡Sin anuncios! - - - ¡Actualiza a Premium y elimina los anuncios! - - - Premium: Sin anuncios + Historial + QR ilimitados - - - Inicia sesión con tu cuenta y obtén: - - - 30 días sin anuncios - - - 50 códigos QR/día - - - Historial de códigos QR - - - Iniciar con Google - - - Iniciar con Microsoft - - - ¡Oferta Especial! - - - Al iniciar sesión, obtienes automáticamente - - - y puedes generar hasta - - - gratuitamente. - - - No te registramos sin tu permiso. - - - Política de Privacidad - - - ¡Jehepy porã! (Pago exitoso!) - - - Volver al Inicio - - - Pago cancelado. - - - Ver Planes - - - Desbloquea el Poder Total de QRRápido - - - Acceso sin límites, sin anuncios y con recursos exclusivos para máxima productividad. - - - Plan Mensual - - - Ideal para comenzar a explorar las funciones premium. - - - Suscribirse Ahora - - - Plan Anual - - - Recomendado - - - /año - - - Ahorra $ - - - La mejor relación calidad-precio para usuarios frecuentes. - - - Suscribirse al Plan Anual - - - Todos los planes incluyen: - - - Redirigiendo... - - - Ocurrió un error al iniciar el pago. Inténtalo de nuevo. - - - Tus códigos QR generados se guardan aquí para descarga futura - - - Generar Nuevo Código QR - - - Tipo: - - - Creado el: - - - Mostrando los 50 códigos QR más recientes. Los más antiguos se eliminan automáticamente. - - - Ningún Código QR encontrado - - - Cuando generes códigos QR estando conectado, aparecerán aquí para descarga futura. - - - Generar Primer Código QR - - - Error al regenerar el Código QR. Inténtalo de nuevo. - - - Pequeño (200px) - - - Mediano (300px) - - - Grande (500px) - - - XL (800px) - - - Mínimo - - - Grande - - - Logo/Icono - - - PNG, JPG hasta 2MB - - - Estilo de Bordes - - - Cuadrado - - - Redondeado - - - Circular - - - Hoja - - - Generar Código QR Rápidamente - - - Generando... - - - Disponibilidad - - - QRs generados hoy - - - Tu código QR aparecerá aquí en segundos - - - Generación ultra-rápida garantizada - - - Descargar SVG (Vectorial) - - - Compartir Código QR - - - Compartir (Sistema) - - - para guardar en el historial - - - Generación prioritaria (0.4s) - - - Acelerar por $19.90/mes - - - Primero, elige el tipo de código QR - - - 🌐 Para generar QR de URL, ingresa la dirección completa (ej: https://google.com) - - - 👤 Para tarjeta de visita, completa nombre, teléfono y email en los campos - - - 📶 Para WiFi, ingresa nombre de red, contraseña y tipo de seguridad - - - 💬 Para SMS, ingresa el número del destinatario y el mensaje - - - 📧 Para email, completa destinatario, asunto y mensaje (opcional) - - - 📝 Para texto libre, ingresa cualquier contenido que desees - - - Consejos para QR Más Rápidos - - - URLs cortas se generan más rápido - - - Menos texto = mayor velocidad - - - Colores sólidos optimizan el proceso - - - Tamaños menores aceleran la descarga - - - Mba'ére QR Rápido pya'eve? (¿Por qué es más rápido?) - - - Comparación con otros generadores populares - - - Optimizado para velocidad - - - Competidor A - - - Generador tradicional - - - Competidor B - - - Interfaz pesada - - - Competidor C - - - Muchos anuncios - - - promedio - - - Generar Código QR - - - Perfil - - - Historial - - - Premium hendyva (Activo) - - - Salir - - - ¡Iniciar sesión = 30 días sin anuncios! - - - El generador de QR más rápido de la web - - - Promedio de - - - 1.2 segundos - - - por código QR • Rei rehe (Gratis) • Sin registro obligatorio - - - El generador de códigos QR pya'eve (ás rápido) de la web. Rei rehe (Gratis), seguro y confiable. - - - Enlaces Útiles - - - Términos de Uso - - - Soporte - - - Ayuda - - - Todos los derechos reservados. - - - Códigos QR restantes hoy - - - ¡Límite diario alcanzado! Inicia sesión para acceso ilimitado. - - - Usuarios anónimos: 3 códigos QR por día - - - Política de Privacidad - QR Rapido - - - Conocé nuestra política de privacidad y cómo protegemos tus datos personales en QR Rapido. - - - Última actualización - - - Esta Política de Privacidad describe cómo QR Rapido ("nosotros", "nuestro" o "nuestra") recolecta, usa y protege la información que proporcionás cuando usás nuestro servicio de generación de códigos QR. - - - 1. Recolección de Datos - - - Recolectamos la siguiente información: - -• Datos de autenticación vía Google/Microsoft (nombre, email, foto de perfil) -• Contenido de los códigos QR generados (solo para usuarios registrados que eligen guardar en el historial) -• Datos de uso y estadísticas anónimas para mejorar nuestro servicio -• Información de pago procesada vía Stripe (no almacenamos datos de tarjeta) - - - 2. Uso de los Datos - - - Utilizamos tus datos para: - -• Proporcionar y mejorar nuestro servicio de generación de códigos QR -• Mantener tu historial de códigos QR (solo si elegís guardarlos) -• Procesar pagos de suscripciones premium -• Enviar comunicaciones relacionadas al servicio -• Cumplir obligaciones legales conforme a las leyes de protección de datos - - - 3. Protección de los Datos - - - Implementamos medidas de seguridad técnicas y organizacionales adecuadas para proteger tus datos personales contra acceso no autorizado, alteración, divulgación o destrucción, incluyendo: - -• Cifrado SSL/TLS en todas las comunicaciones -• Almacenamiento seguro en servidores protegidos -• Control de acceso restringido a los datos -• Monitoreo continuo de seguridad - - - 4. Compartir Datos - - - No vendemos, alquilamos ni compartimos tus datos personales con terceros, excepto: - -• Con proveedores de servicios esenciales (Google, Microsoft, Stripe) para autenticación y pagos -• Cuando sea requerido por ley u orden judicial -• Para proteger nuestros derechos legales y la seguridad de los usuarios - - - 5. Tus Derechos - - - De acuerdo con las leyes de protección de datos, tenés derecho a: - -• Acceder a tus datos personales -• Corregir datos incompletos o incorrectos -• Solicitar la eliminación de datos innecesarios -• Revocar consentimiento para tratamiento de datos -• Portabilidad de tus datos - - - 6. Cookies y Tecnologías Similares - - - Utilizamos cookies esenciales para el funcionamiento del sitio y análisis de tráfico vía Google Analytics. Podés gestionar tus preferencias de cookies en la configuración de tu navegador. - - - 7. Contacto - - - Para consultas sobre esta Política de Privacidad o ejercer tus derechos, contactanos a través del email: contato@qrrapido.site - - - Términos de Uso - QR Rapido - - - Leé los términos y condiciones de uso de QR Rapido, el generador de códigos QR más rápido de América Latina. - - - Última actualización - - - Estos Términos de Uso ("Términos") rigen el uso del servicio QR Rapido ("Servicio") proporcionado por nuestra empresa ("nosotros", "nuestro" o "nuestra"). Al usar nuestro Servicio, aceptás estos Términos. - - - 1. Aceptación de los Términos - - - Al acceder y usar QR Rapido, declarás tener al menos 18 años de edad o poseer autorización de padres/responsables, y aceptás cumplir estos Términos y todas las leyes aplicables. - - - 2. Descripción del Servicio - - - QR Rapido es un servicio online gratuito de generación de códigos QR que ofrece: - -• Generación rápida de códigos QR para diversos tipos de contenido -• Versión gratuita con limitaciones diarias -• Plan Premium con recursos avanzados e ilimitados -• Historial de códigos para usuarios registrados - - - 3. Responsabilidades del Usuario - - - Te comprometés a: - -• Usar el servicio únicamente para fines legales y éticos -• No generar códigos QR con contenido ofensivo, ilegal o que infrinja derechos de terceros -• No intentar comprometer la seguridad o disponibilidad del servicio -• Mantener la confidencialidad de tus credenciales de acceso - - - 4. Usos Prohibidos - - - Está prohibido usar el servicio para: - -• Diseminar malware, phishing o enlaces maliciosos -• Violación de derechos de autor o propiedad intelectual -• Spam, acoso o actividades fraudulentas -• Actividades que violen leyes nacionales o internacionales - - - 5. Propiedad Intelectual - - - Todos los derechos sobre el software, diseño, marca y contenido de QR Rapido pertenecen a nuestra empresa. Los códigos QR generados son de tu propiedad, pero nos concedés licencia para almacenarlos según sea necesario para proporcionar el servicio. - - - 6. Limitaciones del Servicio - - - • Usuarios gratuitos tienen límite diario de códigos QR -• Nos reservamos el derecho de modificar o interrumpir el servicio temporalmente -• No garantizamos disponibilidad 100% del tiempo -• Podemos implementar medidas técnicas para prevenir abuso - - - 7. Pagos y Suscripciones - - - • Suscripciones Premium son procesadas de forma segura vía Stripe -• Pagos son recurrentes mensualmente hasta cancelación -• Puede cancelar su suscripción en cualquier momento desde su perfil, sin multas ni cargos adicionales -• Tiene derecho de retracto de 7 días para solicitar reembolso total (Ley de Defensa del Consumidor) -• Después de la cancelación, mantendrá acceso Premium hasta el final del período ya pagado -• No hay reembolso proporcional para cancelaciones después del período de 7 días -• Precios pueden ser alterados mediante aviso previo de 30 días - - - 8. Limitación de Responsabilidad - - - El servicio se proporciona "como está". No nos responsabilizamos por: - -• Daños directos o indirectos derivados del uso del servicio -• Pérdida de datos o interrupción de negocios -• Uso inadecuado de los códigos QR generados por terceros -• Contenido accedido a través de los códigos QR - - - 9. Modificaciones de los Términos - - - Podemos actualizar estos Términos periódicamente. Cambios significativos serán comunicados por email o aviso en el sitio. El uso continuado después de los cambios constituye aceptación de los nuevos Términos. - - - 10. Ley Aplicable - - - Estos Términos se rigen por las leyes aplicables en cada jurisdicción. Las disputas serán resueltas en los tribunales competentes de cada país, sin perjuicio a tu derecho de acceso a los órganos de defensa del consumidor. - - - 11. Contacto - - - Para dudas sobre estos Términos de Uso, contactanos: contato@qrrapido.site - - - Volver al Inicio - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ¡Japo código QR pya'épe! (Genera códigos QR en segundos) + + + Japo Código QR (Generar) + + + Mba'éichapa código QR (Tipo) + + + Mba'e oĩva (Contenido) + + + URL/Enlace + + + Texto Simple + + + WiFi ñanduti + + + Tarjeta mba'eichaguáva (de Visita) + + + SMS + + + Email + + + QR Dinamico (Premium) + + + Estilo pya'e (Rápido) + + + Ymave (Clásico) + + + Ko'ãgagua (Moderno) + + + Sa'ygua (Colorido) + + + Emoĩ ne código QR mba'e ko'ápe... (Ingrese el contenido aquí) + + + Ñemohenda porãve (Personalización Avanzada) + + + Sa'y tuichavéva (Color Principal) + + + Sa'y hugua (Color de Fondo) + + + Tuicha (Tamaño) + + + Opa'ĩ (Margen) + + + Ta'anga/Ícono + + + Estilo de Esquinas + + + Japo Código QR pya'épe (Generar Rápidamente) + + + Hecha tenondegua (Vista Previa) + + + Ne código QR ojekuaa ko'ápe segundos pype (aparecerá aquí en segundos) + + + Generacion ultra-rapida garantizada + + + Descargar PNG + + + Descargar SVG (Vectorial) + + + Descargar PDF + + + Guardar en Historial + + + Inicie sesion para guardar en el historial + + + QR Rápido Premium (Porã) + + + Ñe'ẽ pya'épe (Consejos para QR Más Rápidos) + + + URLs cortas se generan mas rapido + + + Menos texto = mayor velocidad + + + Colores solidos optimizan el proceso + + + Tamanos menores aceleran la descarga + + + Iniciar Sesion + + + Iniciar con + + + Google + + + Microsoft + + + Desbloquea todas las funciones premium! + + + Jeporu porã! (Oferta Premium!) + + + Elimina anuncios, accede a analisis detallados y mucho mas por solo $12.90/mes o $129.00/ano. Inicia sesion y suscribete ahora! + + + Politica de Privacidad + + + Volver al generador + + + Generado en + + + s + + + Generacion ultra rapida! + + + Generacion rapida! + + + Generacion normal + + + Osẽ vai - Ha'e jéy (Error - Inténtalo de nuevo) + + + Ñongatu porã! Código QR guardado en el historial! + + + Crear Codigo QR Rapidamente + + + Usuario Premium Activo + + + Sin Anuncios • Historial • QR Ilimitado + + + Ilimitado hoy + + + Codigos QR restantes + + + Tipo de Codigo QR + + + Seleccionar tipo + + + URL/Enlace + + + Texto Simple + + + Tarjeta de Visita + + + QR Dinamico (Premium) + + + Ingrese el contenido de su codigo QR aqui... + + + Sugerencias de contenido + + + Clasico + + + Moderno + + + Colorido + + + Rede WPA (a mais comum) + + + WEP (muito antigo) + + + Sin contrasenha + + + Acelera tu productividad con el generador de QR más rápido del mundo + + + 3x más rápido que la competencia + + + Estado Actual + + + Tienes + + + días restantes sin anuncios. + + + ¡Actualiza ahora y ten acceso premium para siempre! + + + días restantes + + + El plan más popular + + + por mes + + + Códigos QR ilimitados + + + Generación ultra-rápida (0.4s) + + + Sin anuncios para siempre + + + Códigos QR dinámicos + + + Analítica en tiempo real + + + Soporte prioritario + + + API para desarrolladores + + + Actualizar Ahora + + + Pago seguro via Stripe + + + Cancela cuando quieras + + + Comparación de Planes + + + Función + + + Códigos QR por día + + + Ilimitado + + + Velocidad de generación + + + Anuncios + + + Sin anuncios + + + Analítica detallada + + + Demostración de Velocidad + + + Competidores + + + Tiempo promedio + + + ¡11x más rápido! + + + Preguntas Frecuentes + + + ¿Puedo cancelar en cualquier momento? + + + ¡Sí! Puedes cancelar tu suscripción en cualquier momento. No hay tarifas de cancelación y mantendrás el acceso premium hasta el final del período ya pagado. + + + ¿Qué son los códigos QR dinámicos? + + + Los códigos QR dinámicos te permiten cambiar el contenido del QR después de que haya sido creado, sin necesidad de generar un nuevo código. Perfecto para campañas de marketing y uso empresarial. + + + ¿Cómo funciona el soporte prioritario? + + + Los usuarios premium reciben respuesta en hasta 2 horas hábiles por email, acceso al chat directo y soporte técnico especializado. + + + Error al procesar el pago: + + + Error al procesar el pago. Inténtalo de nuevo. + + + Publicidad + + + ✨ Usuario Premium - ¡Sin anuncios! + + + ¡Actualiza a Premium y elimina los anuncios! + + + Premium: Sin anuncios + Historial + QR ilimitados + + + Inicia sesión con tu cuenta y obtén: + + + 30 días sin anuncios + + + 50 códigos QR/día + + + Historial de códigos QR + + + Iniciar con Google + + + Iniciar con Microsoft + + + ¡Oferta Especial! + + + Al iniciar sesión, obtienes automáticamente + + + y puedes generar hasta + + + gratuitamente. + + + No te registramos sin tu permiso. + + + Política de Privacidad + + + ¡Jehepy porã! (Pago exitoso!) + + + Volver al Inicio + + + Pago cancelado. + + + Ver Planes + + + Desbloquea el Poder Total de QRRápido + + + Acceso sin límites, sin anuncios y con recursos exclusivos para máxima productividad. + + + Plan Mensual + + + Ideal para comenzar a explorar las funciones premium. + + + Suscribirse Ahora + + + Plan Anual + + + Recomendado + + + /año + + + Ahorra $ + + + La mejor relación calidad-precio para usuarios frecuentes. + + + Suscribirse al Plan Anual + + + Todos los planes incluyen: + + + Redirigiendo... + + + Ocurrió un error al iniciar el pago. Inténtalo de nuevo. + + + Tus códigos QR generados se guardan aquí para descarga futura + + + Generar Nuevo Código QR + + + Tipo: + + + Creado el: + + + Mostrando los 50 códigos QR más recientes. Los más antiguos se eliminan automáticamente. + + + Ningún Código QR encontrado + + + Cuando generes códigos QR estando conectado, aparecerán aquí para descarga futura. + + + Generar Primer Código QR + + + Error al regenerar el Código QR. Inténtalo de nuevo. + + + Pequeño (200px) + + + Mediano (300px) + + + Grande (500px) + + + XL (800px) + + + Mínimo + + + Grande + + + Logo/Icono + + + PNG, JPG hasta 2MB + + + Estilo de Bordes + + + Cuadrado + + + Redondeado + + + Circular + + + Hoja + + + Generar Código QR Rápidamente + + + Generando... + + + Disponibilidad + + + QRs generados hoy + + + Tu código QR aparecerá aquí en segundos + + + Generación ultra-rápida garantizada + + + Descargar SVG (Vectorial) + + + Compartir Código QR + + + Compartir (Sistema) + + + para guardar en el historial + + + Generación prioritaria (0.4s) + + + Acelerar por $19.90/mes + + + Primero, elige el tipo de código QR + + + 🌐 Para generar QR de URL, ingresa la dirección completa (ej: https://google.com) + + + 👤 Para tarjeta de visita, completa nombre, teléfono y email en los campos + + + 📶 Para WiFi, ingresa nombre de red, contraseña y tipo de seguridad + + + 💬 Para SMS, ingresa el número del destinatario y el mensaje + + + 📧 Para email, completa destinatario, asunto y mensaje (opcional) + + + 📝 Para texto libre, ingresa cualquier contenido que desees + + + Consejos para QR Más Rápidos + + + URLs cortas se generan más rápido + + + Menos texto = mayor velocidad + + + Colores sólidos optimizan el proceso + + + Tamaños menores aceleran la descarga + + + Mba'ére QR Rápido pya'eve? (¿Por qué es más rápido?) + + + Comparación con otros generadores populares + + + Optimizado para velocidad + + + Competidor A + + + Generador tradicional + + + Competidor B + + + Interfaz pesada + + + Competidor C + + + Muchos anuncios + + + promedio + + + Generar Código QR + + + Perfil + + + Historial + + + Premium hendyva (Activo) + + + Salir + + + ¡Iniciar sesión = 30 días sin anuncios! + + + El generador de QR más rápido de la web + + + Promedio de + + + 1.2 segundos + + + por código QR • Rei rehe (Gratis) • Sin registro obligatorio + + + El generador de códigos QR pya'eve (ás rápido) de la web. Rei rehe (Gratis), seguro y confiable. + + + Enlaces Útiles + + + Términos de Uso + + + Soporte + + + Ayuda + + + Todos los derechos reservados. + + + Códigos QR restantes hoy + + + ¡Límite diario alcanzado! Inicia sesión para acceso ilimitado. + + + Usuarios anónimos: 3 códigos QR por día + + + Política de Privacidad - QR Rapido + + + Conocé nuestra política de privacidad y cómo protegemos tus datos personales en QR Rapido. + + + Última actualización + + + Esta Política de Privacidad describe cómo QR Rapido ("nosotros", "nuestro" o "nuestra") recolecta, usa y protege la información que proporcionás cuando usás nuestro servicio de generación de códigos QR. + + + 1. Recolección de Datos + + + Recolectamos la siguiente información: + +• Datos de autenticación vía Google/Microsoft (nombre, email, foto de perfil) +• Contenido de los códigos QR generados (solo para usuarios registrados que eligen guardar en el historial) +• Datos de uso y estadísticas anónimas para mejorar nuestro servicio +• Información de pago procesada vía Stripe (no almacenamos datos de tarjeta) + + + 2. Uso de los Datos + + + Utilizamos tus datos para: + +• Proporcionar y mejorar nuestro servicio de generación de códigos QR +• Mantener tu historial de códigos QR (solo si elegís guardarlos) +• Procesar pagos de suscripciones premium +• Enviar comunicaciones relacionadas al servicio +• Cumplir obligaciones legales conforme a las leyes de protección de datos + + + 3. Protección de los Datos + + + Implementamos medidas de seguridad técnicas y organizacionales adecuadas para proteger tus datos personales contra acceso no autorizado, alteración, divulgación o destrucción, incluyendo: + +• Cifrado SSL/TLS en todas las comunicaciones +• Almacenamiento seguro en servidores protegidos +• Control de acceso restringido a los datos +• Monitoreo continuo de seguridad + + + 4. Compartir Datos + + + No vendemos, alquilamos ni compartimos tus datos personales con terceros, excepto: + +• Con proveedores de servicios esenciales (Google, Microsoft, Stripe) para autenticación y pagos +• Cuando sea requerido por ley u orden judicial +• Para proteger nuestros derechos legales y la seguridad de los usuarios + + + 5. Tus Derechos + + + De acuerdo con las leyes de protección de datos, tenés derecho a: + +• Acceder a tus datos personales +• Corregir datos incompletos o incorrectos +• Solicitar la eliminación de datos innecesarios +• Revocar consentimiento para tratamiento de datos +• Portabilidad de tus datos + + + 6. Cookies y Tecnologías Similares + + + Utilizamos cookies esenciales para el funcionamiento del sitio y análisis de tráfico vía Google Analytics. Podés gestionar tus preferencias de cookies en la configuración de tu navegador. + + + 7. Contacto + + + Para consultas sobre esta Política de Privacidad o ejercer tus derechos, contactanos a través del email: contato@qrrapido.site + + + Términos de Uso - QR Rapido + + + Leé los términos y condiciones de uso de QR Rapido, el generador de códigos QR más rápido de América Latina. + + + Última actualización + + + Estos Términos de Uso ("Términos") rigen el uso del servicio QR Rapido ("Servicio") proporcionado por nuestra empresa ("nosotros", "nuestro" o "nuestra"). Al usar nuestro Servicio, aceptás estos Términos. + + + 1. Aceptación de los Términos + + + Al acceder y usar QR Rapido, declarás tener al menos 18 años de edad o poseer autorización de padres/responsables, y aceptás cumplir estos Términos y todas las leyes aplicables. + + + 2. Descripción del Servicio + + + QR Rapido es un servicio online gratuito de generación de códigos QR que ofrece: + +• Generación rápida de códigos QR para diversos tipos de contenido +• Versión gratuita con limitaciones diarias +• Plan Premium con recursos avanzados e ilimitados +• Historial de códigos para usuarios registrados + + + 3. Responsabilidades del Usuario + + + Te comprometés a: + +• Usar el servicio únicamente para fines legales y éticos +• No generar códigos QR con contenido ofensivo, ilegal o que infrinja derechos de terceros +• No intentar comprometer la seguridad o disponibilidad del servicio +• Mantener la confidencialidad de tus credenciales de acceso + + + 4. Usos Prohibidos + + + Está prohibido usar el servicio para: + +• Diseminar malware, phishing o enlaces maliciosos +• Violación de derechos de autor o propiedad intelectual +• Spam, acoso o actividades fraudulentas +• Actividades que violen leyes nacionales o internacionales + + + 5. Propiedad Intelectual + + + Todos los derechos sobre el software, diseño, marca y contenido de QR Rapido pertenecen a nuestra empresa. Los códigos QR generados son de tu propiedad, pero nos concedés licencia para almacenarlos según sea necesario para proporcionar el servicio. + + + 6. Limitaciones del Servicio + + + • Usuarios gratuitos tienen límite diario de códigos QR +• Nos reservamos el derecho de modificar o interrumpir el servicio temporalmente +• No garantizamos disponibilidad 100% del tiempo +• Podemos implementar medidas técnicas para prevenir abuso + + + 7. Pagos y Suscripciones + + + • Suscripciones Premium son procesadas de forma segura vía Stripe +• Pagos son recurrentes mensualmente hasta cancelación +• Puede cancelar su suscripción en cualquier momento desde su perfil, sin multas ni cargos adicionales +• Tiene derecho de retracto de 7 días para solicitar reembolso total (Ley de Defensa del Consumidor) +• Después de la cancelación, mantendrá acceso Premium hasta el final del período ya pagado +• No hay reembolso proporcional para cancelaciones después del período de 7 días +• Precios pueden ser alterados mediante aviso previo de 30 días + + + 8. Limitación de Responsabilidad + + + El servicio se proporciona "como está". No nos responsabilizamos por: + +• Daños directos o indirectos derivados del uso del servicio +• Pérdida de datos o interrupción de negocios +• Uso inadecuado de los códigos QR generados por terceros +• Contenido accedido a través de los códigos QR + + + 9. Modificaciones de los Términos + + + Podemos actualizar estos Términos periódicamente. Cambios significativos serán comunicados por email o aviso en el sitio. El uso continuado después de los cambios constituye aceptación de los nuevos Términos. + + + 10. Ley Aplicable + + + Estos Términos se rigen por las leyes aplicables en cada jurisdicción. Las disputas serán resueltas en los tribunales competentes de cada país, sin perjuicio a tu derecho de acceso a los órganos de defensa del consumidor. + + + 11. Contacto + + + Para dudas sobre estos Términos de Uso, contactanos: contato@qrrapido.site + + + Volver al Inicio + + + ¡Quiero hablar con ustedes! + + + Elegí cómo hablar con nuestro equipo: + + + Hablar por Telegram + + + Enviar formulario + + + Contacto con Soporte Premium + + + Habla con nuestro equipo premium + + + Completa tus datos y te responderemos lo antes posible. + + + Tu nombre + + + ¿Cómo debemos llamarte? + + + Tu correo + + + tu@ejemplo.com + + + Tu mensaje + + + Cuéntanos cómo podemos ayudarte… + + + Canal de contacto preferido + + + Telegram + + + Correo + + + Teléfono / WhatsApp + + + Enviar mensaje + + + Usamos esta información solo para responder tu solicitud. Los mensajes se procesan mediante Formspree. + \ No newline at end of file diff --git a/Resources/SharedResource.pt-BR.resx b/Resources/SharedResource.pt-BR.resx index 74ade57..286f6d7 100644 --- a/Resources/SharedResource.pt-BR.resx +++ b/Resources/SharedResource.pt-BR.resx @@ -1274,6 +1274,63 @@ Suporte Premium (usuários pagos) + + Quero falar com vocês! + + + Escolha como prefere falar com nossa equipe: + + + Falar no Telegram + + + Enviar formulário + + + Contato com Suporte Premium + + + Fale com nossa equipe premium + + + Preencha seus dados e entraremos em contato o quanto antes. + + + Seu nome + + + Como devemos te chamar? + + + Seu email + + + voce@exemplo.com + + + Sua mensagem + + + Conte como podemos ajudar… + + + Canal de contato preferido + + + Telegram + + + Email + + + Telefone / WhatsApp + + + Enviar mensagem + + + Usaremos suas informações apenas para responder à solicitação. As mensagens são processadas via Formspree. + Serviços Profissionais @@ -2153,4 +2210,4 @@ QR codes estáticos são ideais para informações permanentes como WiFi, cartões de visita, URLs de sites, e contatos. - \ No newline at end of file + diff --git a/Resources/SharedResource.resx b/Resources/SharedResource.resx index dbb925d..4250b1b 100644 --- a/Resources/SharedResource.resx +++ b/Resources/SharedResource.resx @@ -420,10 +420,67 @@ QR Code deleted successfully! - - Error deleting QR code. Please try again. - - - Deleting - - \ No newline at end of file + + Error deleting QR code. Please try again. + + + Deleting + + + Talk with our team + + + Choose how you'd like to reach us: + + + Chat on Telegram + + + Send contact form + + + Premium Support Contact + + + Talk to our premium support team + + + Fill out the form below and we will reach you back as soon as possible. + + + Your name + + + How should we call you? + + + Your email + + + you@example.com + + + Your message + + + Tell us how we can help… + + + Preferred contact channel + + + Telegram + + + Email + + + Phone / WhatsApp + + + Send message + + + We use this information only to respond to your request. Messages are processed via Formspree. + + diff --git a/Views/Shared/_Layout.cshtml b/Views/Shared/_Layout.cshtml index 89c312b..688847b 100644 --- a/Views/Shared/_Layout.cshtml +++ b/Views/Shared/_Layout.cshtml @@ -75,7 +75,7 @@ - + @if (isDevelopment) { diff --git a/Views/Shared/_TelegramPremiumFab.cshtml b/Views/Shared/_TelegramPremiumFab.cshtml index 913d322..973f593 100644 --- a/Views/Shared/_TelegramPremiumFab.cshtml +++ b/Views/Shared/_TelegramPremiumFab.cshtml @@ -1,94 +1,51 @@ -@using System.Globalization @using Microsoft.Extensions.Localization @inject IStringLocalizer Localizer @inject Microsoft.Extensions.Configuration.IConfiguration Configuration @{ - var culture = CultureInfo.CurrentUICulture; - var telegramLang = culture.Name.Replace('-', '_'); - var botUsername = Configuration["Telegram:LoginWidgetBotUsername"] ?? string.Empty; - var botId = Configuration["Telegram:BotId"] ?? string.Empty; - var requestAccess = Configuration["Telegram:LoginWidgetRequestAccess"] ?? "write"; + var telegramUrl = Configuration["Support:TelegramUrl"] ?? "https://t.me/jobmakerbr"; + var formConfigured = !string.IsNullOrWhiteSpace(Configuration["Support:FormspreeUrl"]); + var formLink = Url.Action("PremiumContact", "Support"); + var formEnabled = formConfigured && !string.IsNullOrEmpty(formLink); } -
- - -
-
-
@Localizer["TelegramPremiumTitle"]
- -
-
- - -
- - @Localizer["TelegramPremiumStatusLoading"] -
- -
-

@Html.Raw(Localizer["TelegramPremiumStatusConnected", ""])

-
- - -
-
- -
-

@Localizer["TelegramPremiumLoginHint"]

-
-
-
- - -
-
-
-
- -
-
-
-
- -
- -
diff --git a/Views/Support/PremiumContact.cshtml b/Views/Support/PremiumContact.cshtml new file mode 100644 index 0000000..c010bcb --- /dev/null +++ b/Views/Support/PremiumContact.cshtml @@ -0,0 +1,82 @@ +@using System.Globalization +@using Microsoft.Extensions.Localization +@inject IStringLocalizer Localizer +@inject Microsoft.Extensions.Configuration.IConfiguration Configuration + +@{ + + ViewData["Title"] = Localizer["PremiumSupportFormPageTitle"]; + var formAction = Configuration["Support:FormspreeUrl"] ?? "https://formspree.io/f/xpwynqpj"; + var culture = CultureInfo.CurrentUICulture.Name; + Layout = "~/Views/Shared/_Layout.cshtml"; +} + +
+
+
+
+
+

@Localizer["PremiumSupportFormHeading"]

+

@Localizer["PremiumSupportFormDescription"]

+ +
+ + + + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ +

+ @Localizer["PremiumSupportFormPrivacyDisclaimer"] +

+
+
+
+
+
diff --git a/appsettings.Development.json b/appsettings.Development.json index 290425f..9555263 100644 --- a/appsettings.Development.json +++ b/appsettings.Development.json @@ -7,6 +7,10 @@ "TaglineEN": "Generate QR codes in seconds!", "Version": "1.0.0" }, + "Support": { + "TelegramUrl": "https://t.me/jobmakerbr", + "FormspreeUrl": "https://formspree.io/f/xpwynqpj" + }, "ApplicationName": "QRRapido-Dev", "Environment": "Dev", "Serilog": { diff --git a/appsettings.Production.json b/appsettings.Production.json index ad0e2da..c41cb6b 100644 --- a/appsettings.Production.json +++ b/appsettings.Production.json @@ -1,6 +1,10 @@ { "ApplicationName": "QRRapido-Prod", "Environment": "Prod", + "Support": { + "TelegramUrl": "https://t.me/jobmakerbr", + "FormspreeUrl": "https://formspree.io/f/xpwynqpj" + }, "ConnectionStrings": { "MongoDB": "mongodb://admin:c4rn31r0@129.146.116.218:27017,141.148.162.114:27017/QrRapido?replicaSet=rs0&authSource=admin" }, @@ -38,7 +42,11 @@ "DatabaseSizeErrorMB": 5120, "GrowthRateWarningMBPerHour": 100, "IncludeCollectionStats": true, - "CollectionsToMonitor": [ "Users", "QRCodeHistory", "AdFreeSessions" ] + "CollectionsToMonitor": [ + "Users", + "QRCodeHistory", + "AdFreeSessions" + ] }, "HealthChecks": { "MongoDB": { diff --git a/appsettings.json b/appsettings.json index 08b245d..6a3aff2 100644 --- a/appsettings.json +++ b/appsettings.json @@ -10,6 +10,10 @@ "ConnectionStrings": { "MongoDB": "mongodb://localhost:27017/QrRapido" }, + "Support": { + "TelegramUrl": "https://t.me/jobmakerbr", + "FormspreeUrl": "https://formspree.io/f/xpwynqpj" + }, "Authentication": { "Google": { "ClientId": "1080447252222-dqjsu999tvrpb69oj5iapckdh9g8rvha.apps.googleusercontent.com", @@ -105,7 +109,7 @@ }, "Premium": { "FreeQRLimit": 10, - "PremiumPrice": 12.90, + "PremiumPrice": 12.9, "Features": { "UnlimitedQR": true, "DynamicQR": true, @@ -149,7 +153,11 @@ "DatabaseSizeErrorMB": 5120, "GrowthRateWarningMBPerHour": 100, "IncludeCollectionStats": true, - "CollectionsToMonitor": [ "Users", "QRCodeHistory", "AdFreeSessions" ] + "CollectionsToMonitor": [ + "Users", + "QRCodeHistory", + "AdFreeSessions" + ] }, "HealthChecks": { "MongoDB": { @@ -180,4 +188,4 @@ } }, "AllowedHosts": "*" -} +} \ No newline at end of file diff --git a/wwwroot/css/telegram-fab.css b/wwwroot/css/telegram-fab.css index 051aefa..b596aae 100644 --- a/wwwroot/css/telegram-fab.css +++ b/wwwroot/css/telegram-fab.css @@ -1,80 +1,147 @@ -.fab-telegram { +.support-fab-root { position: fixed; - bottom: var(--telegram-fab-offset, 1.5rem); - right: var(--telegram-fab-offset, 1.5rem); - width: 3rem; - height: 3rem; - border-radius: 50%; + bottom: var(--support-fab-offset, 1.5rem); + right: var(--support-fab-offset, 1.5rem); + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 0.75rem; + z-index: 1080; +} + +.support-fab-root .fab-trigger { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + min-width: 3rem; + padding: 0.75rem 1rem; + border-radius: 999px; box-shadow: 0 0.75rem 1.5rem rgba(0, 0, 0, 0.18); - z-index: 1052; opacity: 0.95; backdrop-filter: blur(2px); transition: transform 0.2s ease, opacity 0.2s ease; } -.fab-telegram:hover, -.fab-telegram:focus-visible { +.support-fab-root .fab-trigger:hover, +.support-fab-root .fab-trigger:focus-visible { opacity: 1; transform: translateY(-2px); } -.fab-telegram:focus-visible { +.support-fab-root .fab-trigger:focus-visible { outline: 2px solid rgba(0, 123, 255, 0.6); outline-offset: 2px; } -@media (max-width: 575.98px) { - .fab-telegram { - width: 2.75rem; - height: 2.75rem; - bottom: 1rem; - right: 1rem; - } +.support-fab-root .fab-trigger .fab-trigger-text { + font-weight: 600; } -.telegram-fab-root .toast-container { - z-index: 1080; +.support-fab-menu { + position: relative; + display: none; + width: 240px; + padding: 1rem; + border-radius: 1rem; + background: rgba(17, 24, 39, 0.92); + color: #fff; + box-shadow: 0 1.5rem 3rem rgba(15, 23, 42, 0.45); + backdrop-filter: blur(8px); } -.telegram-fab-loading .spinner-border { - width: 1.5rem; - height: 1.5rem; -} - -.telegram-fab-widget-placeholder { - min-height: 90px; +.support-fab-root.is-open .support-fab-menu { display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.support-fab-menu::before { + content: ""; + position: absolute; + bottom: -8px; + right: 32px; + width: 16px; + height: 16px; + background: inherit; + transform: rotate(45deg); + z-index: 0; + border-radius: 2px; + box-shadow: 0 1.5rem 3rem rgba(15, 23, 42, 0.4); +} + +.support-fab-text { + margin: 0; + font-size: 0.875rem; + color: rgba(255, 255, 255, 0.82); +} + +.support-fab-actions { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.support-fab-link { + display: inline-flex; align-items: center; justify-content: center; + gap: 0.5rem; + border-radius: 999px; + padding: 0.625rem 0.75rem; + transition: transform 0.2s ease, background-color 0.2s ease; } -.telegram-fab-widget-skeleton .placeholder { - display: inline-block; - height: 0.875rem; +.support-fab-link .icon { + font-size: 1rem; } -.telegram-fab-widget-skeleton .placeholder.col-8 { - width: 70%; +.support-fab-link.support-telegram { + background: rgba(59, 130, 246, 0.15); + color: #60a5fa; } -.telegram-fab-widget-skeleton .placeholder.col-6 { - width: 55%; +.support-fab-link.support-telegram:hover, +.support-fab-link.support-telegram:focus-visible { + background: rgba(59, 130, 246, 0.25); + color: #fff; } -.offcanvas-sm-bottom { - --bs-offcanvas-width: min(420px, 90vw); +.support-fab-link.support-form { + background: rgba(249, 115, 22, 0.15); + color: #f97316; } -@media (max-width: 767.98px) { - .offcanvas-sm-bottom { - --bs-offcanvas-width: 100%; - --bs-offcanvas-height: min(80vh, 420px); - --bs-offcanvas-transform: translateY(100%); - border-radius: 1rem 1rem 0 0; - width: 100%; - top: auto; - bottom: 0; - left: 0; - right: 0; +.support-fab-link.support-form:hover, +.support-fab-link.support-form:focus-visible { + background: rgba(249, 115, 22, 0.25); + color: #fff; +} + +.support-fab-link:hover, +.support-fab-link:focus-visible { + transform: translateY(-1px); + text-decoration: none; +} + +.support-fab-link:focus-visible { + outline: 2px solid rgba(255, 255, 255, 0.45); + outline-offset: 2px; +} + +@media (max-width: 575.98px) { + .support-fab-root { + bottom: 1rem; + right: 1rem; + gap: 0.5rem; + } + + .support-fab-root .fab-trigger { + padding: 0.65rem 0.85rem; + font-size: 0.875rem; + } + + .support-fab-menu { + width: min(260px, 80vw); } } diff --git a/wwwroot/js/telegram-fab.js b/wwwroot/js/telegram-fab.js index a909535..e588df8 100644 --- a/wwwroot/js/telegram-fab.js +++ b/wwwroot/js/telegram-fab.js @@ -1,327 +1,80 @@ (function () { - function initTelegramFab() { - const root = document.getElementById('telegramFabRoot'); + function initSupportFab() { + const root = document.querySelector('[data-support-fab]'); if (!root || root.dataset.initialized === 'true') { return; } + const toggle = root.querySelector('[data-support-fab-toggle]'); + const menu = root.querySelector('[data-support-fab-menu]'); + const focusableSelectors = 'a[href], button:not([disabled])'; + + if (!toggle || !menu) { + return; + } + root.dataset.initialized = 'true'; - const dataset = root.dataset; - const offcanvasElement = document.getElementById('telegramPremiumOffcanvas'); - const loadingSection = document.getElementById('telegramFabLoading'); - const connectedSection = document.getElementById('telegramFabConnected'); - const disconnectedSection = document.getElementById('telegramFabDisconnected'); - const alertElement = document.getElementById('telegramFabAlert'); - const retryButton = root.querySelector('.telegram-fab-retry'); - const openButton = root.querySelector('.telegram-fab-open'); - const unlinkButton = root.querySelector('.telegram-fab-unlink'); - const usernameElement = root.querySelector('.telegram-fab-username'); - const widgetPlaceholder = document.getElementById('telegramLoginWidgetPlaceholder'); - const toastContainer = document.getElementById('telegramFabToasts'); - const fabButton = document.getElementById('telegramPremiumFab'); + function openMenu() { + root.classList.add('is-open'); + menu.hidden = false; + toggle.setAttribute('aria-expanded', 'true'); - if (!offcanvasElement || !loadingSection || !connectedSection || !disconnectedSection) { - console.warn('[Telegram FAB] Missing required DOM nodes. Aborting initialization.'); - return; + const firstItem = menu.querySelector(focusableSelectors); + if (firstItem) { + firstItem.focus(); + } } - const offcanvas = bootstrap.Offcanvas.getOrCreateInstance(offcanvasElement); - let currentStatus = null; - let currentDeepLink = null; - let widgetMounted = false; - - const messages = { - loading: dataset.statusLoading || 'Loading...', - error: dataset.statusError || 'Something went wrong.', - connectedTemplate: dataset.statusConnected || 'Connected as {0}', - disconnected: dataset.statusDisconnected || '', - linkSuccess: dataset.linkSuccess || 'Linked successfully.', - unlinkSuccess: dataset.unlinkSuccess || 'Unlinked successfully.', - linkError: dataset.linkError || 'Unable to link. Try again.', - unlinkError: dataset.unlinkError || 'Unable to unlink. Try again.', - retry: dataset.retryLabel || 'Try again', - open: dataset.openLabel || 'Open', - unlink: dataset.unlinkLabel || 'Unlink' - }; - - function toggleSections(state) { - loadingSection.classList.toggle('d-none', state !== 'loading'); - connectedSection.classList.toggle('d-none', state !== 'connected'); - disconnectedSection.classList.toggle('d-none', state !== 'disconnected'); - } - - function showAlert(message) { - if (!alertElement) { + function closeMenu() { + if (!root.classList.contains('is-open')) { return; } - alertElement.textContent = message; - alertElement.classList.remove('d-none'); + root.classList.remove('is-open'); + menu.hidden = true; + toggle.setAttribute('aria-expanded', 'false'); + toggle.focus(); } - function hideAlert() { - if (!alertElement) { - return; + toggle.addEventListener('click', function () { + if (root.classList.contains('is-open')) { + closeMenu(); + } else { + openMenu(); } - - alertElement.classList.add('d-none'); - alertElement.textContent = ''; - } - - function showToast(message, type) { - if (!toastContainer || !message) { - return; - } - - const palette = { - success: 'text-bg-success', - error: 'text-bg-danger', - info: 'text-bg-info' - }; - const toast = document.createElement('div'); - toast.className = `toast align-items-center ${palette[type] || palette.info} border-0`; - toast.role = 'status'; - toast.setAttribute('aria-live', 'polite'); - toast.innerHTML = [ - '
', - `
${message}
`, - '', - '
' - ].join(''); - - toastContainer.appendChild(toast); - - const toastInstance = bootstrap.Toast.getOrCreateInstance(toast, { - delay: 4000, - autohide: true - }); - - toast.addEventListener('hidden.bs.toast', function () { - toast.remove(); - }); - - toastInstance.show(); - } - - function updateConnectedView(username, deepLink) { - toggleSections('connected'); - hideAlert(); - - if (usernameElement) { - usernameElement.textContent = username || ''; - } - - currentDeepLink = deepLink || null; - } - - function updateDisconnectedView() { - toggleSections('disconnected'); - hideAlert(); - - if (!widgetMounted) { - mountLoginWidget(); - } - } - - function applyErrorState(message) { - toggleSections('disconnected'); - showAlert(message || messages.error); - - if (retryButton) { - retryButton.classList.remove('d-none'); - } - } - - async function fetchStatus() { - toggleSections('loading'); - hideAlert(); - - try { - const response = await fetch('/telegram/status', { - method: 'GET', - credentials: 'same-origin', - headers: { - 'Accept': 'application/json' - } - }); - - if (response.status === 401 || response.status === 403) { - if (fabButton) { - fabButton.setAttribute('hidden', 'hidden'); - fabButton.setAttribute('tabindex', '-1'); - } - root.setAttribute('aria-hidden', 'true'); - root.style.display = 'none'; - return; - } - - if (!response.ok) { - throw new Error('status_request_failed'); - } - - currentStatus = await response.json(); - - if (currentStatus && currentStatus.connected) { - updateConnectedView(currentStatus.username || '', currentStatus.deepLink || null); - } else { - updateDisconnectedView(); - } - } catch (error) { - console.warn('[Telegram FAB] Status request failed:', error); - applyErrorState(messages.error); - } - } - - function mountLoginWidget() { - const botUsernameRaw = (dataset.botUsername || '').trim(); - - if (!botUsernameRaw) { - console.warn('[Telegram FAB] Telegram bot username missing. Configure Telegram:LoginWidgetBotUsername.'); - applyErrorState(messages.error); - return; - } - - const botUsername = botUsernameRaw.startsWith('@') - ? botUsernameRaw.slice(1) - : botUsernameRaw; - - if (!widgetPlaceholder) { - return; - } - - widgetPlaceholder.innerHTML = ''; - - const widgetScript = document.createElement('script'); - widgetScript.src = 'https://telegram.org/js/telegram-widget.js?22'; - widgetScript.async = true; - widgetScript.dataset.telegramLogin = botUsername; - widgetScript.dataset.size = 'large'; - widgetScript.dataset.userpic = 'false'; - widgetScript.dataset.requestAccess = dataset.requestAccess || 'write'; - - const lang = (dataset.telegramLang || 'en').replace('-', '_'); - widgetScript.dataset.lang = lang; - - widgetScript.dataset.onauth = 'telegramFabOnAuth'; - - widgetPlaceholder.appendChild(widgetScript); - widgetMounted = true; - } - - async function linkTelegram(payload) { - toggleSections('loading'); - hideAlert(); - - try { - const response = await fetch('/telegram/link', { - method: 'POST', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, - body: JSON.stringify(payload) - }); - - if (!response.ok) { - throw new Error('link_failed'); - } - - showToast(messages.linkSuccess, 'success'); - await fetchStatus(); - } catch (error) { - console.error('[Telegram FAB] Link failed:', error); - showToast(messages.linkError, 'error'); - applyErrorState(messages.linkError); - } - } - - async function unlinkTelegram() { - toggleSections('loading'); - hideAlert(); - - try { - const response = await fetch('/telegram/unlink', { - method: 'POST', - credentials: 'same-origin', - headers: { - 'Accept': 'application/json' - } - }); - - if (!response.ok) { - throw new Error('unlink_failed'); - } - - showToast(messages.unlinkSuccess, 'success'); - widgetMounted = false; - await fetchStatus(); - } catch (error) { - console.error('[Telegram FAB] Unlink failed:', error); - showToast(messages.unlinkError, 'error'); - toggleSections('connected'); - showAlert(messages.unlinkError); - } - } - - offcanvasElement.addEventListener('show.bs.offcanvas', function () { - fetchStatus(); }); - if (retryButton) { - retryButton.addEventListener('click', function () { - hideAlert(); - fetchStatus(); - }); - } - - if (openButton) { - openButton.addEventListener('click', function () { - if (currentDeepLink) { - window.open(currentDeepLink, '_blank', 'noopener'); - } else { - fetchStatus(); - } - }); - } - - if (unlinkButton) { - unlinkButton.addEventListener('click', function () { - unlinkTelegram(); - }); - } - - window.telegramFabOnAuth = function (user) { - if (!user) { - showToast(messages.linkError, 'error'); - return; + toggle.addEventListener('keydown', function (event) { + if (event.key === 'ArrowDown') { + event.preventDefault(); + openMenu(); } + }); - const payload = { - id: user.id, - hash: user.hash, - first_name: user.first_name, - last_name: user.last_name, - username: user.username, - photo_url: user.photo_url, - auth_date: user.auth_date, - bot_id: dataset.botId || null - }; + menu.addEventListener('keydown', function (event) { + if (event.key === 'Escape') { + event.preventDefault(); + closeMenu(); + } + }); - linkTelegram(payload); - }; + menu.querySelectorAll(focusableSelectors).forEach(function (item) { + item.addEventListener('click', closeMenu); + }); - if (fabButton) { - fabButton.addEventListener('keydown', function (event) { - if (event.key === 'Enter' || event.key === ' ') { - event.preventDefault(); - offcanvas.show(); - } - }); - } + document.addEventListener('click', function (event) { + if (!root.contains(event.target)) { + closeMenu(); + } + }); + + document.addEventListener('keydown', function (event) { + if (event.key === 'Escape') { + closeMenu(); + } + }); } - document.addEventListener('DOMContentLoaded', initTelegramFab); - window.initTelegramFab = initTelegramFab; + document.addEventListener('DOMContentLoaded', initSupportFab); })();