Docker + Jenkfins File + v0.1
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
EXPOSE 443
|
EXPOSE 443
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
|
|
||||||
COPY ["GeradoresWS/GeradoresWS.csproj", "GeradoresWS/"]
|
COPY ["GeradoresWS/GeradoresWS.csproj", "GeradoresWS/"]
|
||||||
@@ -25,7 +25,7 @@ WORKDIR /app
|
|||||||
COPY --from=publish /app/publish .
|
COPY --from=publish /app/publish .
|
||||||
|
|
||||||
# Set environment variables
|
# Set environment variables
|
||||||
ENV ASPNETCORE_URLS=http://+:8080
|
ENV ASPNETCORE_URLS=http://+:8080, http://+:443
|
||||||
ENV ASPNETCORE_ENVIRONMENT=Production
|
ENV ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
|
||||||
ENTRYPOINT ["dotnet", "GeradoresWS.dll"]
|
ENTRYPOINT ["dotnet", "GeradoresWS.dll"]
|
||||||
@@ -5,16 +5,22 @@ VisualStudioVersion = 17.6.33829.357
|
|||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFiles", "SolutionFiles", "{6370AD16-6443-4846-B933-702A86A48A19}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFiles", "SolutionFiles", "{6370AD16-6443-4846-B933-702A86A48A19}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
.dockerignore = .dockerignore
|
||||||
.gitattributes = .gitattributes
|
.gitattributes = .gitattributes
|
||||||
.gitignore = .gitignore
|
.gitignore = .gitignore
|
||||||
|
docker-compose.yml = docker-compose.yml
|
||||||
|
Dockerfile = Dockerfile
|
||||||
|
Jenkinsfile = Jenkinsfile
|
||||||
README.md = README.md
|
README.md = README.md
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{54A90642-561A-4BB1-A94E-469ADEE60C69}") = "geradoresfe", "geradoresfe\geradoresfe.esproj", "{1D9DDDEB-6FBA-4A9C-AE85-6A3630D8B9AC}"
|
Project("{54A90642-561A-4BB1-A94E-469ADEE60C69}") = "geradoresfe", "geradoresfe\geradoresfe.esproj", "{1D9DDDEB-6FBA-4A9C-AE85-6A3630D8B9AC}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeradoresWS", "GeradoresWS\GeradoresWS.csproj", "{78B34F6D-E9C9-4FD0-A3E4-670BA401ACF6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeradoresWS", "GeradoresWS\GeradoresWS.csproj", "{78B34F6D-E9C9-4FD0-A3E4-670BA401ACF6}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeradoresService", "GeradoresService\GeradoresService.csproj", "{35C4D726-3771-4D34-9A43-541588FCECAA}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeradoresService", "GeradoresService\GeradoresService.csproj", "{35C4D726-3771-4D34-9A43-541588FCECAA}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "UnitTest\UnitTest.csproj", "{911FEEB4-749E-43CA-9FE3-CE8334B5E0C9}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -36,6 +42,10 @@ Global
|
|||||||
{35C4D726-3771-4D34-9A43-541588FCECAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{35C4D726-3771-4D34-9A43-541588FCECAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{35C4D726-3771-4D34-9A43-541588FCECAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{35C4D726-3771-4D34-9A43-541588FCECAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{35C4D726-3771-4D34-9A43-541588FCECAA}.Release|Any CPU.Build.0 = Release|Any CPU
|
{35C4D726-3771-4D34-9A43-541588FCECAA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{911FEEB4-749E-43CA-9FE3-CE8334B5E0C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{911FEEB4-749E-43CA-9FE3-CE8334B5E0C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{911FEEB4-749E-43CA-9FE3-CE8334B5E0C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{911FEEB4-749E-43CA-9FE3-CE8334B5E0C9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
13
GeradoresService/DAL/Geradore.cs
Normal file
13
GeradoresService/DAL/Geradore.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace GeradoresService.DAL;
|
||||||
|
|
||||||
|
public partial class Geradore
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int? Tipo { get; set; }
|
||||||
|
|
||||||
|
public string? Valor { get; set; }
|
||||||
|
}
|
||||||
34
GeradoresService/DAL/GeradoresContext.cs
Normal file
34
GeradoresService/DAL/GeradoresContext.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace GeradoresService.DAL;
|
||||||
|
|
||||||
|
public partial class GeradoresContext : DbContext
|
||||||
|
{
|
||||||
|
public GeradoresContext()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeradoresContext(DbContextOptions<GeradoresContext> options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual DbSet<Geradore> Geradores { get; set; }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder.Entity<Geradore>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PK__Geradore__3214EC2710D5AD88");
|
||||||
|
|
||||||
|
entity.Property(e => e.Id).HasColumnName("ID");
|
||||||
|
entity.Property(e => e.Valor).HasMaxLength(50);
|
||||||
|
});
|
||||||
|
|
||||||
|
OnModelCreatingPartial(modelBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||||
|
}
|
||||||
@@ -1,9 +1,21 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="DAL\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
using System.ComponentModel;
|
using GeradoresService.DAL;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
|
|
||||||
namespace GeradoresService
|
namespace GeradoresService
|
||||||
{
|
{
|
||||||
public class NIF
|
public class NIF
|
||||||
{
|
{
|
||||||
|
private readonly GeradoresContext _geradoresContext;
|
||||||
|
|
||||||
|
public NIF(GeradoresContext geradoresContext)
|
||||||
|
{
|
||||||
|
_geradoresContext = geradoresContext;
|
||||||
|
}
|
||||||
|
|
||||||
public enum NIFType
|
public enum NIFType
|
||||||
{
|
{
|
||||||
[Description("Pessoa singular (1)")]
|
[Description("Pessoa singular (1)")]
|
||||||
@@ -29,16 +37,14 @@ namespace GeradoresService
|
|||||||
PessoaColectivaIrregular = 9
|
PessoaColectivaIrregular = 9
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public static GetNIFTypes(){
|
public string Generate(string? type)
|
||||||
EnumHelper.GetEnumValuesAndDescriptions(NIFType);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public static string Generate(string? type)
|
|
||||||
{
|
{
|
||||||
return GenerateRandomNIF(type);
|
var nif = GenerateRandomNIF(type);
|
||||||
|
//SaveNIF(nif);
|
||||||
|
return nif;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GenerateRandomNIF(string? nifType)
|
public string GenerateRandomNIF(string? nifType)
|
||||||
{
|
{
|
||||||
var firstDigitValidate = new char[] { '1', '2', '3', '5', '6', '8', '9' };
|
var firstDigitValidate = new char[] { '1', '2', '3', '5', '6', '8', '9' };
|
||||||
Random rnd = new Random();
|
Random rnd = new Random();
|
||||||
@@ -86,7 +92,7 @@ namespace GeradoresService
|
|||||||
return randomNIF;
|
return randomNIF;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Validate(string nif)
|
public bool Validate(string nif)
|
||||||
{
|
{
|
||||||
// Verificar se o NIF tem 9 dígitos
|
// Verificar se o NIF tem 9 dígitos
|
||||||
if (nif.Length != 9)
|
if (nif.Length != 9)
|
||||||
@@ -117,5 +123,16 @@ namespace GeradoresService
|
|||||||
return digitoControlo == digitos[8];
|
return digitoControlo == digitos[8];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SaveNIF(string NIF)
|
||||||
|
{
|
||||||
|
var ger = new Geradore()
|
||||||
|
{
|
||||||
|
Valor = NIF
|
||||||
|
};
|
||||||
|
|
||||||
|
_geradoresContext.Geradores.Add(ger);
|
||||||
|
_geradoresContext.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using GeradoresService;
|
using GeradoresService;
|
||||||
|
using GeradoresService.DAL;
|
||||||
|
|
||||||
namespace GeradoresWS.Controllers
|
namespace GeradoresWS.Controllers
|
||||||
{
|
{
|
||||||
@@ -7,8 +8,13 @@ namespace GeradoresWS.Controllers
|
|||||||
[Route("[controller]")]
|
[Route("[controller]")]
|
||||||
public class GenerateController : Controller
|
public class GenerateController : Controller
|
||||||
{
|
{
|
||||||
#region NIF
|
GeradoresContext _context;
|
||||||
|
public GenerateController(GeradoresContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region NIF
|
||||||
[HttpGet("GetNIFTypes")]
|
[HttpGet("GetNIFTypes")]
|
||||||
public List<NIF.NIFType> GetNIFTypes()
|
public List<NIF.NIFType> GetNIFTypes()
|
||||||
{
|
{
|
||||||
@@ -18,13 +24,15 @@ namespace GeradoresWS.Controllers
|
|||||||
[HttpGet("GenerateNIF")]
|
[HttpGet("GenerateNIF")]
|
||||||
public string GenerateNIF(string? type)
|
public string GenerateNIF(string? type)
|
||||||
{
|
{
|
||||||
return NIF.Generate(type);
|
var nif = new NIF(_context);
|
||||||
|
return nif.Generate(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("ValidateNIF")]
|
[HttpGet("ValidateNIF")]
|
||||||
public bool ValidateNIF(string nif)
|
public bool ValidateNIF(string nif)
|
||||||
{
|
{
|
||||||
return NIF.Validate(nif);
|
var teste = new NIF(_context);
|
||||||
|
return teste.Validate(nif);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
32
GeradoresWS/Dockerfile
Normal file
32
GeradoresWS/Dockerfile
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 8080
|
||||||
|
EXPOSE 443
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY ["GeradoresWS/GeradoresWS.csproj", "GeradoresWS/"]
|
||||||
|
COPY ["GeradoresService/GeradoresService.csproj", "GeradoresService/"]
|
||||||
|
|
||||||
|
RUN dotnet restore "GeradoresWS/GeradoresWS.csproj"
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
WORKDIR "/src/GeradoresWS"
|
||||||
|
RUN dotnet build "GeradoresWS.csproj" -c debug -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
RUN dotnet publish "GeradoresWS.csproj" -c debug -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
|
||||||
|
# Set environment variables
|
||||||
|
ENV ASPNETCORE_URLS=http://+:8080
|
||||||
|
ENV ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
|
||||||
|
ENTRYPOINT ["dotnet", "GeradoresWS.dll"]
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<UserSecretsId>df357c84-88b1-4100-86d1-889166b333f7</UserSecretsId>
|
<UserSecretsId>df357c84-88b1-4100-86d1-889166b333f7</UserSecretsId>
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
using GeradoresService.DAL;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
@@ -7,13 +10,16 @@ builder.Services.AddControllers();
|
|||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var connectionString = builder.Configuration.GetConnectionString("GeradoresConnection");
|
||||||
|
builder.Services.AddDbContext<GeradoresContext>(options => options.UseSqlServer(connectionString));
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
app.UseSwagger();
|
app.UseSwagger();
|
||||||
app.UseSwaggerUI();
|
app.UseSwaggerUI();
|
||||||
|
|
||||||
|
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|||||||
@@ -32,6 +32,10 @@
|
|||||||
"commandName": "Docker",
|
"commandName": "Docker",
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
|
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_URLS": "http://+:8080",
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
},
|
||||||
"publishAllPorts": true,
|
"publishAllPorts": true,
|
||||||
"useSSL": false
|
"useSSL": false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,9 @@
|
|||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*"
|
"AllowedHosts": "*",
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"GeradoresConnection": "server=127.0.0.1;uid=sa;pwd=mssqlAdmin!1;database=Geradores;TrustServerCertificate=True;"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
27
Jenkinsfile
vendored
27
Jenkinsfile
vendored
@@ -12,12 +12,21 @@ pipeline {
|
|||||||
|
|
||||||
environment {
|
environment {
|
||||||
now = new Date().format('yyyyMMdd-HHmm', TimeZone.getTimeZone('UTC'))
|
now = new Date().format('yyyyMMdd-HHmm', TimeZone.getTimeZone('UTC'))
|
||||||
|
|
||||||
|
DOCKER_IMAGE = 'GeradoresWs/api'
|
||||||
|
DOCKER_TAG = "${env.BUILD_ID}"
|
||||||
|
DOCKER_REGISTRY = 'Shini89'
|
||||||
|
REMOTE_DOCKER_HOST = '192.168.2.20'
|
||||||
|
REMOTE_DOCKER_USER = 'admin'
|
||||||
|
REMOTE_DOCKER_PORT = '2375'
|
||||||
|
|
||||||
|
REACT_DIR = 'geradoresfe' // Diret<65>rio do frontend React
|
||||||
|
SERVICE_DIR = 'GeradoresService' // Diret<65>rio do projeto DLL
|
||||||
|
API_DIR = 'GeradoresWS' // Diret<65>rio do Web API
|
||||||
|
DOCKER_REGISTRY = 'your-docker-registry.com' // Registro Docker
|
||||||
}
|
}
|
||||||
|
|
||||||
stages {
|
stages {
|
||||||
/*******************************************************
|
|
||||||
Stage BUILD
|
|
||||||
*******************************************************/
|
|
||||||
stage('Check for Changes') {
|
stage('Check for Changes') {
|
||||||
steps {
|
steps {
|
||||||
script {
|
script {
|
||||||
@@ -43,12 +52,20 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stage('Checkout Code') {
|
||||||
|
steps {
|
||||||
|
git branch: 'master', url: 'https://git.homeware.pt/Marco/Geradores.git'
|
||||||
|
}
|
||||||
|
}
|
||||||
/*******************************************************
|
/*******************************************************
|
||||||
Stage BUILD
|
Stage BUILD
|
||||||
*******************************************************/
|
*******************************************************/
|
||||||
stage('Build') {
|
stage('Build Service DLL') {
|
||||||
steps {
|
steps {
|
||||||
echo 'Construindo o projeto...'
|
echo 'Building Business Logic DLL...'
|
||||||
|
dir("${env.SERVICE_DIR}") {
|
||||||
|
sh 'dotnet build -c Release'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
38
UnitTest/DB.cs
Normal file
38
UnitTest/DB.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using GeradoresService;
|
||||||
|
using GeradoresService.DAL;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
namespace UnitTest
|
||||||
|
{
|
||||||
|
public class DB
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly GeradoresContext _context;
|
||||||
|
public DB()
|
||||||
|
{
|
||||||
|
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.AddJsonFile("appsettings.json")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
// Obter a connection string a partir do arquivo de configura<72><61>o
|
||||||
|
var connectionString = configuration.GetConnectionString("GeradoresConnection");
|
||||||
|
|
||||||
|
// Configurar o DbContext para usar o InMemoryDatabase
|
||||||
|
var options = new DbContextOptionsBuilder<GeradoresContext>()
|
||||||
|
.UseSqlServer(connectionString)
|
||||||
|
.Options;
|
||||||
|
|
||||||
|
_context = new GeradoresContext(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GenerateNIF()
|
||||||
|
{
|
||||||
|
var nif = new NIF(_context);
|
||||||
|
var gerenatednif = nif.Generate("2");
|
||||||
|
Assert.NotEmpty(gerenatednif);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
UnitTest/UnitTest.csproj
Normal file
54
UnitTest/UnitTest.csproj
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="appsettings.Development.json" />
|
||||||
|
<None Remove="appsettings.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="appsettings.Development.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="8.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\GeradoresService\GeradoresService.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
8
UnitTest/appsettings.Development.json
Normal file
8
UnitTest/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
UnitTest/appsettings.json
Normal file
13
UnitTest/appsettings.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"GeradoresConnection": "server=127.0.0.1;uid=sa;pwd=mssqlAdmin!1;database=Geradores;TrustServerCertificate=True;"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -5,6 +5,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.11.4",
|
"@emotion/react": "^11.11.4",
|
||||||
"@emotion/styled": "^11.11.5",
|
"@emotion/styled": "^11.11.5",
|
||||||
|
"@headlessui/react": "^2.2.0",
|
||||||
|
"@heroicons/react": "^2.1.5",
|
||||||
"@mui/icons-material": "^5.15.15",
|
"@mui/icons-material": "^5.15.15",
|
||||||
"@mui/material": "^5.15.15",
|
"@mui/material": "^5.15.15",
|
||||||
"@testing-library/jest-dom": "^5.17.0",
|
"@testing-library/jest-dom": "^5.17.0",
|
||||||
@@ -50,6 +52,7 @@
|
|||||||
"@types/react-helmet": "^6.1.11",
|
"@types/react-helmet": "^6.1.11",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-react-app": "^7.0.1",
|
"eslint-config-react-app": "^7.0.1",
|
||||||
"jest-editor-support": "^31.1.2"
|
"jest-editor-support": "^31.1.2",
|
||||||
|
"tailwindcss": "^3.4.13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,99 +1,20 @@
|
|||||||
import * as React from 'react';
|
import React from 'react';
|
||||||
import { PaletteMode } from '@mui/material';
|
import Navbar from './components/Navbar';
|
||||||
import CssBaseline from '@mui/material/CssBaseline';
|
|
||||||
import Box from '@mui/material/Box';
|
|
||||||
import Divider from '@mui/material/Divider';
|
|
||||||
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
|
||||||
import ToggleButton from '@mui/material/ToggleButton';
|
|
||||||
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
|
|
||||||
|
|
||||||
import { Helmet } from 'react-helmet';
|
|
||||||
import getLPTheme from './GeradoresTheme';
|
|
||||||
|
|
||||||
import AppAppBar from './components/AppAppBar';
|
|
||||||
import Hero from './components/Hero';
|
import Hero from './components/Hero';
|
||||||
import LogoCollection from './components/LogoCollection';
|
import FeatureSection from './components/Features';
|
||||||
import Highlights from './components/Highlights';
|
|
||||||
import Pricing from './components/Pricing';
|
|
||||||
import Features from './components/Features';
|
|
||||||
import Testimonials from './components/Testimonials';
|
|
||||||
import FAQ from './components/FAQ';
|
|
||||||
import Footer from './components/Footer';
|
import Footer from './components/Footer';
|
||||||
import GeradorCC from './components/GeradorNIF';
|
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
|
||||||
interface ToggleCustomThemeProps {
|
|
||||||
showCustomTheme: Boolean;
|
|
||||||
toggleCustomTheme: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
function ToggleCustomTheme({
|
|
||||||
showCustomTheme,
|
|
||||||
toggleCustomTheme,
|
|
||||||
}: ToggleCustomThemeProps) {
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<div className="min-h-screen flex flex-col">
|
||||||
sx={{
|
<Navbar />
|
||||||
display: 'flex',
|
<main className="flex-grow">
|
||||||
flexDirection: 'column',
|
<Hero />
|
||||||
alignItems: 'center',
|
<FeatureSection />
|
||||||
width: '100dvw',
|
</main>
|
||||||
position: 'fixed',
|
<Footer />
|
||||||
bottom: 24,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ToggleButtonGroup
|
|
||||||
color="primary"
|
|
||||||
exclusive
|
|
||||||
value={showCustomTheme}
|
|
||||||
onChange={toggleCustomTheme}
|
|
||||||
aria-label="Platform"
|
|
||||||
sx={{
|
|
||||||
backgroundColor: 'background.default',
|
|
||||||
'& .Mui-selected': {
|
|
||||||
pointerEvents: 'none',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ToggleButton value>
|
|
||||||
|
|
||||||
Custom theme
|
|
||||||
</ToggleButton>
|
|
||||||
<ToggleButton value={false}>Material Design 2</ToggleButton>
|
|
||||||
</ToggleButtonGroup>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
function App() {
|
|
||||||
/*const [mode, setMode] = React.useState<PaletteMode>('light');
|
|
||||||
const [showCustomTheme, setShowCustomTheme] = React.useState(true);
|
|
||||||
const LPtheme = createTheme(getLPTheme(mode));
|
|
||||||
const defaultTheme = createTheme({ palette: { mode } });
|
|
||||||
|
|
||||||
const toggleColorMode = () => {
|
|
||||||
setMode((prev) => (prev === 'dark' ? 'light' : 'dark'));
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleCustomTheme = () => {
|
|
||||||
setShowCustomTheme((prev) => !prev);
|
|
||||||
};*/
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="App">
|
|
||||||
<Helmet>
|
|
||||||
<meta charSet="utf-8" />
|
|
||||||
<title>Geradores</title>
|
|
||||||
</Helmet>
|
|
||||||
{ /*<ThemeProvider theme={showCustomTheme ? LPtheme : defaultTheme}></ThemeProvider>*/}
|
|
||||||
<div>
|
|
||||||
<CssBaseline />
|
|
||||||
<GeradorCC />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
BIN
geradoresfe/src/assets/logotio.jfif
Normal file
BIN
geradoresfe/src/assets/logotio.jfif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
geradoresfe/src/assets/logotipo.png
Normal file
BIN
geradoresfe/src/assets/logotipo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 136 KiB |
BIN
geradoresfe/src/assets/logotipo_transparent.png
Normal file
BIN
geradoresfe/src/assets/logotipo_transparent.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 136 KiB |
@@ -1,227 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import { PaletteMode } from '@mui/material';
|
|
||||||
import Box from '@mui/material/Box';
|
|
||||||
import AppBar from '@mui/material/AppBar';
|
|
||||||
import Toolbar from '@mui/material/Toolbar';
|
|
||||||
import Button from '@mui/material/Button';
|
|
||||||
import IconButton from '@mui/material/IconButton';
|
|
||||||
import Container from '@mui/material/Container';
|
|
||||||
import Divider from '@mui/material/Divider';
|
|
||||||
import MenuItem from '@mui/material/MenuItem';
|
|
||||||
import Drawer from '@mui/material/Drawer';
|
|
||||||
import MenuIcon from '@mui/icons-material/Menu';
|
|
||||||
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
|
|
||||||
import ToggleColorMode from './ToggleColorMode';
|
|
||||||
|
|
||||||
import Sitemark from './SitemarkIcon';
|
|
||||||
|
|
||||||
interface AppAppBarProps {
|
|
||||||
mode: PaletteMode;
|
|
||||||
toggleColorMode: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function AppAppBar({ mode, toggleColorMode }: AppAppBarProps) {
|
|
||||||
const [open, setOpen] = React.useState(false);
|
|
||||||
|
|
||||||
const toggleDrawer = (newOpen: boolean) => () => {
|
|
||||||
setOpen(newOpen);
|
|
||||||
};
|
|
||||||
|
|
||||||
const scrollToSection = (sectionId: string) => {
|
|
||||||
const sectionElement = document.getElementById(sectionId);
|
|
||||||
const offset = 128;
|
|
||||||
if (sectionElement) {
|
|
||||||
const targetScroll = sectionElement.offsetTop - offset;
|
|
||||||
sectionElement.scrollIntoView({ behavior: 'smooth' });
|
|
||||||
window.scrollTo({
|
|
||||||
top: targetScroll,
|
|
||||||
behavior: 'smooth',
|
|
||||||
});
|
|
||||||
setOpen(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AppBar
|
|
||||||
position="fixed"
|
|
||||||
sx={{
|
|
||||||
boxShadow: 0,
|
|
||||||
bgcolor: 'transparent',
|
|
||||||
backgroundImage: 'none',
|
|
||||||
mt: 2,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Container maxWidth="lg">
|
|
||||||
<Toolbar
|
|
||||||
variant="regular"
|
|
||||||
sx={(theme) => ({
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
flexShrink: 0,
|
|
||||||
borderRadius: '999px',
|
|
||||||
bgcolor:
|
|
||||||
theme.palette.mode === 'light'
|
|
||||||
? 'hsla(220, 60%, 99%, 0.6)'
|
|
||||||
: 'hsla(220, 0%, 0%, 0.7)',
|
|
||||||
backdropFilter: 'blur(24px)',
|
|
||||||
maxHeight: 40,
|
|
||||||
border: '1px solid',
|
|
||||||
borderColor: 'divider',
|
|
||||||
boxShadow:
|
|
||||||
theme.palette.mode === 'light'
|
|
||||||
? '0 1px 2px hsla(210, 0%, 0%, 0.05), 0 2px 12px hsla(210, 100%, 80%, 0.5)'
|
|
||||||
: '0 1px 2px hsla(210, 0%, 0%, 0.5), 0 2px 12px hsla(210, 100%, 25%, 0.3)',
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
flexGrow: 1,
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
px: 0,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Sitemark />
|
|
||||||
<Box sx={{ display: { xs: 'none', md: 'flex' } }}>
|
|
||||||
<Button
|
|
||||||
variant="text"
|
|
||||||
color="info"
|
|
||||||
size="small"
|
|
||||||
onClick={() => scrollToSection('features')}
|
|
||||||
>
|
|
||||||
Features
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="text"
|
|
||||||
color="info"
|
|
||||||
size="small"
|
|
||||||
onClick={() => scrollToSection('testimonials')}
|
|
||||||
>
|
|
||||||
Testimonials
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="text"
|
|
||||||
color="info"
|
|
||||||
size="small"
|
|
||||||
onClick={() => scrollToSection('highlights')}
|
|
||||||
>
|
|
||||||
Highlights
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="text"
|
|
||||||
color="info"
|
|
||||||
size="small"
|
|
||||||
onClick={() => scrollToSection('pricing')}
|
|
||||||
>
|
|
||||||
Pricing
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="text"
|
|
||||||
color="info"
|
|
||||||
size="small"
|
|
||||||
onClick={() => scrollToSection('faq')}
|
|
||||||
sx={{ minWidth: 0 }}
|
|
||||||
>
|
|
||||||
FAQ
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: { xs: 'none', md: 'flex' },
|
|
||||||
gap: 0.5,
|
|
||||||
alignItems: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ToggleColorMode mode={mode} toggleColorMode={toggleColorMode} />
|
|
||||||
<Button
|
|
||||||
color="primary"
|
|
||||||
variant="text"
|
|
||||||
size="small"
|
|
||||||
component="a"
|
|
||||||
href="/material-ui/getting-started/templates/sign-in/"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
Sign in
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color="primary"
|
|
||||||
variant="contained"
|
|
||||||
size="small"
|
|
||||||
component="a"
|
|
||||||
href="/material-ui/getting-started/templates/sign-up/"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
Sign up
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
<Box sx={{ display: { sm: 'flex', md: 'none' } }}>
|
|
||||||
<IconButton aria-label="Menu button" onClick={toggleDrawer(true)}>
|
|
||||||
<MenuIcon />
|
|
||||||
</IconButton>
|
|
||||||
<Drawer anchor="top" open={open} onClose={toggleDrawer(false)}>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
p: 2,
|
|
||||||
backgroundColor: 'background.default',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ToggleColorMode mode={mode} toggleColorMode={toggleColorMode} />
|
|
||||||
<IconButton onClick={toggleDrawer(false)}>
|
|
||||||
<CloseRoundedIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
|
||||||
<Divider sx={{ my: 3 }} />
|
|
||||||
<MenuItem onClick={() => scrollToSection('features')}>
|
|
||||||
Features
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem onClick={() => scrollToSection('testimonials')}>
|
|
||||||
Testimonials
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem onClick={() => scrollToSection('highlights')}>
|
|
||||||
Highlights
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem onClick={() => scrollToSection('pricing')}>
|
|
||||||
Pricing
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem onClick={() => scrollToSection('faq')}>FAQ</MenuItem>
|
|
||||||
<MenuItem>
|
|
||||||
<Button
|
|
||||||
color="primary"
|
|
||||||
variant="contained"
|
|
||||||
component="a"
|
|
||||||
href="/material-ui/getting-started/templates/sign-up/"
|
|
||||||
target="_blank"
|
|
||||||
fullWidth
|
|
||||||
>
|
|
||||||
Sign up
|
|
||||||
</Button>
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem>
|
|
||||||
<Button
|
|
||||||
color="primary"
|
|
||||||
variant="outlined"
|
|
||||||
component="a"
|
|
||||||
href="/material-ui/getting-started/templates/sign-in/"
|
|
||||||
target="_blank"
|
|
||||||
fullWidth
|
|
||||||
>
|
|
||||||
Sign in
|
|
||||||
</Button>
|
|
||||||
</MenuItem>
|
|
||||||
</Box>
|
|
||||||
</Drawer>
|
|
||||||
</Box>
|
|
||||||
</Toolbar>
|
|
||||||
</Container>
|
|
||||||
</AppBar>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,272 +1,27 @@
|
|||||||
import * as React from 'react';
|
import React from 'react';
|
||||||
import Box from '@mui/material/Box';
|
|
||||||
import Button from '@mui/material/Button';
|
|
||||||
import Card from '@mui/material/Card';
|
|
||||||
import Chip from '@mui/material/Chip';
|
|
||||||
import Container from '@mui/material/Container';
|
|
||||||
import Grid from '@mui/material/Grid';
|
|
||||||
import Link from '@mui/material/Link';
|
|
||||||
import Stack from '@mui/material/Stack';
|
|
||||||
import Typography from '@mui/material/Typography';
|
|
||||||
import ChevronRightRoundedIcon from '@mui/icons-material/ChevronRightRounded';
|
|
||||||
import DevicesRoundedIcon from '@mui/icons-material/DevicesRounded';
|
|
||||||
import EdgesensorHighRoundedIcon from '@mui/icons-material/EdgesensorHighRounded';
|
|
||||||
import ViewQuiltRoundedIcon from '@mui/icons-material/ViewQuiltRounded';
|
|
||||||
|
|
||||||
const items = [
|
|
||||||
{
|
|
||||||
icon: <ViewQuiltRoundedIcon />,
|
|
||||||
title: 'Dashboard',
|
|
||||||
description:
|
|
||||||
'This item could provide a snapshot of the most important metrics or data points related to the product.',
|
|
||||||
imageLight: 'url("/static/images/templates/templates-images/dash-light.png")',
|
|
||||||
imageDark: 'url("/static/images/templates/templates-images/dash-dark.png")',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: <EdgesensorHighRoundedIcon />,
|
|
||||||
title: 'Mobile integration',
|
|
||||||
description:
|
|
||||||
'This item could provide information about the mobile app version of the product.',
|
|
||||||
imageLight: 'url("/static/images/templates/templates-images/mobile-light.png")',
|
|
||||||
imageDark: 'url("/static/images/templates/templates-images/mobile-dark.png")',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: <DevicesRoundedIcon />,
|
|
||||||
title: 'Available on all platforms',
|
|
||||||
description:
|
|
||||||
'This item could let users know the product is available on all platforms, such as web, mobile, and desktop.',
|
|
||||||
imageLight: 'url("/static/images/templates/templates-images/devices-light.png")',
|
|
||||||
imageDark: 'url("/static/images/templates/templates-images/devices-dark.png")',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function Features() {
|
|
||||||
const [selectedItemIndex, setSelectedItemIndex] = React.useState(0);
|
|
||||||
|
|
||||||
const handleItemClick = (index: number) => {
|
|
||||||
setSelectedItemIndex(index);
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectedFeature = items[selectedItemIndex];
|
|
||||||
|
|
||||||
|
function FeatureSection() {
|
||||||
return (
|
return (
|
||||||
<Container id="features" sx={{ py: { xs: 8, sm: 16 } }}>
|
<section id="features" className="py-20 bg-white">
|
||||||
<Grid container spacing={6}>
|
<div className="container mx-auto px-4 text-center">
|
||||||
<Grid item xs={12} md={6}>
|
<h2 className="text-3xl font-bold text-gray-800">Why Use Our Generator?</h2>
|
||||||
<div>
|
<div className="mt-8 grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||||
<Typography component="h2" variant="h4" color="text.primary">
|
<div className="p-6 bg-gray-50 rounded-lg shadow-md">
|
||||||
Product features
|
<h3 className="text-xl font-bold text-gray-800">NIF (N<EFBFBD>mero Identifica<EFBFBD><EFBFBD>o Fiscal)</h3>
|
||||||
</Typography>
|
<p className="mt-4 text-gray-600">Quickly generate valid Portuguese Tax Identification Numbers (NIF) for testing.</p>
|
||||||
<Typography
|
|
||||||
variant="body1"
|
|
||||||
color="text.secondary"
|
|
||||||
sx={{ mb: { xs: 2, sm: 4 } }}
|
|
||||||
>
|
|
||||||
Provide a brief overview of the key features of the product. For
|
|
||||||
example, you could list the number of features, their types or
|
|
||||||
benefits, and add-ons.
|
|
||||||
</Typography>
|
|
||||||
</div>
|
</div>
|
||||||
<Grid container item gap={1} sx={{ display: { xs: 'auto', sm: 'none' } }}>
|
<div className="p-6 bg-gray-50 rounded-lg shadow-md">
|
||||||
{items.map(({ title }, index) => (
|
<h3 className="text-xl font-bold text-gray-800">NISS (N<EFBFBD>mero Identifica<EFBFBD><EFBFBD>o Seguran<EFBFBD>a Social)</h3>
|
||||||
<Chip
|
<p className="mt-4 text-gray-600">Create Portuguese Social Security Numbers (NISS) easily with one click.</p>
|
||||||
key={index}
|
|
||||||
label={title}
|
|
||||||
onClick={() => handleItemClick(index)}
|
|
||||||
sx={(theme) => ({
|
|
||||||
...(selectedItemIndex === index && {
|
|
||||||
borderColor:
|
|
||||||
theme.palette.mode === 'light'
|
|
||||||
? 'primary.light'
|
|
||||||
: 'primary.dark',
|
|
||||||
background:
|
|
||||||
'linear-gradient(to bottom right, hsl(210, 98%, 48%), hsl(210, 98%, 35%))',
|
|
||||||
color: 'hsl(0, 0%, 100%)',
|
|
||||||
'& .MuiChip-label': {
|
|
||||||
color: 'hsl(0, 0%, 100%)',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Grid>
|
|
||||||
<Card
|
|
||||||
variant="outlined"
|
|
||||||
sx={{
|
|
||||||
display: { xs: 'auto', sm: 'none' },
|
|
||||||
mt: 4,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
backgroundImage: (theme) =>
|
|
||||||
theme.palette.mode === 'light'
|
|
||||||
? items[selectedItemIndex].imageLight
|
|
||||||
: items[selectedItemIndex].imageDark,
|
|
||||||
backgroundSize: 'cover',
|
|
||||||
backgroundPosition: 'center',
|
|
||||||
minHeight: 280,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Box sx={{ px: 2, pb: 2 }}>
|
|
||||||
<Typography color="text.primary" fontWeight="medium" gutterBottom>
|
|
||||||
{selectedFeature.title}
|
|
||||||
</Typography>
|
|
||||||
<Typography color="text.secondary" variant="body2" sx={{ mb: 1.5 }}>
|
|
||||||
{selectedFeature.description}
|
|
||||||
</Typography>
|
|
||||||
<Link
|
|
||||||
color="primary"
|
|
||||||
variant="body2"
|
|
||||||
fontWeight="bold"
|
|
||||||
sx={{
|
|
||||||
display: 'inline-flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
'& > svg': { transition: '0.2s' },
|
|
||||||
'&:hover > svg': { transform: 'translateX(2px)' },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span>Learn more</span>
|
|
||||||
<ChevronRightRoundedIcon
|
|
||||||
fontSize="small"
|
|
||||||
sx={{ mt: '1px', ml: '2px' }}
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
</Box>
|
|
||||||
</Card>
|
|
||||||
<Stack
|
|
||||||
direction="column"
|
|
||||||
justifyContent="center"
|
|
||||||
alignItems="flex-start"
|
|
||||||
spacing={2}
|
|
||||||
useFlexGap
|
|
||||||
sx={{ width: '100%', display: { xs: 'none', sm: 'flex' } }}
|
|
||||||
>
|
|
||||||
{items.map(({ icon, title, description }, index) => (
|
|
||||||
<Card
|
|
||||||
key={index}
|
|
||||||
component={Button}
|
|
||||||
onClick={() => handleItemClick(index)}
|
|
||||||
sx={(theme) => ({
|
|
||||||
p: 3,
|
|
||||||
height: 'fit-content',
|
|
||||||
width: '100%',
|
|
||||||
background: 'none',
|
|
||||||
...(selectedItemIndex === index && {
|
|
||||||
backgroundColor: 'action.selected',
|
|
||||||
borderColor:
|
|
||||||
theme.palette.mode === 'light'
|
|
||||||
? 'primary.light'
|
|
||||||
: 'primary.dark',
|
|
||||||
}),
|
|
||||||
'&:hover': {
|
|
||||||
background:
|
|
||||||
theme.palette.mode === 'light'
|
|
||||||
? 'linear-gradient(to bottom right, hsla(210, 100%, 97%, 0.5) 25%, hsla(210, 100%, 90%, 0.3) 100%)'
|
|
||||||
: 'linear-gradient(to right bottom, hsla(210, 100%, 12%, 0.2) 25%, hsla(210, 100%, 16%, 0.2) 100%)',
|
|
||||||
borderColor:
|
|
||||||
theme.palette.mode === 'light'
|
|
||||||
? 'primary.light'
|
|
||||||
: 'primary.dark',
|
|
||||||
boxShadow:
|
|
||||||
theme.palette.mode === 'light'
|
|
||||||
? '0px 2px 8px hsla(0, 0%, 0%, 0.1)'
|
|
||||||
: '0px 1px 8px hsla(210, 100%, 25%, 0.5) ',
|
|
||||||
},
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
textAlign: 'left',
|
|
||||||
flexDirection: { xs: 'column', md: 'row' },
|
|
||||||
alignItems: { md: 'center' },
|
|
||||||
gap: 2.5,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={(theme) => ({
|
|
||||||
color:
|
|
||||||
theme.palette.mode === 'light' ? 'grey.400' : 'grey.600',
|
|
||||||
...(selectedItemIndex === index && {
|
|
||||||
color: 'primary.main',
|
|
||||||
}),
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{icon}
|
|
||||||
</Box>
|
|
||||||
<div>
|
|
||||||
<Typography
|
|
||||||
color="text.primary"
|
|
||||||
fontWeight="medium"
|
|
||||||
gutterBottom
|
|
||||||
>
|
|
||||||
{title}
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
color="text.secondary"
|
|
||||||
variant="body2"
|
|
||||||
sx={{ mb: 1.5 }}
|
|
||||||
>
|
|
||||||
{description}
|
|
||||||
</Typography>
|
|
||||||
<Link
|
|
||||||
color="primary"
|
|
||||||
variant="body2"
|
|
||||||
fontWeight="bold"
|
|
||||||
sx={{
|
|
||||||
display: 'inline-flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
'& > svg': { transition: '0.2s' },
|
|
||||||
'&:hover > svg': { transform: 'translateX(2px)' },
|
|
||||||
}}
|
|
||||||
onClick={(event) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span>Learn more</span>
|
|
||||||
<ChevronRightRoundedIcon
|
|
||||||
fontSize="small"
|
|
||||||
sx={{ mt: '1px', ml: '2px' }}
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
<div className="p-6 bg-gray-50 rounded-lg shadow-md">
|
||||||
</Card>
|
<h3 className="text-xl font-bold text-gray-800">Cart<EFBFBD>o de Cidad<EFBFBD>o</h3>
|
||||||
))}
|
<p className="mt-4 text-gray-600">Generate valid Citizen Card numbers for testing purposes in a few seconds.</p>
|
||||||
</Stack>
|
</div>
|
||||||
</Grid>
|
</div>
|
||||||
<Grid
|
</div>
|
||||||
item
|
</section>
|
||||||
xs={12}
|
|
||||||
md={6}
|
|
||||||
sx={{ display: { xs: 'none', sm: 'flex' }, width: '100%' }}
|
|
||||||
>
|
|
||||||
<Card
|
|
||||||
variant="outlined"
|
|
||||||
sx={{
|
|
||||||
height: '100%',
|
|
||||||
width: '100%',
|
|
||||||
display: { xs: 'none', sm: 'flex' },
|
|
||||||
pointerEvents: 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
m: 'auto',
|
|
||||||
width: 420,
|
|
||||||
height: 500,
|
|
||||||
backgroundSize: 'contain',
|
|
||||||
backgroundImage: (theme) =>
|
|
||||||
theme.palette.mode === 'light'
|
|
||||||
? items[selectedItemIndex].imageLight
|
|
||||||
: items[selectedItemIndex].imageDark,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Container>
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default FeatureSection;
|
||||||
|
|||||||
@@ -1,215 +1,16 @@
|
|||||||
import * as React from 'react';
|
import React from 'react';
|
||||||
import Box from '@mui/material/Box';
|
|
||||||
import Button from '@mui/material/Button';
|
|
||||||
import Container from '@mui/material/Container';
|
|
||||||
import IconButton from '@mui/material/IconButton';
|
|
||||||
import InputLabel from '@mui/material/InputLabel';
|
|
||||||
import Link from '@mui/material/Link';
|
|
||||||
import Stack from '@mui/material/Stack';
|
|
||||||
import TextField from '@mui/material/TextField';
|
|
||||||
import Typography from '@mui/material/Typography';
|
|
||||||
|
|
||||||
import { visuallyHidden } from '@mui/utils';
|
const Footer = () => {
|
||||||
|
|
||||||
import FacebookIcon from '@mui/icons-material/GitHub';
|
|
||||||
import LinkedInIcon from '@mui/icons-material/LinkedIn';
|
|
||||||
import TwitterIcon from '@mui/icons-material/X';
|
|
||||||
|
|
||||||
import SitemarkIcon from './SitemarkIcon';
|
|
||||||
|
|
||||||
function Copyright() {
|
|
||||||
return (
|
return (
|
||||||
<Typography variant="body2" color="text.secondary" mt={1}>
|
<footer id="contact" className="bg-gray-800 py-6">
|
||||||
{'Copyright © '}
|
<div className="container mx-auto px-4 text-center text-white">
|
||||||
<Link href="https://mui.com/">Sitemark </Link>
|
<p className="text-sm">© {new Date().getFullYear()} GeneratorApp. All rights reserved.</p>
|
||||||
{new Date().getFullYear()}
|
<p className="mt-2">
|
||||||
</Typography>
|
<a href="mailto:info@generatorapp.com" className="underline">info@generatorapp.com</a>
|
||||||
);
|
</p>
|
||||||
}
|
|
||||||
|
|
||||||
export default function Footer() {
|
|
||||||
return (
|
|
||||||
<Container
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: { xs: 4, sm: 8 },
|
|
||||||
py: { xs: 8, sm: 10 },
|
|
||||||
textAlign: { sm: 'center', md: 'left' },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: { xs: 'column', sm: 'row' },
|
|
||||||
width: '100%',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
gap: 4,
|
|
||||||
minWidth: { xs: '100%', sm: '60%' },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box sx={{ width: { xs: '100%', sm: '60%' } }}>
|
|
||||||
<SitemarkIcon />
|
|
||||||
<Typography variant="body2" fontWeight={600} gutterBottom sx={{ mt: 2 }}>
|
|
||||||
Join the newsletter
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="body2" color="text.secondary" mb={2}>
|
|
||||||
Subscribe for weekly updates. No spams ever!
|
|
||||||
</Typography>
|
|
||||||
<Stack direction="row" spacing={1} useFlexGap>
|
|
||||||
<InputLabel htmlFor="email-newsletter" sx={visuallyHidden}>
|
|
||||||
Email
|
|
||||||
</InputLabel>
|
|
||||||
<TextField
|
|
||||||
id="email-newsletter"
|
|
||||||
hiddenLabel
|
|
||||||
size="small"
|
|
||||||
variant="outlined"
|
|
||||||
fullWidth
|
|
||||||
aria-label="Enter your email address"
|
|
||||||
placeholder="Your email address"
|
|
||||||
inputProps={{
|
|
||||||
autocomplete: 'off',
|
|
||||||
ariaLabel: 'Enter your email address',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Button variant="contained" color="primary" sx={{ flexShrink: 0 }}>
|
|
||||||
Subscribe
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: { xs: 'none', sm: 'flex' },
|
|
||||||
flexDirection: 'column',
|
|
||||||
gap: 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="body2" fontWeight="medium">
|
|
||||||
Product
|
|
||||||
</Typography>
|
|
||||||
<Link color="text.secondary" variant="body2" href="#">
|
|
||||||
Features
|
|
||||||
</Link>
|
|
||||||
<Link color="text.secondary" variant="body2" href="#">
|
|
||||||
Testimonials
|
|
||||||
</Link>
|
|
||||||
<Link color="text.secondary" variant="body2" href="#">
|
|
||||||
Highlights
|
|
||||||
</Link>
|
|
||||||
<Link color="text.secondary" variant="body2" href="#">
|
|
||||||
Pricing
|
|
||||||
</Link>
|
|
||||||
<Link color="text.secondary" variant="body2" href="#">
|
|
||||||
FAQs
|
|
||||||
</Link>
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: { xs: 'none', sm: 'flex' },
|
|
||||||
flexDirection: 'column',
|
|
||||||
gap: 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="body2" fontWeight="medium">
|
|
||||||
Company
|
|
||||||
</Typography>
|
|
||||||
<Link color="text.secondary" variant="body2" href="#">
|
|
||||||
About us
|
|
||||||
</Link>
|
|
||||||
<Link color="text.secondary" variant="body2" href="#">
|
|
||||||
Careers
|
|
||||||
</Link>
|
|
||||||
<Link color="text.secondary" variant="body2" href="#">
|
|
||||||
Press
|
|
||||||
</Link>
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: { xs: 'none', sm: 'flex' },
|
|
||||||
flexDirection: 'column',
|
|
||||||
gap: 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="body2" fontWeight="medium">
|
|
||||||
Legal
|
|
||||||
</Typography>
|
|
||||||
<Link color="text.secondary" variant="body2" href="#">
|
|
||||||
Terms
|
|
||||||
</Link>
|
|
||||||
<Link color="text.secondary" variant="body2" href="#">
|
|
||||||
Privacy
|
|
||||||
</Link>
|
|
||||||
<Link color="text.secondary" variant="body2" href="#">
|
|
||||||
Contact
|
|
||||||
</Link>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
pt: { xs: 4, sm: 8 },
|
|
||||||
width: '100%',
|
|
||||||
borderTop: '1px solid',
|
|
||||||
borderColor: 'divider',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<Link color="text.secondary" variant="body2" href="#">
|
|
||||||
Privacy Policy
|
|
||||||
</Link>
|
|
||||||
<Typography display="inline" sx={{ mx: 0.5, opacity: 0.5 }}>
|
|
||||||
•
|
|
||||||
</Typography>
|
|
||||||
<Link color="text.secondary" variant="body2" href="#">
|
|
||||||
Terms of Service
|
|
||||||
</Link>
|
|
||||||
<Copyright />
|
|
||||||
</div>
|
</div>
|
||||||
<Stack
|
</footer>
|
||||||
direction="row"
|
|
||||||
justifyContent="left"
|
|
||||||
spacing={1}
|
|
||||||
useFlexGap
|
|
||||||
sx={{
|
|
||||||
color: 'text.secondary',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IconButton
|
|
||||||
color="inherit"
|
|
||||||
href="https://github.com/mui"
|
|
||||||
aria-label="GitHub"
|
|
||||||
sx={{ alignSelf: 'center' }}
|
|
||||||
>
|
|
||||||
<FacebookIcon />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton
|
|
||||||
color="inherit"
|
|
||||||
href="https://twitter.com/MaterialUI"
|
|
||||||
aria-label="X"
|
|
||||||
sx={{ alignSelf: 'center' }}
|
|
||||||
>
|
|
||||||
<TwitterIcon />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton
|
|
||||||
color="inherit"
|
|
||||||
href="https://www.linkedin.com/company/mui/"
|
|
||||||
aria-label="LinkedIn"
|
|
||||||
sx={{ alignSelf: 'center' }}
|
|
||||||
>
|
|
||||||
<LinkedInIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
</Container>
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default Footer;
|
||||||
|
|||||||
@@ -1,132 +1,23 @@
|
|||||||
import * as React from 'react';
|
import React from 'react';
|
||||||
import Box from '@mui/material/Box';
|
|
||||||
import Button from '@mui/material/Button';
|
|
||||||
import Container from '@mui/material/Container';
|
|
||||||
import InputLabel from '@mui/material/InputLabel';
|
|
||||||
import Link from '@mui/material/Link';
|
|
||||||
import Stack from '@mui/material/Stack';
|
|
||||||
import TextField from '@mui/material/TextField';
|
|
||||||
import Typography from '@mui/material/Typography';
|
|
||||||
|
|
||||||
import { visuallyHidden } from '@mui/utils';
|
function Hero(){
|
||||||
|
|
||||||
export default function Hero() {
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<section id="home" className="bg-blue-50 py-20">
|
||||||
id="hero"
|
<div className="container mx-auto text-center">
|
||||||
sx={(theme) => ({
|
<h1 className="text-5xl font-bold text-gray-800">
|
||||||
width: '100%',
|
Generate Your NIF, NISS, and Cart<EFBFBD>o de Cidad<EFBFBD>o Easily
|
||||||
backgroundImage:
|
</h1>
|
||||||
theme.palette.mode === 'light'
|
<p className="mt-4 text-gray-600">
|
||||||
? 'radial-gradient(ellipse 80% 50% at 50% -20%, hsl(210, 100%, 90%), transparent)'
|
Use our simple and efficient platform to generate valid testing numbers quickly.
|
||||||
: 'radial-gradient(ellipse 80% 50% at 50% -20%, hsl(210, 100%, 16%), transparent)',
|
</p>
|
||||||
backgroundRepeat: 'no-repeat',
|
<div className="mt-6">
|
||||||
})}
|
<a href="#generate" className="px-6 py-3 bg-blue-600 text-white font-semibold rounded-lg shadow-md hover:bg-blue-700">
|
||||||
>
|
Get Started
|
||||||
<Container
|
</a>
|
||||||
sx={{
|
</div>
|
||||||
display: 'flex',
|
</div>
|
||||||
flexDirection: 'column',
|
</section>
|
||||||
alignItems: 'center',
|
|
||||||
pt: { xs: 14, sm: 20 },
|
|
||||||
pb: { xs: 8, sm: 12 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Stack
|
|
||||||
spacing={2}
|
|
||||||
alignItems="center"
|
|
||||||
useFlexGap
|
|
||||||
sx={{ width: { xs: '100%', sm: '70%' } }}
|
|
||||||
>
|
|
||||||
<Typography
|
|
||||||
variant="h1"
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: { xs: 'column', sm: 'row' },
|
|
||||||
alignItems: 'center',
|
|
||||||
fontSize: 'clamp(3rem, 10vw, 3.5rem)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Our latest
|
|
||||||
<Typography
|
|
||||||
component="span"
|
|
||||||
variant="h1"
|
|
||||||
sx={{
|
|
||||||
fontSize: 'inherit',
|
|
||||||
color: (theme) =>
|
|
||||||
theme.palette.mode === 'light' ? 'primary.main' : 'primary.light',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
products
|
|
||||||
</Typography>
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
textAlign="center"
|
|
||||||
color="text.secondary"
|
|
||||||
sx={{ width: { sm: '100%', md: '80%' } }}
|
|
||||||
>
|
|
||||||
Explore our cutting-edge dashboard, delivering high-quality solutions
|
|
||||||
tailored to your needs. Elevate your experience with top-tier features
|
|
||||||
and services.
|
|
||||||
</Typography>
|
|
||||||
<Stack
|
|
||||||
direction={{ xs: 'column', sm: 'row' }}
|
|
||||||
spacing={1}
|
|
||||||
useFlexGap
|
|
||||||
sx={{ pt: 2, width: { xs: '100%', sm: 'auto' } }}
|
|
||||||
>
|
|
||||||
<InputLabel htmlFor="email-hero" sx={visuallyHidden}>
|
|
||||||
Email
|
|
||||||
</InputLabel>
|
|
||||||
<TextField
|
|
||||||
id="email-hero"
|
|
||||||
hiddenLabel
|
|
||||||
size="small"
|
|
||||||
variant="outlined"
|
|
||||||
aria-label="Enter your email address"
|
|
||||||
placeholder="Your email address"
|
|
||||||
inputProps={{
|
|
||||||
autocomplete: 'off',
|
|
||||||
ariaLabel: 'Enter your email address',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Button variant="contained" color="primary">
|
|
||||||
Start now
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
<Typography variant="caption" textAlign="center">
|
|
||||||
By clicking "Start now" you agree to our
|
|
||||||
<Link href="#" color="primary">
|
|
||||||
Terms & Conditions
|
|
||||||
</Link>
|
|
||||||
.
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
<Box
|
|
||||||
id="image"
|
|
||||||
sx={(theme) => ({
|
|
||||||
mt: { xs: 8, sm: 10 },
|
|
||||||
alignSelf: 'center',
|
|
||||||
height: { xs: 200, sm: 700 },
|
|
||||||
width: '100%',
|
|
||||||
backgroundImage:
|
|
||||||
theme.palette.mode === 'light'
|
|
||||||
? 'url("/static/images/templates/templates-images/hero-light.png")'
|
|
||||||
: 'url("/static/images/templates/templates-images/hero-dark.png")',
|
|
||||||
backgroundSize: 'cover',
|
|
||||||
borderRadius: '12px',
|
|
||||||
outline: '1px solid',
|
|
||||||
outlineColor:
|
|
||||||
theme.palette.mode === 'light'
|
|
||||||
? 'hsla(220, 25%, 80%, 0.5)'
|
|
||||||
: 'hsla(210, 100%, 80%, 0.1)',
|
|
||||||
boxShadow:
|
|
||||||
theme.palette.mode === 'light'
|
|
||||||
? '0 0 12px 8px hsla(220, 25%, 80%, 0.2)'
|
|
||||||
: '0 0 24px 12px hsla(210, 100%, 25%, 0.2)',
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</Container>
|
|
||||||
</Box>
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default Hero;
|
||||||
|
|||||||
108
geradoresfe/src/components/Navbar.tsx
Normal file
108
geradoresfe/src/components/Navbar.tsx
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { Transition } from '@headlessui/react';
|
||||||
|
import { MoonIcon, SunIcon } from '@heroicons/react/24/outline';
|
||||||
|
import Logo from '../assets/logotipo.png';
|
||||||
|
|
||||||
|
|
||||||
|
const Navbar = () => {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const [darkMode, setDarkMode] = useState(false);
|
||||||
|
|
||||||
|
// Apply dark mode based on the toggle state
|
||||||
|
useEffect(() => {
|
||||||
|
if (darkMode) {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
}
|
||||||
|
}, [darkMode]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="bg-blue-900 dark:bg-gray-800 shadow-lg sticky top-0 z-50">
|
||||||
|
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="flex justify-between items-center h-16">
|
||||||
|
|
||||||
|
{/* Logo e Nome da Marca */}
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<img src={Logo} alt="FactoryID Logo" className="h-8 w-auto" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Desktop Navigation Links */}
|
||||||
|
<div className="hidden md:flex space-x-8">
|
||||||
|
<a href="#home" className="text-gray-800 dark:text-white hover:text-yellow-300 transition duration-300 transform hover:scale-110">
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
<a href="#features" className="text-gray-800 dark:text-white hover:text-yellow-300 transition duration-300 transform hover:scale-110">
|
||||||
|
Features
|
||||||
|
</a>
|
||||||
|
<a href="#contact" className="text-gray-800 dark:text-white hover:text-yellow-300 transition duration-300 transform hover:scale-110">
|
||||||
|
Contact
|
||||||
|
</a>
|
||||||
|
<a href="#get-started" className="bg-yellow-300 text-gray-800 px-4 py-2 rounded-lg shadow-md hover:bg-yellow-400 transition duration-300">
|
||||||
|
Get Started
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Dark Mode Toggle */}
|
||||||
|
<div className="flex items-center space-x-4">
|
||||||
|
<button
|
||||||
|
onClick={() => setDarkMode(!darkMode)}
|
||||||
|
className="flex items-center px-2 py-1 rounded-md bg-gray-200 dark:bg-gray-700 dark:text-gray-200 text-gray-800 hover:bg-gray-300 dark:hover:bg-gray-600"
|
||||||
|
>
|
||||||
|
{darkMode ? (
|
||||||
|
<SunIcon className="h-6 w-6 text-yellow-400" />
|
||||||
|
) : (
|
||||||
|
<MoonIcon className="h-6 w-6 text-blue-500" />
|
||||||
|
)}
|
||||||
|
<span className="ml-2">{darkMode ? 'Light Mode' : 'Dark Mode'}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Mobile Menu Button */}
|
||||||
|
<button
|
||||||
|
onClick={() => setIsOpen(!isOpen)}
|
||||||
|
type="button"
|
||||||
|
className="text-gray-800 dark:text-white md:hidden"
|
||||||
|
aria-controls="mobile-menu"
|
||||||
|
aria-expanded="false"
|
||||||
|
>
|
||||||
|
<span className="sr-only">Open main menu</span>
|
||||||
|
<svg className="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d={isOpen ? "M6 18L18 6M6 6l12 12" : "M4 6h16M4 12h16M4 18h16"} />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Menu Dropdown */}
|
||||||
|
<Transition
|
||||||
|
show={isOpen}
|
||||||
|
enter="transition ease-out duration-200 transform"
|
||||||
|
enterFrom="opacity-0 -translate-y-2"
|
||||||
|
enterTo="opacity-100 translate-y-0"
|
||||||
|
leave="transition ease-in duration-150 transform"
|
||||||
|
leaveFrom="opacity-100 translate-y-0"
|
||||||
|
leaveTo="opacity-0 -translate-y-2"
|
||||||
|
>
|
||||||
|
<div className="md:hidden bg-gray-200 dark:bg-gray-700" id="mobile-menu">
|
||||||
|
<div className="px-2 pt-2 pb-3 space-y-1 sm:px-3">
|
||||||
|
<a href="#home" className="block px-3 py-2 rounded-md text-gray-800 dark:text-white hover:bg-purple-600">
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
<a href="#features" className="block px-3 py-2 rounded-md text-gray-800 dark:text-white hover:bg-purple-600">
|
||||||
|
Features
|
||||||
|
</a>
|
||||||
|
<a href="#contact" className="block px-3 py-2 rounded-md text-gray-800 dark:text-white hover:bg-purple-600">
|
||||||
|
Contact
|
||||||
|
</a>
|
||||||
|
<a href="#get-started" className="block px-3 py-2 rounded-md bg-yellow-300 text-gray-800 text-center">
|
||||||
|
Get Started
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Navbar;
|
||||||
@@ -1,13 +1,3 @@
|
|||||||
body {
|
@tailwind base;
|
||||||
margin: 0;
|
@tailwind components;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
@tailwind utilities;
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
||||||
sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
|
||||||
monospace;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import ReactDOM from 'react-dom/client';
|
|||||||
import './index.css';
|
import './index.css';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import reportWebVitals from './reportWebVitals';
|
import reportWebVitals from './reportWebVitals';
|
||||||
import { Helmet } from 'react-helmet'
|
//import { Helmet } from 'react-helmet'
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(
|
const root = ReactDOM.createRoot(
|
||||||
document.getElementById('root') as HTMLElement
|
document.getElementById('root') as HTMLElement
|
||||||
|
|||||||
11
geradoresfe/tailwind.config.js
Normal file
11
geradoresfe/tailwind.config.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
darkMode: 'class', // Enable dark mode with a class
|
||||||
|
content: [
|
||||||
|
"./src/**/*.{js,jsx,ts,tsx}",
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
}
|
||||||
6
package-lock.json
generated
Normal file
6
package-lock.json
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "Geradores",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {}
|
||||||
|
}
|
||||||
1
package.json
Normal file
1
package.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
Reference in New Issue
Block a user