first commit
This commit is contained in:
commit
462ad481f1
9
.claude/settings.local.json
Normal file
9
.claude/settings.local.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(dotnet build)"
|
||||||
|
],
|
||||||
|
"deny": [],
|
||||||
|
"ask": []
|
||||||
|
}
|
||||||
|
}
|
||||||
382
.gitignore
vendored
Normal file
382
.gitignore
vendored
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Oo]ut/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/*.HxS
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these files may be disclosed. Comment the next line if you want to checkin
|
||||||
|
# your web deploy settings, but sensitive information contained in these files may
|
||||||
|
# be disclosed. Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.azurePubxml
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment the next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
CConvertLog*.txt
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
||||||
|
|
||||||
|
# Custom
|
||||||
|
appsettings.Local.json
|
||||||
|
appsettings.Production.json
|
||||||
|
*.Development.json
|
||||||
|
logs/
|
||||||
|
uploads/
|
||||||
|
temp/
|
||||||
|
*.env
|
||||||
|
.env.local
|
||||||
|
.env.production
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# Database
|
||||||
|
*.db
|
||||||
|
*.sqlite
|
||||||
|
*.sqlite3
|
||||||
|
|
||||||
|
# Certificates
|
||||||
|
*.pfx
|
||||||
|
*.crt
|
||||||
|
*.key
|
||||||
51
Areas/ImageConverters/Controllers/JpgToWebpController.cs
Normal file
51
Areas/ImageConverters/Controllers/JpgToWebpController.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.Formats.Webp;
|
||||||
|
|
||||||
|
namespace Convert_It_Online.Areas.ImageConverters.Controllers
|
||||||
|
{
|
||||||
|
[Area("ImageConverters")]
|
||||||
|
public class JpgToWebpController : Controller
|
||||||
|
{
|
||||||
|
public IActionResult Index()
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> Convert(IFormFile jpgFile)
|
||||||
|
{
|
||||||
|
if (jpgFile == null || jpgFile.Length == 0)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError("jpgFile", "Por favor, selecione um arquivo.");
|
||||||
|
return View("Index");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validação simples do tipo de arquivo
|
||||||
|
if (jpgFile.ContentType != "image/jpeg")
|
||||||
|
{
|
||||||
|
ModelState.AddModelError("jpgFile", "Arquivo inválido. Por favor, envie um arquivo JPG.");
|
||||||
|
return View("Index");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var imageStream = jpgFile.OpenReadStream();
|
||||||
|
using var image = await Image.LoadAsync(imageStream);
|
||||||
|
|
||||||
|
using var memoryStream = new MemoryStream();
|
||||||
|
await image.SaveAsync(memoryStream, new WebpEncoder());
|
||||||
|
memoryStream.Position = 0;
|
||||||
|
|
||||||
|
var fileName = Path.GetFileNameWithoutExtension(jpgFile.FileName) + ".webp";
|
||||||
|
return File(memoryStream.ToArray(), "image/webp", fileName);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// Log do erro (não implementado aqui)
|
||||||
|
ModelState.AddModelError("jpgFile", "Ocorreu um erro ao processar a imagem.");
|
||||||
|
return View("Index");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
Areas/ImageConverters/Views/JpgToWebp/Index.cshtml
Normal file
22
Areas/ImageConverters/Views/JpgToWebp/Index.cshtml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
@using Microsoft.AspNetCore.Mvc.Localization
|
||||||
|
@inject IViewLocalizer Localizer
|
||||||
|
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = Localizer["PageTitle"];
|
||||||
|
}
|
||||||
|
|
||||||
|
<h1>@Localizer["PageTitle"]</h1>
|
||||||
|
<p>@Localizer["PageDescription"]</p>
|
||||||
|
|
||||||
|
<div class="card mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<form asp-action="Convert" method="post" enctype="multipart/form-data">
|
||||||
|
<div asp-validation-summary="ModelOnly" class="text-danger mb-3"></div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="jpgFile" class="form-label">@Localizer["FileInputLabel"]</label>
|
||||||
|
<input class="form-control" type="file" id="jpgFile" name="jpgFile" accept="image/jpeg" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">@Localizer["ConvertButton"]</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
15
Areas/ImageConverters/Views/JpgToWebp/Index.es-CL.resx
Normal file
15
Areas/ImageConverters/Views/JpgToWebp/Index.es-CL.resx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="PageTitle" xml:space="preserve">
|
||||||
|
<value>Convertir JPG a WebP</value>
|
||||||
|
</data>
|
||||||
|
<data name="PageDescription" xml:space="preserve">
|
||||||
|
<value>Sube una imagen JPG para convertirla al formato WebP.</value>
|
||||||
|
</data>
|
||||||
|
<data name="FileInputLabel" xml:space="preserve">
|
||||||
|
<value>Selecciona el archivo:</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConvertButton" xml:space="preserve">
|
||||||
|
<value>Convertir Ahora</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
15
Areas/ImageConverters/Views/JpgToWebp/Index.es-MX.resx
Normal file
15
Areas/ImageConverters/Views/JpgToWebp/Index.es-MX.resx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="PageTitle" xml:space="preserve">
|
||||||
|
<value>Convertir JPG a WebP</value>
|
||||||
|
</data>
|
||||||
|
<data name="PageDescription" xml:space="preserve">
|
||||||
|
<value>Suba una imagen JPG para convertirla al formato WebP.</value>
|
||||||
|
</data>
|
||||||
|
<data name="FileInputLabel" xml:space="preserve">
|
||||||
|
<value>Seleccione el archivo:</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConvertButton" xml:space="preserve">
|
||||||
|
<value>Convertir Ahora</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
15
Areas/ImageConverters/Views/JpgToWebp/Index.es-PY.resx
Normal file
15
Areas/ImageConverters/Views/JpgToWebp/Index.es-PY.resx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="PageTitle" xml:space="preserve">
|
||||||
|
<value>Convertir JPG a WebP</value>
|
||||||
|
</data>
|
||||||
|
<data name="PageDescription" xml:space="preserve">
|
||||||
|
<value>Sube una imagen JPG para convertirla al formato WebP.</value>
|
||||||
|
</data>
|
||||||
|
<data name="FileInputLabel" xml:space="preserve">
|
||||||
|
<value>Selecciona el archivo:</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConvertButton" xml:space="preserve">
|
||||||
|
<value>Convertir Ahora</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
15
Areas/ImageConverters/Views/JpgToWebp/Index.pt-BR.resx
Normal file
15
Areas/ImageConverters/Views/JpgToWebp/Index.pt-BR.resx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="PageTitle" xml:space="preserve">
|
||||||
|
<value>Converter JPG para WebP</value>
|
||||||
|
</data>
|
||||||
|
<data name="PageDescription" xml:space="preserve">
|
||||||
|
<value>Faça o upload de uma imagem JPG para convertê-la para o formato WebP.</value>
|
||||||
|
</data>
|
||||||
|
<data name="FileInputLabel" xml:space="preserve">
|
||||||
|
<value>Selecione o arquivo:</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConvertButton" xml:space="preserve">
|
||||||
|
<value>Converter Agora</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
5
Areas/ImageConverters/Views/_ViewImports.cshtml
Normal file
5
Areas/ImageConverters/Views/_ViewImports.cshtml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
@using Convert_It_Online
|
||||||
|
@using Microsoft.AspNetCore.Mvc.Localization
|
||||||
|
|
||||||
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
|
@inject IViewLocalizer Localizer
|
||||||
1
Areas/ImageConverters/Views/_ViewStart.cshtml
Normal file
1
Areas/ImageConverters/Views/_ViewStart.cshtml
Normal file
@ -0,0 +1 @@
|
|||||||
|
@{ Layout = "_Layout"; }
|
||||||
71
Areas/TextTools/Controllers/CaseConverterController.cs
Normal file
71
Areas/TextTools/Controllers/CaseConverterController.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Convert_It_Online.Areas.TextTools.Controllers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ViewModel para a ferramenta de conversão de texto.
|
||||||
|
/// </summary>
|
||||||
|
public class CaseConverterViewModel
|
||||||
|
{
|
||||||
|
[Display(Name = "Seu texto")]
|
||||||
|
public string? InputText { get; set; }
|
||||||
|
|
||||||
|
public string? ResultText { get; set; }
|
||||||
|
|
||||||
|
// Usado para saber qual botão foi pressionado no formulário
|
||||||
|
public string? ConversionType { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Area("TextTools")]
|
||||||
|
public class CaseConverterController : Controller
|
||||||
|
{
|
||||||
|
// Método GET: Apenas exibe a página com um formulário vazio.
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult Index()
|
||||||
|
{
|
||||||
|
var model = new CaseConverterViewModel();
|
||||||
|
return View(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Método POST: Recebe o formulário, processa e retorna o resultado.
|
||||||
|
[HttpPost]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
public IActionResult Index([FromForm] CaseConverterViewModel model)
|
||||||
|
{
|
||||||
|
if (!ModelState.IsValid || string.IsNullOrEmpty(model.InputText))
|
||||||
|
{
|
||||||
|
// Se o modelo for inválido ou o texto estiver vazio, retorna a view sem fazer nada.
|
||||||
|
return View(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executa a conversão baseada no valor do botão pressionado
|
||||||
|
model.ResultText = model.ConversionType switch
|
||||||
|
{
|
||||||
|
"upper" => model.InputText.ToUpper(),
|
||||||
|
"lower" => model.InputText.ToLower(),
|
||||||
|
"sentence" => ToSentenceCase(model.InputText),
|
||||||
|
_ => model.InputText // Caso padrão, não faz nada
|
||||||
|
};
|
||||||
|
|
||||||
|
// Retorna a mesma view, agora com o modelo preenchido (InputText e ResultText)
|
||||||
|
return View(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converte uma string para "Sentence case", onde a primeira letra de cada sentença é maiúscula.
|
||||||
|
/// </summary>
|
||||||
|
private string ToSentenceCase(string input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(input)) return input;
|
||||||
|
|
||||||
|
var lowerCase = input.ToLower();
|
||||||
|
// Regex para encontrar o primeiro caractere da string ou o primeiro caractere após um ponto e espaço.
|
||||||
|
var r = new Regex(@"(^[a-z])|\.\s+(.)", RegexOptions.ExplicitCapture);
|
||||||
|
|
||||||
|
return r.Replace(lowerCase, s => s.Value.ToUpper());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
Areas/TextTools/Views/CaseConverter/Index.cshtml
Normal file
32
Areas/TextTools/Views/CaseConverter/Index.cshtml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
@using Microsoft.AspNetCore.Mvc.Localization
|
||||||
|
@inject IViewLocalizer Localizer
|
||||||
|
|
||||||
|
@model Convert_It_Online.Areas.TextTools.Controllers.CaseConverterViewModel
|
||||||
|
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = Localizer["PageTitle"];
|
||||||
|
}
|
||||||
|
|
||||||
|
<h1 class="mb-4">@Localizer["PageTitle"]</h1>
|
||||||
|
|
||||||
|
<form asp-action="Index" method="post">
|
||||||
|
@Html.AntiForgeryToken()
|
||||||
|
<div class="mb-3">
|
||||||
|
<label asp-for="InputText" class="form-label">@Localizer["TextAreaLabel"]</label>
|
||||||
|
<textarea asp-for="InputText" class="form-control" rows="8"></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-wrap gap-2">
|
||||||
|
<button type="submit" name="ConversionType" value="upper" class="btn btn-primary">@Localizer["ToUpperButton"]</button>
|
||||||
|
<button type="submit" name="ConversionType" value="lower" class="btn btn-secondary">@Localizer["ToLowerButton"]</button>
|
||||||
|
<button type="submit" name="ConversionType" value="sentence" class="btn btn-info">@Localizer["ToSentenceCaseButton"]</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
@if (!string.IsNullOrEmpty(Model.ResultText))
|
||||||
|
{
|
||||||
|
<hr class="my-4" />
|
||||||
|
<h2>@Localizer["ResultTitle"]</h2>
|
||||||
|
<textarea asp-for="ResultText" class="form-control" rows="8" readonly="readonly"></textarea>
|
||||||
|
}
|
||||||
21
Areas/TextTools/Views/CaseConverter/Index.es-CL.resx
Normal file
21
Areas/TextTools/Views/CaseConverter/Index.es-CL.resx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="PageTitle" xml:space="preserve">
|
||||||
|
<value>Convertidor de Mayúsculas y Minúsculas</value>
|
||||||
|
</data>
|
||||||
|
<data name="TextAreaLabel" xml:space="preserve">
|
||||||
|
<value>Ingresa tu texto aquí:</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToUpperButton" xml:space="preserve">
|
||||||
|
<value>MAYÚSCULAS</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToLowerButton" xml:space="preserve">
|
||||||
|
<value>minúsculas</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToSentenceCaseButton" xml:space="preserve">
|
||||||
|
<value>Primera Mayúscula</value>
|
||||||
|
</data>
|
||||||
|
<data name="ResultTitle" xml:space="preserve">
|
||||||
|
<value>Resultado</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
21
Areas/TextTools/Views/CaseConverter/Index.es-MX.resx
Normal file
21
Areas/TextTools/Views/CaseConverter/Index.es-MX.resx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="PageTitle" xml:space="preserve">
|
||||||
|
<value>Convertidor de Mayúsculas y Minúsculas</value>
|
||||||
|
</data>
|
||||||
|
<data name="TextAreaLabel" xml:space="preserve">
|
||||||
|
<value>Ingrese su texto aquí:</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToUpperButton" xml:space="preserve">
|
||||||
|
<value>MAYÚSCULAS</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToLowerButton" xml:space="preserve">
|
||||||
|
<value>minúsculas</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToSentenceCaseButton" xml:space="preserve">
|
||||||
|
<value>Primera Mayúscula</value>
|
||||||
|
</data>
|
||||||
|
<data name="ResultTitle" xml:space="preserve">
|
||||||
|
<value>Resultado</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
21
Areas/TextTools/Views/CaseConverter/Index.es-PY.resx
Normal file
21
Areas/TextTools/Views/CaseConverter/Index.es-PY.resx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="PageTitle" xml:space="preserve">
|
||||||
|
<value>Convertidor de Mayúsculas y Minúsculas</value>
|
||||||
|
</data>
|
||||||
|
<data name="TextAreaLabel" xml:space="preserve">
|
||||||
|
<value>Ingresa tu texto aquí:</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToUpperButton" xml:space="preserve">
|
||||||
|
<value>MAYÚSCULAS</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToLowerButton" xml:space="preserve">
|
||||||
|
<value>minúsculas</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToSentenceCaseButton" xml:space="preserve">
|
||||||
|
<value>Primera Mayúscula</value>
|
||||||
|
</data>
|
||||||
|
<data name="ResultTitle" xml:space="preserve">
|
||||||
|
<value>Resultado</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
21
Areas/TextTools/Views/CaseConverter/Index.pt-BR.resx
Normal file
21
Areas/TextTools/Views/CaseConverter/Index.pt-BR.resx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="PageTitle" xml:space="preserve">
|
||||||
|
<value>Conversor de Caixa de Texto</value>
|
||||||
|
</data>
|
||||||
|
<data name="TextAreaLabel" xml:space="preserve">
|
||||||
|
<value>Digite seu texto aqui:</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToUpperButton" xml:space="preserve">
|
||||||
|
<value>MAIÚSCULAS</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToLowerButton" xml:space="preserve">
|
||||||
|
<value>minúsculas</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToSentenceCaseButton" xml:space="preserve">
|
||||||
|
<value>Primeira Maiúscula</value>
|
||||||
|
</data>
|
||||||
|
<data name="ResultTitle" xml:space="preserve">
|
||||||
|
<value>Resultado</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
5
Areas/TextTools/Views/_ViewImports.cshtml
Normal file
5
Areas/TextTools/Views/_ViewImports.cshtml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
@using Convert_It_Online
|
||||||
|
@using Microsoft.AspNetCore.Mvc.Localization
|
||||||
|
|
||||||
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
|
@inject IViewLocalizer Localizer
|
||||||
1
Areas/TextTools/Views/_ViewStart.cshtml
Normal file
1
Areas/TextTools/Views/_ViewStart.cshtml
Normal file
@ -0,0 +1 @@
|
|||||||
|
@{ Layout = "_Layout"; }
|
||||||
44
Controllers/HomeController.cs
Normal file
44
Controllers/HomeController.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Convert_It_Online.Controllers
|
||||||
|
{
|
||||||
|
// ViewModel para representar uma ferramenta no menu da Home
|
||||||
|
public class ToolViewModel
|
||||||
|
{
|
||||||
|
public required string TitleKey { get; set; }
|
||||||
|
public required string DescriptionKey { get; set; }
|
||||||
|
public required string Area { get; set; }
|
||||||
|
public required string Controller { get; set; }
|
||||||
|
public required string IconClass { get; set; } // Propriedade para o ícone
|
||||||
|
public string Action { get; set; } = "Index";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HomeController : Controller
|
||||||
|
{
|
||||||
|
public IActionResult Index()
|
||||||
|
{
|
||||||
|
var availableTools = new List<ToolViewModel>
|
||||||
|
{
|
||||||
|
new ToolViewModel
|
||||||
|
{
|
||||||
|
TitleKey = "TextToolsTitle",
|
||||||
|
DescriptionKey = "TextToolsDescription",
|
||||||
|
Area = "TextTools",
|
||||||
|
Controller = "CaseConverter",
|
||||||
|
IconClass = "bi-fonts"
|
||||||
|
},
|
||||||
|
new ToolViewModel
|
||||||
|
{
|
||||||
|
TitleKey = "ImageToolsTitle",
|
||||||
|
DescriptionKey = "ImageToolsDescription",
|
||||||
|
Area = "ImageConverters",
|
||||||
|
Controller = "JpgToWebp",
|
||||||
|
IconClass = "bi-image-alt"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return View(availableTools);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Convert-It.csproj
Normal file
14
Convert-It.csproj
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<RootNamespace>Convert_It_Online</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
25
Convert-It.sln
Normal file
25
Convert-It.sln
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.14.36414.22 d17.14
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Convert-It", "Convert-It.csproj", "{D8E3BC66-82F6-0019-7082-DF2342D15CEC}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{D8E3BC66-82F6-0019-7082-DF2342D15CEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D8E3BC66-82F6-0019-7082-DF2342D15CEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D8E3BC66-82F6-0019-7082-DF2342D15CEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D8E3BC66-82F6-0019-7082-DF2342D15CEC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {DD63E0A6-3BE6-4B90-8606-3F4BDEB89264}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
64
Program.cs
Normal file
64
Program.cs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using Microsoft.AspNetCore.Localization;
|
||||||
|
using Microsoft.AspNetCore.Localization.Routing;
|
||||||
|
|
||||||
|
// 1. Builder e Serviços
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
|
||||||
|
|
||||||
|
builder.Services.AddControllersWithViews()
|
||||||
|
.AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.Suffix);
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// 2. Configuração de Localização (RequestLocalizationOptions)
|
||||||
|
var supportedCultures = new[] { "pt-BR", "es-MX", "es-CL", "es-PY" };
|
||||||
|
|
||||||
|
var localizationOptions = new RequestLocalizationOptions
|
||||||
|
{
|
||||||
|
DefaultRequestCulture = new RequestCulture("pt-BR"),
|
||||||
|
SupportedCultures = supportedCultures.Select(c => new CultureInfo(c)).ToList(),
|
||||||
|
SupportedUICultures = supportedCultures.Select(c => new CultureInfo(c)).ToList()
|
||||||
|
};
|
||||||
|
|
||||||
|
localizationOptions.RequestCultureProviders.Clear();
|
||||||
|
localizationOptions.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider());
|
||||||
|
|
||||||
|
// 3. Pipeline de Middlewares (na ordem correta)
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseDeveloperExceptionPage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
app.UseExceptionHandler("/Home/Error");
|
||||||
|
app.UseHsts();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
app.UseStaticFiles();
|
||||||
|
|
||||||
|
app.UseRouting();
|
||||||
|
|
||||||
|
app.UseRequestLocalization(localizationOptions);
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
// 4. Mapeamento de Rotas (com cultura)
|
||||||
|
app.MapControllerRoute(
|
||||||
|
name: "areaRoute",
|
||||||
|
pattern: "{culture:length(2,5)}/{area:exists}/{controller=Home}/{action=Index}/{id?}");
|
||||||
|
|
||||||
|
app.MapControllerRoute(
|
||||||
|
name: "default",
|
||||||
|
pattern: "{culture:length(2,5)}/{controller=Home}/{action=Index}/{id?}");
|
||||||
|
|
||||||
|
app.MapFallback(async context =>
|
||||||
|
{
|
||||||
|
context.Response.Redirect("/pt-BR");
|
||||||
|
await Task.CompletedTask;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 5. Execução
|
||||||
|
app.Run();
|
||||||
12
Properties/launchSettings.json
Normal file
12
Properties/launchSettings.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"Convert-It": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
},
|
||||||
|
"applicationUrl": "https://localhost:59345;http://localhost:59346"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
Views/Home/Index.cshtml
Normal file
39
Views/Home/Index.cshtml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
@using Microsoft.AspNetCore.Mvc.Localization
|
||||||
|
@inject IViewLocalizer Localizer
|
||||||
|
|
||||||
|
@model List<Convert_It_Online.Controllers.ToolViewModel>
|
||||||
|
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = Localizer["PageTitle"];
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="text-center mb-5">
|
||||||
|
<h1 class="display-4">@Localizer["PageTitle"]</h1>
|
||||||
|
<p class="lead text-muted">@Localizer["Subtitle"]</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row row-cols-1 row-cols-md-2 g-4">
|
||||||
|
@foreach (var tool in Model)
|
||||||
|
{
|
||||||
|
<div class="col">
|
||||||
|
@* A tag de link envolve todo o card e usa os Tag Helpers para a rota *@
|
||||||
|
<a asp-area="@tool.Area"
|
||||||
|
asp-controller="@tool.Controller"
|
||||||
|
asp-action="@tool.Action"
|
||||||
|
asp-route-culture="@ViewContext.RouteData.Values["culture"]"
|
||||||
|
class="text-decoration-none">
|
||||||
|
|
||||||
|
<div class="card h-100 text-center border-secondary">
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<div class="feature-icon-1 bg-primary bg-gradient text-white fs-1 rounded-3 mb-4 mt-n4">
|
||||||
|
<i class="@tool.IconClass"></i>
|
||||||
|
</div>
|
||||||
|
<h2 class="fs-4 fw-bold">@Localizer[tool.TitleKey]</h2>
|
||||||
|
<p class="mb-0 text-muted">@Localizer[tool.DescriptionKey]</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
21
Views/Home/Index.es-CL.resx
Normal file
21
Views/Home/Index.es-CL.resx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="PageTitle" xml:space="preserve">
|
||||||
|
<value>Tus Herramientas de Conversión</value>
|
||||||
|
</data>
|
||||||
|
<data name="Subtitle" xml:space="preserve">
|
||||||
|
<value>Soluciones rápidas y fáciles para tu día a día</value>
|
||||||
|
</data>
|
||||||
|
<data name="TextToolsTitle" xml:space="preserve">
|
||||||
|
<value>Herramientas de Texto</value>
|
||||||
|
</data>
|
||||||
|
<data name="TextToolsDescription" xml:space="preserve">
|
||||||
|
<value>Convierte, formatea y manipula textos fácilmente.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ImageToolsTitle" xml:space="preserve">
|
||||||
|
<value>Convertidores de Imagen</value>
|
||||||
|
</data>
|
||||||
|
<data name="ImageToolsDescription" xml:space="preserve">
|
||||||
|
<value>Optimiza y convierte imágenes a cualquier formato.</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
21
Views/Home/Index.es-MX.resx
Normal file
21
Views/Home/Index.es-MX.resx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="PageTitle" xml:space="preserve">
|
||||||
|
<value>Sus Herramientas de Conversión</value>
|
||||||
|
</data>
|
||||||
|
<data name="Subtitle" xml:space="preserve">
|
||||||
|
<value>Soluciones rápidas y fáciles para su día a día</value>
|
||||||
|
</data>
|
||||||
|
<data name="TextToolsTitle" xml:space="preserve">
|
||||||
|
<value>Herramientas de Texto</value>
|
||||||
|
</data>
|
||||||
|
<data name="TextToolsDescription" xml:space="preserve">
|
||||||
|
<value>Convierta, formatee y manipule textos fácilmente.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ImageToolsTitle" xml:space="preserve">
|
||||||
|
<value>Convertidores de Imagen</value>
|
||||||
|
</data>
|
||||||
|
<data name="ImageToolsDescription" xml:space="preserve">
|
||||||
|
<value>Optimice y convierta imágenes para cualquier formato.</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
21
Views/Home/Index.es-PY.resx
Normal file
21
Views/Home/Index.es-PY.resx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="PageTitle" xml:space="preserve">
|
||||||
|
<value>Tus Herramientas de Conversión</value>
|
||||||
|
</data>
|
||||||
|
<data name="Subtitle" xml:space="preserve">
|
||||||
|
<value>Soluciones rápidas y fáciles para tu día a día</value>
|
||||||
|
</data>
|
||||||
|
<data name="TextToolsTitle" xml:space="preserve">
|
||||||
|
<value>Herramientas de Texto</value>
|
||||||
|
</data>
|
||||||
|
<data name="TextToolsDescription" xml:space="preserve">
|
||||||
|
<value>Convierte, formatea y manipula textos fácilmente.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ImageToolsTitle" xml:space="preserve">
|
||||||
|
<value>Convertidores de Imagen</value>
|
||||||
|
</data>
|
||||||
|
<data name="ImageToolsDescription" xml:space="preserve">
|
||||||
|
<value>Optimiza y convierte imágenes a cualquier formato.</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
21
Views/Home/Index.pt-BR.resx
Normal file
21
Views/Home/Index.pt-BR.resx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="PageTitle" xml:space="preserve">
|
||||||
|
<value>Suas Ferramentas de Conversão</value>
|
||||||
|
</data>
|
||||||
|
<data name="Subtitle" xml:space="preserve">
|
||||||
|
<value>Soluções rápidas e fáceis para o seu dia a dia</value>
|
||||||
|
</data>
|
||||||
|
<data name="TextToolsTitle" xml:space="preserve">
|
||||||
|
<value>Ferramentas de Texto</value>
|
||||||
|
</data>
|
||||||
|
<data name="TextToolsDescription" xml:space="preserve">
|
||||||
|
<value>Converta, formate e manipule textos facilmente.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ImageToolsTitle" xml:space="preserve">
|
||||||
|
<value>Conversores de Imagem</value>
|
||||||
|
</data>
|
||||||
|
<data name="ImageToolsDescription" xml:space="preserve">
|
||||||
|
<value>Otimize e converta imagens para qualquer formato.</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
90
Views/Shared/_Layout.cshtml
Normal file
90
Views/Shared/_Layout.cshtml
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
@using Microsoft.AspNetCore.Localization
|
||||||
|
@using Microsoft.Extensions.Options
|
||||||
|
@using Microsoft.AspNetCore.Mvc.Localization
|
||||||
|
|
||||||
|
@inject IOptions<RequestLocalizationOptions> LocOptions
|
||||||
|
@inject IViewLocalizer Localizer
|
||||||
|
|
||||||
|
@{
|
||||||
|
var requestCulture = Context.Features.Get<IRequestCultureFeature>();
|
||||||
|
var supportedCultures = LocOptions.Value.SupportedCultures;
|
||||||
|
}
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="@requestCulture?.RequestCulture.UICulture.Name" data-bs-theme="dark">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>@ViewData["Title"] - Convert-It Online</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootswatch@5.3.3/dist/cyborg/bootstrap.min.css" />
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||||
|
<link rel="stylesheet" href="~/css/site.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<nav class="navbar navbar-expand-lg bg-primary" data-bs-theme="dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index" asp-route-culture="@requestCulture?.RequestCulture.UICulture.Name">Convert-It Online</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarColor01">
|
||||||
|
<ul class="navbar-nav me-auto">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" asp-area="" asp-controller="Home" asp-action="Index" asp-route-culture="@requestCulture?.RequestCulture.UICulture.Name">@Localizer["HomeLink"]</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="btn btn-secondary dropdown-toggle" type="button" id="languageDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-translate me-2"></i>
|
||||||
|
@requestCulture?.RequestCulture.UICulture.NativeName
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="languageDropdown">
|
||||||
|
@foreach (var culture in supportedCultures!)
|
||||||
|
{
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item"
|
||||||
|
asp-controller="@ViewContext.RouteData.Values["controller"]"
|
||||||
|
asp-action="@ViewContext.RouteData.Values["action"]"
|
||||||
|
asp-all-route-data="@Context.Request.Query.ToDictionary(p => p.Key, p => p.Value.ToString())"
|
||||||
|
asp-route-culture="@culture.Name">
|
||||||
|
@culture.NativeName
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="container mt-4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-9">
|
||||||
|
<div class="ad-placeholder ad-top d-none d-lg-flex">
|
||||||
|
<span>Ad Placeholder (Top)</span>
|
||||||
|
</div>
|
||||||
|
<main role="main" class="pb-3">
|
||||||
|
@RenderBody()
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 d-none d-lg-block">
|
||||||
|
<div class="ad-placeholder ad-side">
|
||||||
|
<span>Ad Placeholder (Side)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer mt-auto py-3 bg-dark">
|
||||||
|
<div class="container text-center">
|
||||||
|
<span class="text-muted">@Localizer["FooterText"]</span>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
@await RenderSectionAsync("Scripts", required: false)
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
9
Views/Shared/_Layout.es-CL.resx
Normal file
9
Views/Shared/_Layout.es-CL.resx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="HomeLink" xml:space="preserve">
|
||||||
|
<value>Inicio</value>
|
||||||
|
</data>
|
||||||
|
<data name="FooterText" xml:space="preserve">
|
||||||
|
<value>© 2025 - Convert-It Online</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
9
Views/Shared/_Layout.es-MX.resx
Normal file
9
Views/Shared/_Layout.es-MX.resx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="HomeLink" xml:space="preserve">
|
||||||
|
<value>Inicio</value>
|
||||||
|
</data>
|
||||||
|
<data name="FooterText" xml:space="preserve">
|
||||||
|
<value>© 2025 - Convert-It Online</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
9
Views/Shared/_Layout.es-PY.resx
Normal file
9
Views/Shared/_Layout.es-PY.resx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="HomeLink" xml:space="preserve">
|
||||||
|
<value>Inicio</value>
|
||||||
|
</data>
|
||||||
|
<data name="FooterText" xml:space="preserve">
|
||||||
|
<value>© 2025 - Convert-It Online</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
9
Views/Shared/_Layout.pt-BR.resx
Normal file
9
Views/Shared/_Layout.pt-BR.resx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="HomeLink" xml:space="preserve">
|
||||||
|
<value>Início</value>
|
||||||
|
</data>
|
||||||
|
<data name="FooterText" xml:space="preserve">
|
||||||
|
<value>© 2025 - Convert-It Online</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
5
Views/_ViewImports.cshtml
Normal file
5
Views/_ViewImports.cshtml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
@using Convert_It_Online
|
||||||
|
@using Microsoft.AspNetCore.Mvc.Localization
|
||||||
|
|
||||||
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
|
@inject IViewLocalizer Localizer
|
||||||
3
Views/_ViewStart.cshtml
Normal file
3
Views/_ViewStart.cshtml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
@{
|
||||||
|
Layout = "_Layout";
|
||||||
|
}
|
||||||
224
wwwroot/css/site.css
Normal file
224
wwwroot/css/site.css
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
/* ========== TEMA ESCURO PERSONALIZADO ========== */
|
||||||
|
:root {
|
||||||
|
--primary-gradient: linear-gradient(135deg, #007bff 0%, #0056b3 100%);
|
||||||
|
--card-bg: rgba(255, 255, 255, 0.05);
|
||||||
|
--card-border: rgba(255, 255, 255, 0.1);
|
||||||
|
--text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
--box-shadow: 0 8px 32px rgba(0, 123, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== LAYOUT PRINCIPAL ========== */
|
||||||
|
body {
|
||||||
|
background: linear-gradient(135deg, #0a1929 0%, #1a2332 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar {
|
||||||
|
background: var(--primary-gradient) !important;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 123, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-brand {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
text-shadow: var(--text-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== CARDS MODERNOS ========== */
|
||||||
|
.card {
|
||||||
|
background: var(--card-bg);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid var(--card-border);
|
||||||
|
box-shadow: var(--box-shadow);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover {
|
||||||
|
transform: translateY(-8px);
|
||||||
|
box-shadow: 0 12px 40px rgba(0, 123, 255, 0.25);
|
||||||
|
border-color: rgba(0, 123, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card a:hover {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== ÍCONES DOS CARDS ========== */
|
||||||
|
.feature-icon-1 {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 4rem;
|
||||||
|
width: 4rem;
|
||||||
|
background: var(--primary-gradient) !important;
|
||||||
|
box-shadow: 0 8px 16px rgba(0, 123, 255, 0.3);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-icon-1::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -50%;
|
||||||
|
left: -50%;
|
||||||
|
width: 200%;
|
||||||
|
height: 200%;
|
||||||
|
background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.1), transparent);
|
||||||
|
transition: all 0.6s ease;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover .feature-icon-1::before {
|
||||||
|
opacity: 1;
|
||||||
|
animation: shimmer 1s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shimmer {
|
||||||
|
0% { transform: translateX(-100%) rotate(45deg); }
|
||||||
|
100% { transform: translateX(100%) rotate(45deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== TÍTULOS E TEXTOS ========== */
|
||||||
|
.display-4 {
|
||||||
|
font-weight: 800;
|
||||||
|
background: var(--primary-gradient);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
text-shadow: none;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lead {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card h2 {
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card p {
|
||||||
|
opacity: 0.85;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== DROPDOWN DE IDIOMAS ========== */
|
||||||
|
.dropdown-toggle {
|
||||||
|
background: rgba(255, 255, 255, 0.1) !important;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2) !important;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-toggle:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.2) !important;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
background: rgba(33, 37, 41, 0.95) !important;
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item {
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item:hover {
|
||||||
|
background: rgba(0, 123, 255, 0.2) !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== FOOTER ========== */
|
||||||
|
.footer {
|
||||||
|
background: linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%) !important;
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== PLACEHOLDERS DE ANÚNCIO ========== */
|
||||||
|
.ad-placeholder {
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
border: 2px dashed rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 1rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
font-size: 1rem;
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ad-placeholder:hover {
|
||||||
|
border-color: rgba(0, 123, 255, 0.3);
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ad-top {
|
||||||
|
min-height: 90px;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ad-side {
|
||||||
|
min-height: 600px;
|
||||||
|
position: sticky;
|
||||||
|
top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== RESPONSIVIDADE ========== */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.display-4 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lead {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-icon-1 {
|
||||||
|
height: 3rem;
|
||||||
|
width: 3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== ANIMAÇÕES SUAVES ========== */
|
||||||
|
* {
|
||||||
|
transition: color 0.2s ease, background-color 0.2s ease, border-color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
animation: fadeInUp 0.6s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(30px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user