Compare commits
2 Commits
6749da8d4e
...
0e7e3d552e
| Author | SHA1 | Date | |
|---|---|---|---|
| 0e7e3d552e | |||
| 127424fc70 |
@ -35,7 +35,8 @@
|
|||||||
"Bash(ss:*)",
|
"Bash(ss:*)",
|
||||||
"Bash(lsof:*)",
|
"Bash(lsof:*)",
|
||||||
"Bash(dotnet run:*)",
|
"Bash(dotnet run:*)",
|
||||||
"Bash(dotnet user-secrets:*)"
|
"Bash(dotnet user-secrets:*)",
|
||||||
|
"Bash(xargs grep:*)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"enableAllProjectMcpServers": false
|
"enableAllProjectMcpServers": false
|
||||||
|
|||||||
@ -29,4 +29,21 @@ public class TenantSettings
|
|||||||
// SEO / Layout
|
// SEO / Layout
|
||||||
public string MetaKeywords { get; set; } = "cartão digital, página de links, bio links, linktree brasil, página profissional";
|
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.";
|
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();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -626,7 +626,7 @@ app.Use(async (context, next) =>
|
|||||||
"frame-src 'self' https://accounts.google.com https://login.microsoftonline.com; " +
|
"frame-src 'self' https://accounts.google.com https://login.microsoftonline.com; " +
|
||||||
"object-src 'none'; " +
|
"object-src 'none'; " +
|
||||||
"base-uri 'self'; " +
|
"base-uri 'self'; " +
|
||||||
"form-action 'self'";
|
"form-action 'self' https://accounts.google.com https://login.microsoftonline.com";
|
||||||
context.Response.Headers.Append("Content-Security-Policy", csp);
|
context.Response.Headers.Append("Content-Security-Policy", csp);
|
||||||
|
|
||||||
// Load balancer e debugging headers
|
// Load balancer e debugging headers
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
|
using BCards.Web.Configuration;
|
||||||
using BCards.Web.Models;
|
using BCards.Web.Models;
|
||||||
using BCards.Web.Repositories;
|
using BCards.Web.Repositories;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -10,10 +12,12 @@ namespace BCards.Web.Services;
|
|||||||
public class CategoryService : ICategoryService
|
public class CategoryService : ICategoryService
|
||||||
{
|
{
|
||||||
private readonly ICategoryRepository _categoryRepository;
|
private readonly ICategoryRepository _categoryRepository;
|
||||||
|
private readonly TenantSettings _tenant;
|
||||||
|
|
||||||
public CategoryService(ICategoryRepository categoryRepository)
|
public CategoryService(ICategoryRepository categoryRepository, IOptions<TenantSettings> tenantOptions)
|
||||||
{
|
{
|
||||||
_categoryRepository = categoryRepository;
|
_categoryRepository = categoryRepository;
|
||||||
|
_tenant = tenantOptions.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Category>> GetAllCategoriesAsync()
|
public async Task<List<Category>> GetAllCategoriesAsync()
|
||||||
@ -57,6 +61,23 @@ public class CategoryService : ICategoryService
|
|||||||
var categories = await _categoryRepository.GetAllActiveAsync();
|
var categories = await _categoryRepository.GetAllActiveAsync();
|
||||||
if (categories.Any()) return;
|
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[]
|
var defaultCategories = new[]
|
||||||
{
|
{
|
||||||
new Category
|
new Category
|
||||||
|
|||||||
@ -43,7 +43,30 @@
|
|||||||
<link rel="icon" type="image/x-icon" href="~/favicon.ico" />
|
<link rel="icon" type="image/x-icon" href="~/favicon.ico" />
|
||||||
|
|
||||||
@await RenderSectionAsync("Styles", required: false)
|
@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">
|
<script type="text/javascript">
|
||||||
(function(c,l,a,r,i,t,y){
|
(function(c,l,a,r,i,t,y){
|
||||||
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
|
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
|
||||||
|
|||||||
@ -32,6 +32,19 @@
|
|||||||
"CtaButtonText": "Criar Minha Bio",
|
"CtaButtonText": "Criar Minha Bio",
|
||||||
"MetaKeywords": "bio links criadora, creator bio, linktree conteudo adulto, links onlyfans, bio instagram criadora",
|
"MetaKeywords": "bio links criadora, creator bio, linktree conteudo adulto, links onlyfans, bio instagram criadora",
|
||||||
"FooterTagline": "Seu conteúdo, sua identidade.",
|
"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": [
|
"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-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" },
|
{ "Icon": "fas fa-envelope", "Label": "✉️ Email", "Prefix": "mailto:", "Placeholder": "seuemail@exemplo.com", "Instructions": "Digite apenas o email", "Color": "bg-success" },
|
||||||
|
|||||||
@ -147,7 +147,7 @@
|
|||||||
},
|
},
|
||||||
"Microsoft": {
|
"Microsoft": {
|
||||||
"ClientId": "b411606a-e574-4f59-b7cd-10dd941b9fa3",
|
"ClientId": "b411606a-e574-4f59-b7cd-10dd941b9fa3",
|
||||||
"ClientSecret": ".v88Q~2UIFu926J9lETzY_dY16Wqxo0QvYECjdvx"
|
"ClientSecret": "bff10c42-f1e5-487b-bacb-16b1b691aa7d"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Moderation": {
|
"Moderation": {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user