Compare commits

..

No commits in common. "0e7e3d552e066aaccecbaaa9325d1e6c7650c289" and "6749da8d4e4974400fd5ee05add4ef557ab7ca75" have entirely different histories.

7 changed files with 5 additions and 80 deletions

View File

@ -35,8 +35,7 @@
"Bash(ss:*)",
"Bash(lsof:*)",
"Bash(dotnet run:*)",
"Bash(dotnet user-secrets:*)",
"Bash(xargs grep:*)"
"Bash(dotnet user-secrets:*)"
]
},
"enableAllProjectMcpServers": false

View File

@ -29,21 +29,4 @@ public class TenantSettings
// SEO / Layout
public string MetaKeywords { get; set; } = "cartão digital, página de links, bio links, linktree brasil, página profissional";
public string FooterTagline { get; set; } = "Sua presença online, simplificada.";
// Branding / Colors
public string HeroGradient { get; set; } = "linear-gradient(135deg, #667eea 0%, #764ba2 100%)";
public string PrimaryColor { get; set; } = "#0d6efd";
public string PrimaryColorDark { get; set; } = "#0a58ca";
// Category seeding (se vazio, usa os padrões do BCards)
public List<CategorySeedItem> DefaultCategories { get; set; } = new();
}
public class CategorySeedItem
{
public string Name { get; set; } = "";
public string Slug { get; set; } = "";
public string Icon { get; set; } = "";
public string Description { get; set; } = "";
public List<string> SeoKeywords { get; set; } = new();
}

View File

@ -626,7 +626,7 @@ app.Use(async (context, next) =>
"frame-src 'self' https://accounts.google.com https://login.microsoftonline.com; " +
"object-src 'none'; " +
"base-uri 'self'; " +
"form-action 'self' https://accounts.google.com https://login.microsoftonline.com";
"form-action 'self'";
context.Response.Headers.Append("Content-Security-Policy", csp);
// Load balancer e debugging headers

View File

@ -1,7 +1,5 @@
using BCards.Web.Configuration;
using BCards.Web.Models;
using BCards.Web.Repositories;
using Microsoft.Extensions.Options;
using System.Text.RegularExpressions;
using System.Globalization;
using System.Text;
@ -12,12 +10,10 @@ namespace BCards.Web.Services;
public class CategoryService : ICategoryService
{
private readonly ICategoryRepository _categoryRepository;
private readonly TenantSettings _tenant;
public CategoryService(ICategoryRepository categoryRepository, IOptions<TenantSettings> tenantOptions)
public CategoryService(ICategoryRepository categoryRepository)
{
_categoryRepository = categoryRepository;
_tenant = tenantOptions.Value;
}
public async Task<List<Category>> GetAllCategoriesAsync()
@ -61,23 +57,6 @@ public class CategoryService : ICategoryService
var categories = await _categoryRepository.GetAllActiveAsync();
if (categories.Any()) return;
// Usa categorias configuradas no tenant se disponíveis
if (_tenant.DefaultCategories.Any())
{
foreach (var item in _tenant.DefaultCategories)
{
await _categoryRepository.CreateAsync(new Category
{
Name = item.Name,
Slug = string.IsNullOrWhiteSpace(item.Slug) ? GenerateSlug(item.Name) : item.Slug,
Icon = item.Icon,
Description = item.Description,
SeoKeywords = item.SeoKeywords
});
}
return;
}
var defaultCategories = new[]
{
new Category

View File

@ -44,29 +44,6 @@
@await RenderSectionAsync("Styles", required: false)
<style>
:root {
--tenant-primary: @tenant.PrimaryColor;
--tenant-primary-dark: @tenant.PrimaryColorDark;
--tenant-gradient: @tenant.HeroGradient;
}
.hero-section { background: var(--tenant-gradient) !important; }
.bg-home-blue { background: var(--tenant-gradient) !important; }
.bg-home-blue .navbar-collapse { background-color: color-mix(in srgb, var(--tenant-primary) 80%, black) !important; }
.btn-primary { background-color: var(--tenant-primary) !important; border-color: var(--tenant-primary) !important; }
.btn-primary:hover { background-color: var(--tenant-primary-dark) !important; border-color: var(--tenant-primary-dark) !important; }
.btn-outline-primary { color: var(--tenant-primary) !important; border-color: var(--tenant-primary) !important; }
.btn-outline-primary:hover { background-color: var(--tenant-primary) !important; color: #fff !important; }
.text-primary { color: var(--tenant-primary) !important; }
.bg-primary { background-color: var(--tenant-primary) !important; }
.border-primary { border-color: var(--tenant-primary) !important; }
.bg-primary.bg-opacity-10 { background-color: color-mix(in srgb, var(--tenant-primary) 10%, transparent) !important; }
#loading-bar { background: linear-gradient(90deg, var(--tenant-primary), var(--tenant-primary-dark), var(--tenant-primary)) !important; }
.nav-link.active { background-color: color-mix(in srgb, var(--tenant-primary) 10%, transparent) !important; }
.form-control:focus { border-color: var(--tenant-primary); box-shadow: 0 0 0 0.2rem color-mix(in srgb, var(--tenant-primary) 25%, transparent); }
.profile-image-placeholder { border-color: var(--tenant-primary) !important; }
</style>
<script type="text/javascript">
(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};

View File

@ -32,19 +32,6 @@
"CtaButtonText": "Criar Minha Bio",
"MetaKeywords": "bio links criadora, creator bio, linktree conteudo adulto, links onlyfans, bio instagram criadora",
"FooterTagline": "Seu conteúdo, sua identidade.",
"HeroGradient": "linear-gradient(135deg, #ff416c 0%, #c0392b 100%)",
"PrimaryColor": "#e63946",
"PrimaryColorDark": "#c1121f",
"DefaultCategories": [
{ "Icon": "📸", "Name": "Modelos", "Slug": "modelos", "Description": "Modelos e criadores de conteúdo visual", "SeoKeywords": ["modelo", "fotografia", "conteúdo", "criadora"] },
{ "Icon": "⭐", "Name": "Influencers", "Slug": "influencers", "Description": "Influencers e personalidades digitais", "SeoKeywords": ["influencer", "digital", "social media"] },
{ "Icon": "💪", "Name": "Fitness", "Slug": "fitness", "Description": "Criadores de conteúdo fitness e lifestyle", "SeoKeywords": ["fitness", "academia", "saúde", "corpo"] },
{ "Icon": "🎨", "Name": "Arte", "Slug": "arte", "Description": "Artistas e criadores de conteúdo visual", "SeoKeywords": ["arte", "ilustração", "design", "criativo"] },
{ "Icon": "🎵", "Name": "Música", "Slug": "musica", "Description": "Músicos e cantores independentes", "SeoKeywords": ["música", "cantor", "artista", "show"] },
{ "Icon": "🎮", "Name": "Gaming", "Slug": "gaming", "Description": "Streamers e criadores de conteúdo gamer", "SeoKeywords": ["gaming", "streamer", "games", "twitch"] },
{ "Icon": "🦸", "Name": "Cosplay", "Slug": "cosplay", "Description": "Cosplayers e criadores de fantasia", "SeoKeywords": ["cosplay", "anime", "fantasia", "cosplayer"] },
{ "Icon": "💋", "Name": "Lifestyle", "Slug": "lifestyle", "Description": "Criadores de conteúdo lifestyle e entretenimento", "SeoKeywords": ["lifestyle", "entretenimento", "diversão"] }
],
"AllowedLinkTypes": [
{ "Icon": "fas fa-globe", "Label": "🌐 Site Geral", "Prefix": "https://", "Placeholder": "exemplo.com", "Instructions": "Digite o domínio e caminho", "Color": "bg-primary" },
{ "Icon": "fas fa-envelope", "Label": "✉️ Email", "Prefix": "mailto:", "Placeholder": "seuemail@exemplo.com", "Instructions": "Digite apenas o email", "Color": "bg-success" },

View File

@ -147,7 +147,7 @@
},
"Microsoft": {
"ClientId": "b411606a-e574-4f59-b7cd-10dd941b9fa3",
"ClientSecret": "bff10c42-f1e5-487b-bacb-16b1b691aa7d"
"ClientSecret": ".v88Q~2UIFu926J9lETzY_dY16Wqxo0QvYECjdvx"
}
},
"Moderation": {