142 lines
6.5 KiB
C#
142 lines
6.5 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Extensions.Localization;
|
|
using QRRapidoApp.Services;
|
|
using System.Security.Claims;
|
|
|
|
namespace QRRapidoApp.Controllers
|
|
{
|
|
public class TutoriaisController : Controller
|
|
{
|
|
private readonly IMarkdownService _markdownService;
|
|
private readonly AdDisplayService _adDisplayService;
|
|
private readonly ILogger<TutoriaisController> _logger;
|
|
private readonly IStringLocalizer<QRRapidoApp.Resources.SharedResource> _localizer;
|
|
private readonly IConfiguration _config;
|
|
|
|
public TutoriaisController(
|
|
IMarkdownService markdownService,
|
|
AdDisplayService adDisplayService,
|
|
ILogger<TutoriaisController> logger,
|
|
IStringLocalizer<QRRapidoApp.Resources.SharedResource> localizer,
|
|
IConfiguration config)
|
|
{
|
|
_markdownService = markdownService;
|
|
_adDisplayService = adDisplayService;
|
|
_logger = logger;
|
|
_localizer = localizer;
|
|
_config = config;
|
|
}
|
|
|
|
// Portuguese: /tutoriais/{slug} (canonical, no prefix)
|
|
// Spanish: /es-PY/tutoriais/{slug}
|
|
// English: /en/tutoriais/{slug}
|
|
[Route("tutoriais/{slug}")]
|
|
[Route("es-PY/tutoriais/{slug}")]
|
|
[Route("es/tutoriais/{slug}")]
|
|
[Route("en/tutoriais/{slug}")]
|
|
public async Task<IActionResult> Article(string slug, string? culture = null)
|
|
{
|
|
try
|
|
{
|
|
// Determine culture from URL path if not provided
|
|
var reqPath = Request.Path.Value ?? "";
|
|
culture ??= reqPath.StartsWith("/es-PY", StringComparison.OrdinalIgnoreCase) ? "es-PY"
|
|
: reqPath.StartsWith("/es/", StringComparison.OrdinalIgnoreCase) ? "es"
|
|
: reqPath.StartsWith("/en/", StringComparison.OrdinalIgnoreCase) ? "en"
|
|
: "pt-BR";
|
|
|
|
var article = await _markdownService.GetArticleAsync(slug, culture);
|
|
|
|
if (article == null)
|
|
{
|
|
_logger.LogWarning("Article not found: {Slug} ({Culture})", slug, culture);
|
|
return NotFound();
|
|
}
|
|
|
|
// Set ViewBag for ads and user info
|
|
var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
ViewBag.ShowAds = await _adDisplayService.ShouldShowAds(userId);
|
|
ViewBag.IsPremium = await _adDisplayService.HasValidPremiumSubscription(userId ?? "");
|
|
ViewBag.IsAuthenticated = User.Identity?.IsAuthenticated ?? false;
|
|
ViewBag.UserName = User.Identity?.Name ?? "";
|
|
_adDisplayService.SetViewBagAds(ViewBag);
|
|
|
|
// Set SEO metadata from article
|
|
ViewBag.Title = article.Metadata.Title;
|
|
ViewBag.Description = article.Metadata.Description;
|
|
ViewBag.Keywords = article.Metadata.Keywords;
|
|
ViewBag.OgImage = article.Metadata.Image;
|
|
ViewBag.OgType = "article";
|
|
ViewBag.ArticleAuthor = article.Metadata.Author;
|
|
ViewBag.ArticlePublishedTime = article.Metadata.Date.ToString("yyyy-MM-ddTHH:mm:ssZ");
|
|
ViewBag.ArticleModifiedTime = article.Metadata.LastMod.ToString("yyyy-MM-ddTHH:mm:ssZ");
|
|
ViewBag.Culture = culture;
|
|
ViewBag.Slug = slug;
|
|
|
|
// Get related articles (same culture, exclude current)
|
|
var allArticles = await _markdownService.GetAllArticlesAsync(culture);
|
|
article.RelatedArticles = allArticles
|
|
.Where(a => a.Title != article.Metadata.Title)
|
|
.Take(3)
|
|
.ToList();
|
|
|
|
_logger.LogInformation("Serving article: {Slug} ({Culture})", slug, culture);
|
|
return View(article);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error serving article: {Slug} ({Culture})", slug, culture);
|
|
return StatusCode(500, "Internal server error");
|
|
}
|
|
}
|
|
|
|
// Portuguese: /tutoriais (canonical, no prefix)
|
|
// Spanish: /es-PY/tutoriais
|
|
// English: /en/tutoriais
|
|
[Route("tutoriais")]
|
|
[Route("es-PY/tutoriais")]
|
|
[Route("es/tutoriais")]
|
|
[Route("en/tutoriais")]
|
|
public async Task<IActionResult> Index(string? culture = null)
|
|
{
|
|
try
|
|
{
|
|
// Determine culture from URL path if not provided
|
|
var reqPath = Request.Path.Value ?? "";
|
|
culture ??= reqPath.StartsWith("/es-PY", StringComparison.OrdinalIgnoreCase) ? "es-PY"
|
|
: reqPath.StartsWith("/es/", StringComparison.OrdinalIgnoreCase) ? "es"
|
|
: reqPath.StartsWith("/en/", StringComparison.OrdinalIgnoreCase) ? "en"
|
|
: "pt-BR";
|
|
|
|
var articles = await _markdownService.GetAllArticlesAsync(culture);
|
|
|
|
// Set ViewBag
|
|
var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
ViewBag.ShowAds = await _adDisplayService.ShouldShowAds(userId);
|
|
ViewBag.IsPremium = await _adDisplayService.HasValidPremiumSubscription(userId ?? "");
|
|
ViewBag.IsAuthenticated = User.Identity?.IsAuthenticated ?? false;
|
|
ViewBag.UserName = User.Identity?.Name ?? "";
|
|
_adDisplayService.SetViewBagAds(ViewBag);
|
|
|
|
ViewBag.Title = culture == "pt-BR" ? "Tutoriais QR Code"
|
|
: culture == "en" ? "QR Code Tutorials"
|
|
: "Tutoriales Código QR";
|
|
ViewBag.Description = culture == "pt-BR"
|
|
? "Aprenda a criar e usar QR Codes com nossos tutoriais completos"
|
|
: culture == "en"
|
|
? "Learn how to create and use QR Codes with our complete step-by-step tutorials"
|
|
: "Aprende a crear y usar códigos QR con nuestros tutoriales completos";
|
|
ViewBag.Culture = culture;
|
|
|
|
_logger.LogInformation("Serving tutorials index ({Culture}): {Count} articles", culture, articles.Count);
|
|
return View(articles);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error serving tutorials index ({Culture})", culture);
|
|
return StatusCode(500, "Internal server error");
|
|
}
|
|
}
|
|
}
|
|
}
|