diff --git a/GeradoresService/CC.cs b/GeradoresService/CC.cs index 483d9d4..fd375bf 100644 --- a/GeradoresService/CC.cs +++ b/GeradoresService/CC.cs @@ -1,46 +1,81 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace GeradoresService { - internal class CC + public static class CartaoCidadao { - - /*static bool Validate(string CardNumber) + // Função estática para gerar o número de documento + public static string Generate() { - int sum = 0; - bool alternate = false; + Random rand = new Random(); - // Percorre os dígitos do número de trás para frente - for (int i = creditCardNumber.Length - 1; i >= 0; i--) + // Gerar o Número de Identificação Civil (8 dígitos) + string numeroIdentificacaoCivil = rand.Next(0, 100000000).ToString("D8"); + + // Gerar o Check Digit C + int checkDigitC = CalcularCheckDigit(numeroIdentificacaoCivil); + + // Gerar a Versão (duas letras ou números aleatórios entre A-Z ou 0-9) + string versao = GerarVersao(); + + // Gerar o Check Digit T (Número aleatório entre 0-9) + int checkDigitT = rand.Next(0, 10); // T: Número aleatório por enquanto, conforme exemplo. + + // Montar o número completo do documento com o formato desejado + string numeroDocumento = $"{numeroIdentificacaoCivil} {checkDigitC} {versao}{checkDigitT}"; + + return numeroDocumento; + } + + // Função para calcular o Check Digit C com base no Número de Identificação Civil + private static int CalcularCheckDigit(string numeroIdentificacaoCivil) + { + int soma = 0; + bool segundoElemento = false; + + // Percorrer o número da direita para a esquerda + for (int i = numeroIdentificacaoCivil.Length - 1; i >= 0; i--) { - int digit = creditCardNumber[i] - '0'; + int valor = numeroIdentificacaoCivil[i] - '0'; // Converte o char para inteiro - // Se é um dígito - if (digit >= 0 && digit <= 9) + // Multiplicar cada segundo número por 2 + if (segundoElemento) { - if (alternate) - { - digit *= 2; - if (digit > 9) - digit -= 9; - } + valor *= 2; + if (valor >= 10) valor -= 9; // Subtrair 9 se o valor for maior ou igual a 10 + } - sum += digit; - alternate = !alternate; + soma += valor; + segundoElemento = !segundoElemento; + } + + // Retornar o check digit (resto da soma por 10) + return soma % 10; + } + + // Função para gerar a versão (letras ou números) + private static string GerarVersao() + { + Random rand = new Random(); + string versao = ""; + + for (int i = 0; i < 2; i++) // Gerar duas letras/números + { + int numeroAleatorio = rand.Next(0, 36); // 26 letras + 10 números + + if (numeroAleatorio < 26) + { + // Gerar uma letra de A a Z + versao += (char)('A' + numeroAleatorio); } else { - // Se não é um dígito, o número é inválido - return false; + // Gerar um número de 0 a 9 + versao += (char)('0' + (numeroAleatorio - 26)); } } - // O número de cartão de crédito é válido se a soma for divisível por 10 - return sum % 10 == 0; - }*/ + return versao; + } } } diff --git a/GeradoresService/NIF.cs b/GeradoresService/NIF.cs index 47bc127..e2a7a94 100644 --- a/GeradoresService/NIF.cs +++ b/GeradoresService/NIF.cs @@ -1,6 +1,8 @@ using GeradoresService.DAL; +using System; using System.ComponentModel; -using System.Net.NetworkInformation; +using System.Linq; +using System.Text.Json.Serialization; namespace GeradoresService { @@ -13,6 +15,7 @@ namespace GeradoresService _geradoresContext = geradoresContext; } + [JsonConverter(typeof(JsonStringEnumConverter))] public enum NIFType { [Description("Pessoa singular (1)")] @@ -37,102 +40,58 @@ namespace GeradoresService PessoaColectivaIrregular = 9 } - public string Generate(string? type) + public string Generate(NIFType? type) { var nif = GenerateRandomNIF(type); - //SaveNIF(nif); return nif; } - public string GenerateRandomNIF(string? nifType) + public string GenerateRandomNIF(NIFType? nifType) { - var firstDigitValidate = new char[] { '1', '2', '3', '5', '6', '8', '9' }; - Random rnd = new Random(); char firstDigit; + Random rnd = new Random(); - if (string.IsNullOrEmpty(nifType)) + if (nifType.HasValue) { - // Gera o primeiro dígito aleatório dentro dos válidos - int firstDigitIndex = rnd.Next(0, 6); // Escolhe um índice de 0 a 5 - firstDigit = firstDigitValidate[firstDigitIndex]; + firstDigit = ((int)nifType.Value).ToString()[0]; } else { - if (firstDigitValidate.Contains(nifType[0])) - { - firstDigit = nifType[0]; - } - else - { - int firstDigitIndex = rnd.Next(0, 6); // Escolhe um índice de 0 a 5 - firstDigit = firstDigitValidate[firstDigitIndex]; - } + var validFirstDigits = Enum.GetValues(typeof(NIFType)).Cast().Select(v => v.ToString()[0]).ToArray(); + firstDigit = validFirstDigits[rnd.Next(validFirstDigits.Length)]; } - // Gera os próximos 7 dígitos aleatórios - string nextDigits = ""; + string nextDigits = string.Concat(Enumerable.Range(0, 7).Select(_ => rnd.Next(0, 10).ToString())); + + int checkDigit = (firstDigit - '0') * 9; for (int i = 0; i < 7; i++) { - nextDigits += rnd.Next(0, 10); // Gera um dígito aleatório de 0 a 9 - } - - // Calcula o dígito de controlo - int checkDigit = (firstDigit - '0') * 9; - for (int i = 2; i <= 8; i++) - { - checkDigit += (nextDigits[i - 2] - '0') * (10 - i); + checkDigit += (nextDigits[i] - '0') * (8 - i); } checkDigit = 11 - (checkDigit % 11); if (checkDigit >= 10) checkDigit = 0; - // Concatena os dígitos gerados e o dígito de controlo - string randomNIF = firstDigit + nextDigits + checkDigit; - - return randomNIF; + return firstDigit + nextDigits + checkDigit; } public bool Validate(string nif) { - // Verificar se o NIF tem 9 dígitos - if (nif.Length != 9) - { + if (nif.Length != 9 || !nif.All(char.IsDigit)) return false; - } - // Converter o NIF para um array de dígitos - int[] digitos = new int[9]; - for (int i = 0; i < 9; i++) - { - if (!int.TryParse(nif[i].ToString(), out digitos[i])) - { - return false; // Se algum caractere não for um dígito, o NIF é inválido - } - } + int[] digitos = nif.Select(c => c - '0').ToArray(); + int soma = digitos.Take(8).Select((num, i) => num * (9 - i)).Sum(); + int digitoControlo = (11 - (soma % 11)) % 10; - // Calcular o dígito de controlo - int soma = 0; - for (int i = 0; i < 8; i++) - { - soma += digitos[i] * (9 - i); - } - int resto = soma % 11; - int digitoControlo = resto <= 1 ? 0 : 11 - resto; - - // Verificar se o dígito de controlo coincide com o último dígito do NIF return digitoControlo == digitos[8]; } public void SaveNIF(string NIF) { - var ger = new Geradore() - { - Valor = NIF - }; - + var ger = new Geradore() { Valor = NIF }; _geradoresContext.Geradores.Add(ger); _geradoresContext.SaveChanges(); } - } -} \ No newline at end of file +} diff --git a/GeradoresWS/Controllers/GenerateController.cs b/GeradoresWS/Controllers/GenerateController.cs index 20850d8..91b6faf 100644 --- a/GeradoresWS/Controllers/GenerateController.cs +++ b/GeradoresWS/Controllers/GenerateController.cs @@ -15,14 +15,8 @@ namespace GeradoresWS.Controllers } #region NIF - [HttpGet("GetNIFTypes")] - public List GetNIFTypes() - { - return new List(); - } - [HttpGet("GenerateNIF")] - public string GenerateNIF(string? type) + public string GenerateNIF(NIF.NIFType type) { var nif = new NIF(_context); return nif.Generate(type); @@ -49,5 +43,13 @@ namespace GeradoresWS.Controllers return NISS.Validate(nif); } #endregion + + #region CC + [HttpGet("GenerateCC")] + public string GenerateCC() + { + return CartaoCidadao.Generate(); + } + #endregion } } diff --git a/GeradoresWS/Filters/EnumDescriptionFilter.cs b/GeradoresWS/Filters/EnumDescriptionFilter.cs new file mode 100644 index 0000000..afdb4b7 --- /dev/null +++ b/GeradoresWS/Filters/EnumDescriptionFilter.cs @@ -0,0 +1,65 @@ +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using System.ComponentModel; + +namespace Primus.ProfitabilityModel.WebAPI.Filters +{ + public class EnumDescriptionFilter : ISchemaFilter + { + public void Apply(OpenApiSchema schema, SchemaFilterContext context) + { + if (context.Type.IsEnum) + { + // Obter os valores do enum + var enumValues = Enum.GetValues(context.Type) + .Cast() + .ToList(); + + // Obter os nomes dos enums + var enumNames = enumValues.Select(e => e.ToString()).ToList(); + + // Obter as descrições dos enums + var enumDescriptions = enumValues.Select(e => GetEnumDescription(e)).ToList(); + + // Adicionar as extensões com os nomes e descrições + var enumNamesArray = new OpenApiArray(); + foreach (var name in enumNames) + { + enumNamesArray.Add(new OpenApiString(name)); + } + + var enumDescriptionsArray = new OpenApiArray(); + foreach (var description in enumDescriptions) + { + enumDescriptionsArray.Add(new OpenApiString(description)); + } + + schema.Extensions.Add("x-enumNames", enumDescriptionsArray); + schema.Extensions.Add("x-enumDescriptions", enumDescriptionsArray); + + // Adicionar os valores do enum ao campo Enum + schema.Enum = enumNames + .Select(name => new OpenApiString(name)) + .Cast() + .ToList(); + } + } + + private static string GetEnumDescription(Enum value) + { + // Verificar se o campo é nulo antes de chamar GetCustomAttribute + var field = value.GetType().GetField(value.ToString()); + if (field == null) + { + return value.ToString(); // Se o campo for nulo, retorna o nome do valor do enum + } + + // Acessa o atributo Description, caso exista + var attribute = (DescriptionAttribute)Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)); + + // Retorna a descrição ou o nome do valor do enum, se a descrição não estiver presente + return attribute?.Description ?? value.ToString(); + } + } +} diff --git a/GeradoresWS/Program.cs b/GeradoresWS/Program.cs index 9953e63..f9c26fc 100644 --- a/GeradoresWS/Program.cs +++ b/GeradoresWS/Program.cs @@ -1,15 +1,35 @@ using GeradoresService.DAL; using Microsoft.EntityFrameworkCore; +using Microsoft.OpenApi.Models; +using Primus.ProfitabilityModel.WebAPI.Filters; +using System.Text.Json.Serialization; var builder = WebApplication.CreateBuilder(args); // Add services to the container. - -builder.Services.AddControllers(); +builder.Services.AddControllers().AddJsonOptions(options => +{ + options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); +}); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddSwaggerGen(); +builder.Services.AddSwaggerGen(options => +{ + options.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); + options.SwaggerDoc("v1", new OpenApiInfo + { + Version = "v1", + Title = "FactoryId", + Contact = new OpenApiContact + { + Name = "Marco Santos" + }, + }); + + // Registra o filtro de esquema que aplica descries para todos os enums + options.SchemaFilter(); +}); var connectionString = builder.Configuration.GetConnectionString("GeradoresConnection"); diff --git a/UnitTest/DB.cs b/UnitTest/DB.cs index 631d94b..05b99da 100644 --- a/UnitTest/DB.cs +++ b/UnitTest/DB.cs @@ -31,8 +31,8 @@ namespace UnitTest public void GenerateNIF() { var nif = new NIF(_context); - var gerenatednif = nif.Generate("2"); - Assert.NotEmpty(gerenatednif); + //var gerenatednif = nif.Generate("2"); + //Assert.NotEmpty(gerenatednif); } } } \ No newline at end of file diff --git a/UnitTest/Geradores.cs b/UnitTest/Geradores.cs new file mode 100644 index 0000000..e0c2364 --- /dev/null +++ b/UnitTest/Geradores.cs @@ -0,0 +1,19 @@ +using GeradoresService; +using GeradoresService.DAL; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; + +namespace UnitTest +{ + public class Geradores + { + private readonly GeradoresContext _context; + + [Fact] + public void GenerateCC() + { + var cc = CartaoCidadao.Generate(); + Console.WriteLine(cc); + } + } +} \ No newline at end of file diff --git a/geradoresfe/.env b/geradoresfe/.env index dd278cd..e88a86e 100644 --- a/geradoresfe/.env +++ b/geradoresfe/.env @@ -1 +1 @@ -REACT_APP_API_URL=https://localhost:44329/ \ No newline at end of file +VITE_API_URL=https://localhost:44329/ \ No newline at end of file diff --git a/geradoresfe/.gitignore b/geradoresfe/.gitignore index 18c0012..a547bf3 100644 --- a/geradoresfe/.gitignore +++ b/geradoresfe/.gitignore @@ -1,28 +1,24 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - +# Logs +logs +*.log npm-debug.log* yarn-debug.log* yarn-error.log* -.vercel +pnpm-debug.log* +lerna-debug.log* -package-lock.json -yarn-lock.json -pnpm-lock.json +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/geradoresfe/README.md b/geradoresfe/README.md index b87cb00..7959ce4 100644 --- a/geradoresfe/README.md +++ b/geradoresfe/README.md @@ -1,46 +1,69 @@ -# Getting Started with Create React App +# React + TypeScript + Vite -This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. -## Available Scripts +Currently, two official plugins are available: -In the project directory, you can run: +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh -### `npm start` +## Expanding the ESLint configuration -Runs the app in the development mode.\ -Open [http://localhost:3000](http://localhost:3000) to view it in the browser. +If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: -The page will reload if you make edits.\ -You will also see any lint errors in the console. +```js +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... -### `npm test` + // Remove tseslint.configs.recommended and replace with this + ...tseslint.configs.recommendedTypeChecked, + // Alternatively, use this for stricter rules + ...tseslint.configs.strictTypeChecked, + // Optionally, add this for stylistic rules + ...tseslint.configs.stylisticTypeChecked, -Launches the test runner in the interactive watch mode.\ -See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. + // Other configs... + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` -### `npm run build` +You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: -Builds the app for production to the `build` folder.\ -It correctly bundles React in production mode and optimizes the build for the best performance. +```js +// eslint.config.js +import reactX from 'eslint-plugin-react-x' +import reactDom from 'eslint-plugin-react-dom' -The build is minified and the filenames include the hashes.\ -Your app is ready to be deployed! - -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. - -### `npm run eject` - -**Note: this is a one-way operation. Once you `eject`, you can’t go back!** - -If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. - -Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. - -You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. - -## Learn More - -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). - -To learn React, check out the [React documentation](https://reactjs.org/). +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + // Enable lint rules for React + reactX.configs['recommended-typescript'], + // Enable lint rules for React DOM + reactDom.configs.recommended, + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` diff --git a/geradoresfe/eslint.config.js b/geradoresfe/eslint.config.js new file mode 100644 index 0000000..d94e7de --- /dev/null +++ b/geradoresfe/eslint.config.js @@ -0,0 +1,23 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { globalIgnores } from 'eslint/config' + +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs['recommended-latest'], + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + }, +]) diff --git a/geradoresfe/index.html b/geradoresfe/index.html new file mode 100644 index 0000000..72b02f8 --- /dev/null +++ b/geradoresfe/index.html @@ -0,0 +1,13 @@ + + + + + + + Factory Id + + +
+ + + diff --git a/geradoresfe/nuget.config b/geradoresfe/nuget.config deleted file mode 100644 index 6548586..0000000 --- a/geradoresfe/nuget.config +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/geradoresfe/package.json b/geradoresfe/package.json index 9ca1bc7..1af4f62 100644 --- a/geradoresfe/package.json +++ b/geradoresfe/package.json @@ -1,75 +1,43 @@ { - "name": "tailadmin-react-free", - "version": "2.0.0", - "dependencies": { - "@fullcalendar/core": "^6.1.15", - "@fullcalendar/daygrid": "^6.1.15", - "@fullcalendar/interaction": "^6.1.15", - "@fullcalendar/list": "^6.1.15", - "@fullcalendar/react": "^6.1.15", - "@fullcalendar/timegrid": "^6.1.15", - "@react-jvectormap/core": "^1.0.4", - "@react-jvectormap/world": "^1.1.2", - "@tailwindcss/forms": "^0.5.9", - "@testing-library/jest-dom": "^5.17.0", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^13.5.0", - "@types/jest": "^27.5.2", - "@types/node": "^16.18.119", - "@types/react": "^18.3.12", - "@types/react-dom": "^18.3.1", - "apexcharts": "^4.1.0", - "autoprefixer": "^10.4.20", - "axios": "^1.8.1", - "classnames": "^2.5.1", - "clsx": "^2.1.1", - "flatpickr": "^4.6.13", - "lucide-react": "^0.477.0", - "motion": "^12.4.10", - "postcss": "^8.4.49", - "react": "^18.3.1", - "react-apexcharts": "^1.6.0", - "react-dnd": "^16.0.1", - "react-dnd-html5-backend": "^16.0.1", - "react-dom": "^18.3.1", - "react-dropzone": "^14.3.5", - "react-flatpickr": "^3.10.13", - "react-helmet": "^6.1.0", - "react-helmet-async": "^2.0.5", - "react-router": "^7.0.1", - "react-scripts": "5.0.1", - "react-simple-maps": "^3.0.0", - "swiper": "^11.1.15", - "tailwind-merge": "^2.6.0", - "typescript": "^4.9.5", - "web-vitals": "^2.1.4" - }, + "name": "geradoresfe", + "private": true, + "version": "1.0.0", + "type": "module", "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] + "dependencies": { + "@headlessui/react": "^2.2.4", + "@heroicons/react": "^2.2.0", + "@tailwindcss/vite": "^4.1.11", + "axios": "^1.10.0", + "lucide-react": "^0.525.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-hot-toast": "^2.5.2", + "react-router": "^7.6.3", + "react-router-dom": "^7.6.3", + "tailwind-merge": "^3.3.1" }, "devDependencies": { - "@types/react-flatpickr": "^3.8.11", - "tailwindcss": "^3.4.15" + "@eslint/js": "^9.30.1", + "@tailwindcss/postcss": "^4.1.11", + "@types/node": "^24.0.13", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "autoprefixer": "^10.4.21", + "eslint": "^9.30.1", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "globals": "^16.3.0", + "postcss": "^8.5.6", + "tailwindcss": "^4.1.11", + "typescript": "~5.8.3", + "typescript-eslint": "^8.35.1", + "vite": "^7.0.4" } } diff --git a/geradoresfe/postcss.config.cjs b/geradoresfe/postcss.config.cjs new file mode 100644 index 0000000..fcb25d2 --- /dev/null +++ b/geradoresfe/postcss.config.cjs @@ -0,0 +1,6 @@ +module.exports = { + plugins: [ + require('@tailwindcss/postcss'), + require('autoprefixer'), + ], +} \ No newline at end of file diff --git a/geradoresfe/public/index.html b/geradoresfe/public/index.html deleted file mode 100644 index 7d64e7e..0000000 --- a/geradoresfe/public/index.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - -
- - - diff --git a/geradoresfe/public/logo192.png b/geradoresfe/public/logo192.png deleted file mode 100644 index fc44b0a..0000000 Binary files a/geradoresfe/public/logo192.png and /dev/null differ diff --git a/geradoresfe/public/logo512.png b/geradoresfe/public/logo512.png deleted file mode 100644 index a4e47a6..0000000 Binary files a/geradoresfe/public/logo512.png and /dev/null differ diff --git a/geradoresfe/public/manifest.json b/geradoresfe/public/manifest.json deleted file mode 100644 index 080d6c7..0000000 --- a/geradoresfe/public/manifest.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" -} diff --git a/geradoresfe/public/robots.txt b/geradoresfe/public/robots.txt deleted file mode 100644 index e9e57dc..0000000 --- a/geradoresfe/public/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Disallow: diff --git a/geradoresfe/src/Api/GeradorApi.tsx b/geradoresfe/src/Api/GeradorApi.tsx index bfbc091..5229300 100644 --- a/geradoresfe/src/Api/GeradorApi.tsx +++ b/geradoresfe/src/Api/GeradorApi.tsx @@ -1,6 +1,8 @@ -import axios, { AxiosResponse } from 'axios'; +import axios from 'axios'; +import type { AxiosResponse } from 'axios'; +import { NIFType } from '../service/api'; -const API_URL = process.env.REACT_APP_API_URL; +const API_URL = import.meta.env.VITE_API_URL; class GeradorService { static async GenerateNIF(type: string | null): Promise { @@ -18,6 +20,21 @@ class GeradorService { } } + static async ValidateNIF(type: string | null): Promise { + try { + const response: AxiosResponse = await axios.get(API_URL + 'Generate/ValidateNIF', + { + params: { + type: type + } + }); + return response.data; + } catch (error) { + console.error('Error fetching NIF:', error); + return []; + } + } + static async GenerateNISS(): Promise { try { @@ -28,6 +45,17 @@ class GeradorService { return []; } } + + static async GenerateCC(): Promise { + try { + + const response: AxiosResponse = await axios.get(API_URL + 'Generate/GenerateCC'); + return response.data; + } catch (error) { + console.error('Error fetching NIF:', error); + return []; + } + } } export default GeradorService; \ No newline at end of file diff --git a/geradoresfe/src/icons/angle-left.svg b/geradoresfe/src/App.css similarity index 100% rename from geradoresfe/src/icons/angle-left.svg rename to geradoresfe/src/App.css diff --git a/geradoresfe/src/App.test.tsx b/geradoresfe/src/App.test.tsx deleted file mode 100644 index 2a68616..0000000 --- a/geradoresfe/src/App.test.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import App from './App'; - -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); diff --git a/geradoresfe/src/App.tsx b/geradoresfe/src/App.tsx index defee17..1dbe89d 100644 --- a/geradoresfe/src/App.tsx +++ b/geradoresfe/src/App.tsx @@ -1,37 +1,22 @@ -import { Route, BrowserRouter as Router, Routes } from "react-router"; -import AppLayout from "./layout/AppLayout"; -import AuthLayout from "./layout/AuthLayout"; -import SignIn from "./pages/AuthPages/SignIn"; -import SignUp from "./pages/AuthPages/SignUp"; -import Blank from "./pages/Blank"; +import { Routes, Route, BrowserRouter as Router } from 'react-router-dom'; +import { Toaster } from 'react-hot-toast'; +import Home from './pages/Home'; +import { Layout } from './layout/Layout'; -import Home from "./pages/Home"; -import GenerateNIF from "./pages/GenerateNIF"; -import GenerateNISS from "./pages/GenerateNISS"; -import GenerateCC from "./pages/GenerateCC"; - -export default function App() { - return ( - <> - - - {/* Dashboard Layout */} - }> - } /> - } /> - } /> - } /> - - - {/* Auth Layout */} - }> - } /> - } /> - - - {/* Fallback Route */} - - - - ); +function App() { + return ( + + + + } /> + + + + + + + + ); } + +export default App; \ No newline at end of file diff --git a/geradoresfe/src/assets/logotipo.png b/geradoresfe/src/assets/logotipo.png index 061270f..eb824d1 100644 Binary files a/geradoresfe/src/assets/logotipo.png and b/geradoresfe/src/assets/logotipo.png differ diff --git a/geradoresfe/src/assets/logotipo32x32.png b/geradoresfe/src/assets/logotipo32x32.png new file mode 100644 index 0000000..544911d Binary files /dev/null and b/geradoresfe/src/assets/logotipo32x32.png differ diff --git a/geradoresfe/src/assets/react.svg b/geradoresfe/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/geradoresfe/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/geradoresfe/src/components/Geradores/GeradorCard.tsx b/geradoresfe/src/components/Geradores/GeradorCard.tsx new file mode 100644 index 0000000..ccf6d58 --- /dev/null +++ b/geradoresfe/src/components/Geradores/GeradorCard.tsx @@ -0,0 +1,111 @@ +import React, { useState } from "react"; +import { RefreshCwIcon, CopyIcon } from "lucide-react"; +import { Button } from "../ui/Button"; +import { Input } from "../ui/Input"; +import { Select } from "../ui/Select"; // Import do Select moderno +import { ResultDisplay } from "../ui/ResultDisplay"; +import { ButtonGroup } from "../ui/ButtonGroup"; + +type Parametro = + | { nome: string; tipo: "text" | "number" | "password"; placeholder?: string } + | { nome: string; tipo: "select"; options: { label: string; value: string }[] }; + +type GeradorCardProps = { + titulo: string; + descricao?: string; + parametros?: Parametro[]; + onGerar: (parametros?: Record) => string | Promise; + onValidar?: (valor: string) => boolean | Promise; +}; + +export default function GeradorCard({ + titulo, + descricao, + parametros = [], + onGerar, + onValidar, +}: GeradorCardProps) { + const [resultado, setResultado] = useState(""); + const [paramInputs, setParamInputs] = useState>({}); + const [validado, setValidado] = useState(null); + + const handleInputChange = (nome: string, valor: string) => { + setParamInputs((prev) => ({ ...prev, [nome]: valor })); + }; + + const handleGerar = async () => { + const gerado = await onGerar(paramInputs); + setResultado(gerado); + setValidado(null); + }; + + const handleValidar = async () => { + if (onValidar) { + const isValid = await onValidar(resultado); + setValidado(isValid); + } + }; + + const handleCopiar = () => { + navigator.clipboard.writeText(resultado); + }; + + return ( +
+
+

{titulo}

+ {descricao &&

{descricao}

} +
+ + {parametros.length > 0 && ( +
+ {parametros.map((param) => { + if (param.tipo === "select") { + return ( + handleInputChange(param.nome, e.target.value)} + /> + ); + })} +
+ )} + +
+ +
+ + + + + + + {onValidar && ( + + )} + +
+ ); +} diff --git a/geradoresfe/src/components/Geradores/Tipos/GenerateNIF.tsx b/geradoresfe/src/components/Geradores/Tipos/GenerateNIF.tsx new file mode 100644 index 0000000..00b7bc4 --- /dev/null +++ b/geradoresfe/src/components/Geradores/Tipos/GenerateNIF.tsx @@ -0,0 +1,44 @@ +import React from "react"; +import GeradorCard from "../GeradorCard"; +import { EnumToOptions } from "../../../library/utils"; +import { NIFType } from "../../../service/api"; + +const NifTypes = EnumToOptions(NIFType).map((opt) => ({ + label: opt.label, + value: opt.value, +})); + +const GenerateNIF = () => { + const handleGenerateNIF = async (params: Record) => { + const tipoSelecionado = params["Tipo de NIF"]; + // Aqui chamarias a tua API real, exemplo: + // const nif = await GeradorService.GenerateNIF({ type: tipoSelecionado }); + // Para simular: + return `NIF-${tipoSelecionado}-${Math.floor(Math.random() * 1000000)}`; + }; + + const handleValidateNIF = async (valor: string) => { + // Lógica real de validação + return valor.startsWith("NIF-"); + }; + + return ( +
+ +
+ ); +}; + +export default GenerateNIF; diff --git a/geradoresfe/src/components/Logo.tsx b/geradoresfe/src/components/Logo.tsx new file mode 100644 index 0000000..7e0c269 --- /dev/null +++ b/geradoresfe/src/components/Logo.tsx @@ -0,0 +1,6 @@ +// components/Logo.tsx +import logo from '../assets/Logotipo.png'; + +export const Logo = () => ( + FactoryId logo +); diff --git a/geradoresfe/src/components/UserProfile/UserAddressCard.tsx b/geradoresfe/src/components/UserProfile/UserAddressCard.tsx deleted file mode 100644 index a8131e2..0000000 --- a/geradoresfe/src/components/UserProfile/UserAddressCard.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import { useModal } from "../../hooks/useModal"; -import { Modal } from "../ui/modal"; -import Button from "../ui/button/Button"; -import Input from "../form/input/InputField"; -import Label from "../form/Label"; - -export default function UserAddressCard() { - const { isOpen, openModal, closeModal } = useModal(); - const handleSave = () => { - // Handle save logic here - console.log("Saving changes..."); - closeModal(); - }; - return ( - <> -
-
-
-

- Address -

- -
-
-

- Country -

-

- United States -

-
- -
-

- City/State -

-

- Phoenix, Arizona, United States -

-
- -
-

- Postal Code -

-

- ERT 2489 -

-
- -
-

- TAX ID -

-

- AS4568384 -

-
-
-
- - -
-
- -
-
-

- Edit Address -

-

- Update your details to keep your profile up-to-date. -

-
-
-
-
-
- - -
- -
- - -
- -
- - -
- -
- - -
-
-
-
- - -
-
-
-
- - ); -} diff --git a/geradoresfe/src/components/UserProfile/UserInfoCard.tsx b/geradoresfe/src/components/UserProfile/UserInfoCard.tsx deleted file mode 100644 index 18fdcba..0000000 --- a/geradoresfe/src/components/UserProfile/UserInfoCard.tsx +++ /dev/null @@ -1,185 +0,0 @@ -import React from "react"; -import { useModal } from "../../hooks/useModal"; -import { Modal } from "../ui/modal"; -import Button from "../ui/button/Button"; -import Input from "../form/input/InputField"; -import Label from "../form/Label"; - -export default function UserInfoCard() { - const { isOpen, openModal, closeModal } = useModal(); - const handleSave = () => { - // Handle save logic here - console.log("Saving changes..."); - closeModal(); - }; - return ( -
-
-
-

- Personal Information -

- -
-
-

- First Name -

-

- Musharof -

-
- -
-

- Last Name -

-

- Chowdhury -

-
- -
-

- Email address -

-

- randomuser@pimjo.com -

-
- -
-

- Phone -

-

- +09 363 398 46 -

-
- -
-

- Bio -

-

- Team Manager -

-
-
-
- - -
- - -
-
-

- Edit Personal Information -

-

- Update your details to keep your profile up-to-date. -

-
-
-
-
-
- Social Links -
- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
-
-
-
-
- Personal Information -
- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
-
-
-
-
- - -
-
-
-
-
- ); -} diff --git a/geradoresfe/src/components/UserProfile/UserMetaCard.tsx b/geradoresfe/src/components/UserProfile/UserMetaCard.tsx deleted file mode 100644 index cc52dbe..0000000 --- a/geradoresfe/src/components/UserProfile/UserMetaCard.tsx +++ /dev/null @@ -1,217 +0,0 @@ -import React from "react"; -import { useModal } from "../../hooks/useModal"; -import { Modal } from "../ui/modal"; -import Button from "../ui/button/Button"; -import Input from "../form/input/InputField"; -import Label from "../form/Label"; - -export default function UserMetaCard() { - const { isOpen, openModal, closeModal } = useModal(); - const handleSave = () => { - // Handle save logic here - console.log("Saving changes..."); - closeModal(); - }; - return ( - <> -
-
-
-
- user -
-
-

- Musharof Chowdhury -

-
-

- Team Manager -

-
-

- Arizona, United States -

-
-
-
- - - - - - - -
-
- -
-
- -
-
-

- Edit Personal Information -

-

- Update your details to keep your profile up-to-date. -

-
-
-
-
-
- Social Links -
- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
-
-
-
-
- Personal Information -
- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
-
-
-
-
- - -
-
-
-
- - ); -} diff --git a/geradoresfe/src/components/charts/bar/BarChartOne.tsx b/geradoresfe/src/components/charts/bar/BarChartOne.tsx deleted file mode 100644 index 4737efd..0000000 --- a/geradoresfe/src/components/charts/bar/BarChartOne.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import React from "react"; -import Chart from "react-apexcharts"; -import { ApexOptions } from "apexcharts"; - -export default function BarChartOne() { - const options: ApexOptions = { - colors: ["#465fff"], - chart: { - fontFamily: "Outfit, sans-serif", - type: "bar", - height: 180, - toolbar: { - show: false, - }, - }, - plotOptions: { - bar: { - horizontal: false, - columnWidth: "39%", - borderRadius: 5, - borderRadiusApplication: "end", - }, - }, - dataLabels: { - enabled: false, - }, - stroke: { - show: true, - width: 4, - colors: ["transparent"], - }, - xaxis: { - categories: [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ], - axisBorder: { - show: false, - }, - axisTicks: { - show: false, - }, - }, - legend: { - show: true, - position: "top", - horizontalAlign: "left", - fontFamily: "Outfit", - }, - yaxis: { - title: { - text: undefined, - }, - }, - grid: { - yaxis: { - lines: { - show: true, - }, - }, - }, - fill: { - opacity: 1, - }, - - tooltip: { - x: { - show: false, - }, - y: { - formatter: (val: number) => `${val}`, - }, - }, - }; - const series = [ - { - name: "Sales", - data: [168, 385, 201, 298, 187, 195, 291, 110, 215, 390, 280, 112], - }, - ]; - return ( -
-
- -
-
- ); -} diff --git a/geradoresfe/src/components/charts/line/LineChartOne.tsx b/geradoresfe/src/components/charts/line/LineChartOne.tsx deleted file mode 100644 index 6c0760e..0000000 --- a/geradoresfe/src/components/charts/line/LineChartOne.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import React from "react"; -import Chart from "react-apexcharts"; -import { ApexOptions } from "apexcharts"; - -export default function LineChartOne() { - const options: ApexOptions = { - legend: { - show: false, // Hide legend - position: "top", - horizontalAlign: "left", - }, - colors: ["#465FFF", "#9CB9FF"], // Define line colors - chart: { - fontFamily: "Outfit, sans-serif", - height: 310, - type: "line", // Set the chart type to 'line' - toolbar: { - show: false, // Hide chart toolbar - }, - }, - stroke: { - curve: "straight", // Define the line style (straight, smooth, or step) - width: [2, 2], // Line width for each dataset - }, - - fill: { - type: "gradient", - gradient: { - opacityFrom: 0.55, - opacityTo: 0, - }, - }, - markers: { - size: 0, // Size of the marker points - strokeColors: "#fff", // Marker border color - strokeWidth: 2, - hover: { - size: 6, // Marker size on hover - }, - }, - grid: { - xaxis: { - lines: { - show: false, // Hide grid lines on x-axis - }, - }, - yaxis: { - lines: { - show: true, // Show grid lines on y-axis - }, - }, - }, - dataLabels: { - enabled: false, // Disable data labels - }, - tooltip: { - enabled: true, // Enable tooltip - x: { - format: "dd MMM yyyy", // Format for x-axis tooltip - }, - }, - xaxis: { - type: "category", // Category-based x-axis - categories: [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ], - axisBorder: { - show: false, // Hide x-axis border - }, - axisTicks: { - show: false, // Hide x-axis ticks - }, - tooltip: { - enabled: false, // Disable tooltip for x-axis points - }, - }, - yaxis: { - labels: { - style: { - fontSize: "12px", // Adjust font size for y-axis labels - colors: ["#6B7280"], // Color of the labels - }, - }, - title: { - text: "", // Remove y-axis title - style: { - fontSize: "0px", - }, - }, - }, - }; - - const series = [ - { - name: "Sales", - data: [180, 190, 170, 160, 175, 165, 170, 205, 230, 210, 240, 235], - }, - { - name: "Revenue", - data: [40, 30, 50, 40, 55, 40, 70, 100, 110, 120, 150, 140], - }, - ]; - return ( -
-
- -
-
- ); -} diff --git a/geradoresfe/src/components/common/ChartTab.tsx b/geradoresfe/src/components/common/ChartTab.tsx deleted file mode 100644 index d2f5820..0000000 --- a/geradoresfe/src/components/common/ChartTab.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import React, { useState } from "react"; - -const ChartTab: React.FC = () => { - const [selected, setSelected] = useState< - "optionOne" | "optionTwo" | "optionThree" - >("optionOne"); - - const getButtonClass = (option: "optionOne" | "optionTwo" | "optionThree") => - selected === option - ? "shadow-theme-xs text-gray-900 dark:text-white bg-white dark:bg-gray-800" - : "text-gray-500 dark:text-gray-400"; - - return ( -
- - - - - -
- ); -}; - -export default ChartTab; diff --git a/geradoresfe/src/components/common/ComponentCard.tsx b/geradoresfe/src/components/common/ComponentCard.tsx deleted file mode 100644 index 36e0486..0000000 --- a/geradoresfe/src/components/common/ComponentCard.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from "react"; - -interface ComponentCardProps { - title?: string; // O título agora é opcional - children: React.ReactNode; - className?: string; // Additional custom classes for styling - desc?: string; // Description text -} - -const ComponentCard: React.FC = ({ - title, - children, - className = "", - desc = "", -}) => { - return ( -
- {/* Card Header - Só renderiza se o título for passado */} - {title && ( -
-

- {title} -

- {desc && ( -

- {desc} -

- )} -
- )} - - {/* Card Body */} -
-
{children}
-
-
- ); -}; - -export default ComponentCard; diff --git a/geradoresfe/src/components/common/CountdownTimer.tsx b/geradoresfe/src/components/common/CountdownTimer.tsx deleted file mode 100644 index d275d85..0000000 --- a/geradoresfe/src/components/common/CountdownTimer.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React, { useState, useEffect } from "react"; - -interface CountdownTimerProps { - targetDate: Date; -} - -const CountdownTimer: React.FC = ({ targetDate }) => { - const [timeLeft, setTimeLeft] = useState({ - days: 0, - hours: 0, - minutes: 0, - seconds: 0, - }); - - useEffect(() => { - const timer = setInterval(() => { - const now = new Date(); - const difference = targetDate.getTime() - now.getTime(); - - if (difference > 0) { - const days = Math.floor(difference / (1000 * 60 * 60 * 24)); - const hours = Math.floor((difference / (1000 * 60 * 60)) % 24); - const minutes = Math.floor((difference / 1000 / 60) % 60); - const seconds = Math.floor((difference / 1000) % 60); - - setTimeLeft({ days, hours, minutes, seconds }); - } else { - clearInterval(timer); - } - }, 1000); - - return () => clearInterval(timer); - }, [targetDate]); - - const formatTime = (time: number): string => { - return time.toString().padStart(2, "0"); - }; - - return ( -
-
-
- {formatTime(timeLeft.days)} -
- : -
- {formatTime(timeLeft.hours)} -
- : -
- {formatTime(timeLeft.minutes)} -
- : -
- {formatTime(timeLeft.seconds)} -
-
- -
- - {timeLeft.days} - - {timeLeft.days === 1 ? " day" : " days"} left -
-
- ); -}; - -export default CountdownTimer; diff --git a/geradoresfe/src/components/common/GridShape.tsx b/geradoresfe/src/components/common/GridShape.tsx deleted file mode 100644 index fd9c443..0000000 --- a/geradoresfe/src/components/common/GridShape.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from "react"; - -export default function GridShape() { - return ( - <> -
- grid -
-
- grid -
- - ); -} diff --git a/geradoresfe/src/components/common/PageBreadCrumb.tsx b/geradoresfe/src/components/common/PageBreadCrumb.tsx deleted file mode 100644 index c148f38..0000000 --- a/geradoresfe/src/components/common/PageBreadCrumb.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import React from "react"; -import { Link } from "react-router"; - -interface BreadcrumbProps { - pageTitle: string; -} - -const PageBreadcrumb: React.FC = ({ pageTitle }) => { - return ( -
-

- {pageTitle} -

- -
- ); -}; - -export default PageBreadcrumb; diff --git a/geradoresfe/src/components/common/PageMeta.tsx b/geradoresfe/src/components/common/PageMeta.tsx deleted file mode 100644 index 7beedb5..0000000 --- a/geradoresfe/src/components/common/PageMeta.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from "react"; -import { HelmetProvider, Helmet } from "react-helmet-async"; - -const PageMeta = ({ - title, - description, -}: { - title: string; - description: string; -}) => ( - - {title} - - -); - -export const AppWrapper = ({ children }: { children: React.ReactNode }) => ( - {children} -); - -export default PageMeta; diff --git a/geradoresfe/src/components/common/ThemeToggleButton.tsx b/geradoresfe/src/components/common/ThemeToggleButton.tsx deleted file mode 100644 index c30456b..0000000 --- a/geradoresfe/src/components/common/ThemeToggleButton.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from "react"; -import { useTheme } from "../../context/ThemeContext"; - -export const ThemeToggleButton: React.FC = () => { - const { toggleTheme } = useTheme(); - - return ( - - ); -}; diff --git a/geradoresfe/src/components/ecommerce/CountryMap.tsx b/geradoresfe/src/components/ecommerce/CountryMap.tsx deleted file mode 100644 index b62dfb9..0000000 --- a/geradoresfe/src/components/ecommerce/CountryMap.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import React from "react"; -// react plugin for creating vector maps -import { VectorMap } from "@react-jvectormap/core"; -import { worldMill } from "@react-jvectormap/world"; - -// Define the component props -interface CountryMapProps { - mapColor?: string; -} - -const CountryMap: React.FC = ({ mapColor }) => { - return ( - - ); -}; - -export default CountryMap; diff --git a/geradoresfe/src/components/ecommerce/DemographicCard.tsx b/geradoresfe/src/components/ecommerce/DemographicCard.tsx deleted file mode 100644 index 9aa4ca1..0000000 --- a/geradoresfe/src/components/ecommerce/DemographicCard.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import { useState } from "react"; -import { Dropdown } from "../ui/dropdown/Dropdown"; -import { DropdownItem } from "../ui/dropdown/DropdownItem"; -import CountryMap from "./CountryMap"; -import { MoreDotIcon } from "../../icons"; - -export default function DemographicCard() { - const [isOpen, setIsOpen] = useState(false); - - function toggleDropdown() { - setIsOpen(!isOpen); - } - - function closeDropdown() { - setIsOpen(false); - } - return ( -
-
-
-

- Customers Demographic -

-

- Number of customer based on country -

-
- -
- - - - View More - - - Delete - - -
-
-
-
- -
-
- -
-
-
-
- usa -
-
-

- USA -

- - 2,379 Customers - -
-
- -
-
-
-
-

- 79% -

-
-
- -
-
-
- france -
-
-

- France -

- - 589 Customers - -
-
- -
-
-
-
-

- 23% -

-
-
-
-
- ); -} diff --git a/geradoresfe/src/components/ecommerce/EcommerceMetrics.tsx b/geradoresfe/src/components/ecommerce/EcommerceMetrics.tsx deleted file mode 100644 index b4d4383..0000000 --- a/geradoresfe/src/components/ecommerce/EcommerceMetrics.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import React from "react"; -import { - ArrowDownIcon, - ArrowUpIcon, - BoxIconLine, - GroupIcon, -} from "../../icons"; -import Badge from "../ui/badge/Badge"; - -export default function EcommerceMetrics() { - return ( -
- {/* */} -
-
- -
- -
-
- - Customers - -

- 3,782 -

-
- - - 11.01% - -
-
- {/* */} - - {/* */} -
-
- -
-
-
- - Orders - -

- 5,359 -

-
- - - - 9.05% - -
-
- {/* */} -
- ); -} diff --git a/geradoresfe/src/components/ecommerce/MonthlySalesChart.tsx b/geradoresfe/src/components/ecommerce/MonthlySalesChart.tsx deleted file mode 100644 index b8b442e..0000000 --- a/geradoresfe/src/components/ecommerce/MonthlySalesChart.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import Chart from "react-apexcharts"; -import { ApexOptions } from "apexcharts"; -import { MoreDotIcon } from "../../icons"; -import { Dropdown } from "../ui/dropdown/Dropdown"; -import { DropdownItem } from "../ui/dropdown/DropdownItem"; -import { useState } from "react"; - -export default function MonthlySalesChart() { - const options: ApexOptions = { - colors: ["#465fff"], - chart: { - fontFamily: "Outfit, sans-serif", - type: "bar", - height: 180, - toolbar: { - show: false, - }, - }, - plotOptions: { - bar: { - horizontal: false, - columnWidth: "39%", - borderRadius: 5, - borderRadiusApplication: "end", - }, - }, - dataLabels: { - enabled: false, - }, - stroke: { - show: true, - width: 4, - colors: ["transparent"], - }, - xaxis: { - categories: [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ], - axisBorder: { - show: false, - }, - axisTicks: { - show: false, - }, - }, - legend: { - show: true, - position: "top", - horizontalAlign: "left", - fontFamily: "Outfit", - }, - yaxis: { - title: { - text: undefined, - }, - }, - grid: { - yaxis: { - lines: { - show: true, - }, - }, - }, - fill: { - opacity: 1, - }, - - tooltip: { - x: { - show: false, - }, - y: { - formatter: (val: number) => `${val}`, - }, - }, - }; - const series = [ - { - name: "Sales", - data: [168, 385, 201, 298, 187, 195, 291, 110, 215, 390, 280, 112], - }, - ]; - const [isOpen, setIsOpen] = useState(false); - - function toggleDropdown() { - setIsOpen(!isOpen); - } - - function closeDropdown() { - setIsOpen(false); - } - - return ( -
-
-

- Monthly Sales -

-
- - - - View More - - - Delete - - -
-
- -
-
- -
-
-
- ); -} diff --git a/geradoresfe/src/components/ecommerce/MonthlyTarget.tsx b/geradoresfe/src/components/ecommerce/MonthlyTarget.tsx deleted file mode 100644 index 6f544bb..0000000 --- a/geradoresfe/src/components/ecommerce/MonthlyTarget.tsx +++ /dev/null @@ -1,198 +0,0 @@ -import Chart from "react-apexcharts"; -import { ApexOptions } from "apexcharts"; -import { useState } from "react"; -import { MoreDotIcon } from "../../icons"; -import { Dropdown } from "../ui/dropdown/Dropdown"; -import { DropdownItem } from "../ui/dropdown/DropdownItem"; - -export default function MonthlyTarget() { - const series = [75.55]; - const options: ApexOptions = { - colors: ["#465FFF"], - chart: { - fontFamily: "Outfit, sans-serif", - type: "radialBar", - height: 330, - sparkline: { - enabled: true, - }, - }, - plotOptions: { - radialBar: { - startAngle: -85, - endAngle: 85, - hollow: { - size: "80%", - }, - track: { - background: "#E4E7EC", - strokeWidth: "100%", - margin: 5, // margin is in pixels - }, - dataLabels: { - name: { - show: false, - }, - value: { - fontSize: "36px", - fontWeight: "600", - offsetY: -40, - color: "#1D2939", - formatter: function (val) { - return val + "%"; - }, - }, - }, - }, - }, - fill: { - type: "solid", - colors: ["#465FFF"], - }, - stroke: { - lineCap: "round", - }, - labels: ["Progress"], - }; - const [isOpen, setIsOpen] = useState(false); - - function toggleDropdown() { - setIsOpen(!isOpen); - } - - function closeDropdown() { - setIsOpen(false); - } - return ( -
-
-
-
-

- Monthly Target -

-

- Target you’ve set for each month -

-
-
- - - - View More - - - Delete - - -
-
-
-
- -
- - - +10% - -
-

- You earn $3287 today, it's higher than last month. Keep up your good - work! -

-
- -
-
-

- Target -

-

- $20K - - - -

-
- -
- -
-

- Revenue -

-

- $20K - - - -

-
- -
- -
-

- Today -

-

- $20K - - - -

-
-
-
- ); -} diff --git a/geradoresfe/src/components/ecommerce/RecentOrders.tsx b/geradoresfe/src/components/ecommerce/RecentOrders.tsx deleted file mode 100644 index 903d8f5..0000000 --- a/geradoresfe/src/components/ecommerce/RecentOrders.tsx +++ /dev/null @@ -1,208 +0,0 @@ -import { - Table, - TableBody, - TableCell, - TableHeader, - TableRow, -} from "../ui/table"; -import Badge from "../ui/badge/Badge"; - -// Define the TypeScript interface for the table rows -interface Product { - id: number; // Unique identifier for each product - name: string; // Product name - variants: string; // Number of variants (e.g., "1 Variant", "2 Variants") - category: string; // Category of the product - price: string; // Price of the product (as a string with currency symbol) - // status: string; // Status of the product - image: string; // URL or path to the product image - status: "Delivered" | "Pending" | "Canceled"; // Status of the product -} - -// Define the table data using the interface -const tableData: Product[] = [ - { - id: 1, - name: "MacBook Pro 13”", - variants: "2 Variants", - category: "Laptop", - price: "$2399.00", - status: "Delivered", - image: "/images/product/product-01.jpg", // Replace with actual image URL - }, - { - id: 2, - name: "Apple Watch Ultra", - variants: "1 Variant", - category: "Watch", - price: "$879.00", - status: "Pending", - image: "/images/product/product-02.jpg", // Replace with actual image URL - }, - { - id: 3, - name: "iPhone 15 Pro Max", - variants: "2 Variants", - category: "SmartPhone", - price: "$1869.00", - status: "Delivered", - image: "/images/product/product-03.jpg", // Replace with actual image URL - }, - { - id: 4, - name: "iPad Pro 3rd Gen", - variants: "2 Variants", - category: "Electronics", - price: "$1699.00", - status: "Canceled", - image: "/images/product/product-04.jpg", // Replace with actual image URL - }, - { - id: 5, - name: "AirPods Pro 2nd Gen", - variants: "1 Variant", - category: "Accessories", - price: "$240.00", - status: "Delivered", - image: "/images/product/product-05.jpg", // Replace with actual image URL - }, -]; - -export default function RecentOrders() { - return ( -
-
-
-

- Recent Orders -

-
- -
- - -
-
-
- - {/* Table Header */} - - - - Products - - - Category - - - Price - - - Status - - - - - {/* Table Body */} - - - {tableData.map((product) => ( - - -
-
- {product.name} -
-
-

- {product.name} -

- - {product.variants} - -
-
-
- - {product.price} - - - {product.category} - - - - {product.status} - - -
- ))} -
-
-
-
- ); -} diff --git a/geradoresfe/src/components/ecommerce/StatisticsChart.tsx b/geradoresfe/src/components/ecommerce/StatisticsChart.tsx deleted file mode 100644 index 8376e61..0000000 --- a/geradoresfe/src/components/ecommerce/StatisticsChart.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import React from "react"; -import Chart from "react-apexcharts"; -import { ApexOptions } from "apexcharts"; -import ChartTab from "../common/ChartTab"; - -export default function StatisticsChart() { - const options: ApexOptions = { - legend: { - show: false, // Hide legend - position: "top", - horizontalAlign: "left", - }, - colors: ["#465FFF", "#9CB9FF"], // Define line colors - chart: { - fontFamily: "Outfit, sans-serif", - height: 310, - type: "line", // Set the chart type to 'line' - toolbar: { - show: false, // Hide chart toolbar - }, - }, - stroke: { - curve: "straight", // Define the line style (straight, smooth, or step) - width: [2, 2], // Line width for each dataset - }, - - fill: { - type: "gradient", - gradient: { - opacityFrom: 0.55, - opacityTo: 0, - }, - }, - markers: { - size: 0, // Size of the marker points - strokeColors: "#fff", // Marker border color - strokeWidth: 2, - hover: { - size: 6, // Marker size on hover - }, - }, - grid: { - xaxis: { - lines: { - show: false, // Hide grid lines on x-axis - }, - }, - yaxis: { - lines: { - show: true, // Show grid lines on y-axis - }, - }, - }, - dataLabels: { - enabled: false, // Disable data labels - }, - tooltip: { - enabled: true, // Enable tooltip - x: { - format: "dd MMM yyyy", // Format for x-axis tooltip - }, - }, - xaxis: { - type: "category", // Category-based x-axis - categories: [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ], - axisBorder: { - show: false, // Hide x-axis border - }, - axisTicks: { - show: false, // Hide x-axis ticks - }, - tooltip: { - enabled: false, // Disable tooltip for x-axis points - }, - }, - yaxis: { - labels: { - style: { - fontSize: "12px", // Adjust font size for y-axis labels - colors: ["#6B7280"], // Color of the labels - }, - }, - title: { - text: "", // Remove y-axis title - style: { - fontSize: "0px", - }, - }, - }, - }; - - const series = [ - { - name: "Sales", - data: [180, 190, 170, 160, 175, 165, 170, 205, 230, 210, 240, 235], - }, - { - name: "Revenue", - data: [40, 30, 50, 40, 55, 40, 70, 100, 110, 120, 150, 140], - }, - ]; - return ( -
-
-
-

- Statistics -

-

- Target you’ve set for each month -

-
-
- -
-
- -
-
- -
-
-
- ); -} diff --git a/geradoresfe/src/components/form/Form.tsx b/geradoresfe/src/components/form/Form.tsx deleted file mode 100644 index 0530a6a..0000000 --- a/geradoresfe/src/components/form/Form.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React, { FC, ReactNode, FormEvent } from "react"; - -interface FormProps { - onSubmit: (event: FormEvent) => void; - children: ReactNode; - className?: string; -} - -const Form: FC = ({ onSubmit, children, className }) => { - return ( -
{ - event.preventDefault(); // Prevent default form submission - onSubmit(event); - }} - className={` ${className}`} // Default spacing between form fields - > - {children} -
- ); -}; - -export default Form; diff --git a/geradoresfe/src/components/form/Label.tsx b/geradoresfe/src/components/form/Label.tsx deleted file mode 100644 index 8b0628b..0000000 --- a/geradoresfe/src/components/form/Label.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import React, { FC, ReactNode } from "react"; -import { twMerge } from "tailwind-merge"; - -interface LabelProps { - htmlFor?: string; - children: ReactNode; - className?: string; -} - -const Label: FC = ({ htmlFor, children, className }) => { - return ( - - ); -}; - -export default Label; diff --git a/geradoresfe/src/components/form/MultiSelect.tsx b/geradoresfe/src/components/form/MultiSelect.tsx deleted file mode 100644 index d25f7d1..0000000 --- a/geradoresfe/src/components/form/MultiSelect.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import React, { useState } from "react"; - -interface Option { - value: string; - text: string; - selected: boolean; -} - -interface MultiSelectProps { - label: string; - options: Option[]; - defaultSelected?: string[]; - onChange?: (selected: string[]) => void; - disabled?: boolean; -} - -const MultiSelect: React.FC = ({ - label, - options, - defaultSelected = [], - onChange, - disabled = false, -}) => { - const [selectedOptions, setSelectedOptions] = - useState(defaultSelected); - const [isOpen, setIsOpen] = useState(false); - - const toggleDropdown = () => { - if (disabled) return; - setIsOpen((prev) => !prev); - }; - - const handleSelect = (optionValue: string) => { - const newSelectedOptions = selectedOptions.includes(optionValue) - ? selectedOptions.filter((value) => value !== optionValue) - : [...selectedOptions, optionValue]; - - setSelectedOptions(newSelectedOptions); - if (onChange) onChange(newSelectedOptions); - }; - - const removeOption = (index: number, value: string) => { - const newSelectedOptions = selectedOptions.filter((opt) => opt !== value); - setSelectedOptions(newSelectedOptions); - if (onChange) onChange(newSelectedOptions); - }; - - const selectedValuesText = selectedOptions.map( - (value) => options.find((option) => option.value === value)?.text || "" - ); - - return ( -
- - -
-
-
-
-
- {selectedValuesText.length > 0 ? ( - selectedValuesText.map((text, index) => ( -
- {text} -
-
- removeOption(index, selectedOptions[index]) - } - className="pl-2 text-gray-500 cursor-pointer group-hover:text-gray-400 dark:text-gray-400" - > - - - -
-
-
- )) - ) : ( - - )} -
-
- -
-
-
- - {isOpen && ( -
e.stopPropagation()} - > -
- {options.map((option, index) => ( -
-
handleSelect(option.value)} - > -
-
- {option.text} -
-
-
-
- ))} -
-
- )} -
-
-
- ); -}; - -export default MultiSelect; diff --git a/geradoresfe/src/components/form/Select.tsx b/geradoresfe/src/components/form/Select.tsx deleted file mode 100644 index e2f3c6a..0000000 --- a/geradoresfe/src/components/form/Select.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import React, { useState } from "react"; - -interface Option { - value: string; - label: string; -} - -interface SelectProps { - options: Option[]; - placeholder?: string; - onChange: (value: string) => void; - className?: string; - defaultValue?: string; -} - -const Select: React.FC = ({ - options, - placeholder = "Select an option", - onChange, - className = "", - defaultValue = "", -}) => { - // Manage the selected value - const [selectedValue, setSelectedValue] = useState(defaultValue); - - const handleChange = (e: React.ChangeEvent) => { - const value = e.target.value; - setSelectedValue(value); - onChange(value); // Trigger parent handler - }; - - return ( - - ); -}; - -export default Select; diff --git a/geradoresfe/src/components/form/form-elements/CheckboxComponents.tsx b/geradoresfe/src/components/form/form-elements/CheckboxComponents.tsx deleted file mode 100644 index 213416e..0000000 --- a/geradoresfe/src/components/form/form-elements/CheckboxComponents.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React, { useState } from "react"; -import ComponentCard from "../../common/ComponentCard"; -import Checkbox from "../input/Checkbox"; - -export default function CheckboxComponents() { - const [isChecked, setIsChecked] = useState(false); - const [isCheckedTwo, setIsCheckedTwo] = useState(true); - const [isCheckedDisabled, setIsCheckedDisabled] = useState(true); - return ( - -
-
- - - Default - -
-
- -
-
- -
-
-
- ); -} diff --git a/geradoresfe/src/components/form/form-elements/DefaultInputs.tsx b/geradoresfe/src/components/form/form-elements/DefaultInputs.tsx deleted file mode 100644 index 504325c..0000000 --- a/geradoresfe/src/components/form/form-elements/DefaultInputs.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import React, { useState } from "react"; -import ComponentCard from "../../common/ComponentCard"; -import Label from "../Label"; -import Input from "../input/InputField"; -import Select from "../Select"; -import { CalenderIcon, EyeCloseIcon, EyeIcon, TimeIcon } from "../../../icons"; - -export default function DefaultInputs() { - const [showPassword, setShowPassword] = useState(false); - const options = [ - { value: "marketing", label: "Marketing" }, - { value: "template", label: "Template" }, - { value: "development", label: "Development" }, - ]; - const handleSelectChange = (value: string) => { - console.log("Selected value:", value); - }; - return ( - -
-
- - -
-
- - -
-
- - - -
-
-
- -
- console.log(e.target.value)} - /> - - - -
-
-
- -
- console.log(e.target.value)} - /> - - - -
-
-
- -
- - - - - - - - -
-
- -
- ); -} diff --git a/geradoresfe/src/components/form/form-elements/DropZone.tsx b/geradoresfe/src/components/form/form-elements/DropZone.tsx deleted file mode 100644 index 064e7f5..0000000 --- a/geradoresfe/src/components/form/form-elements/DropZone.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React from "react"; -import ComponentCard from "../../common/ComponentCard"; -import { useDropzone } from "react-dropzone"; -// import Dropzone from "react-dropzone"; - -const DropzoneComponent: React.FC = () => { - const onDrop = (acceptedFiles: File[]) => { - console.log("Files dropped:", acceptedFiles); - // Handle file uploads here - }; - - const { getRootProps, getInputProps, isDragActive } = useDropzone({ - onDrop, - accept: { - "image/png": [], - "image/jpeg": [], - "image/webp": [], - "image/svg+xml": [], - }, - }); - return ( - -
-
- {/* Hidden Input */} - - -
- {/* Icon Container */} -
-
- - - -
-
- - {/* Text Content */} -

- {isDragActive ? "Drop Files Here" : "Drag & Drop Files Here"} -

- - - Drag and drop your PNG, JPG, WebP, SVG images here or browse - - - - Browse File - -
-
-
-
- ); -}; - -export default DropzoneComponent; diff --git a/geradoresfe/src/components/form/form-elements/FileInputExample.tsx b/geradoresfe/src/components/form/form-elements/FileInputExample.tsx deleted file mode 100644 index e2a977a..0000000 --- a/geradoresfe/src/components/form/form-elements/FileInputExample.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from "react"; -import ComponentCard from "../../common/ComponentCard"; -import FileInput from "../input/FileInput"; -import Label from "../Label"; - -export default function FileInputExample() { - const handleFileChange = (event: React.ChangeEvent) => { - const file = event.target.files?.[0]; - if (file) { - console.log("Selected file:", file.name); - } - }; - - return ( - -
- - -
-
- ); -} diff --git a/geradoresfe/src/components/form/form-elements/InputGroup.tsx b/geradoresfe/src/components/form/form-elements/InputGroup.tsx deleted file mode 100644 index 2e7208e..0000000 --- a/geradoresfe/src/components/form/form-elements/InputGroup.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import React from "react"; -import ComponentCard from "../../common/ComponentCard"; -import Label from "../Label"; -import Input from "../input/InputField"; -import { EnvelopeIcon } from "../../../icons"; -import PhoneInput from "../group-input/PhoneInput"; - -export default function InputGroup() { - const countries = [ - { code: "US", label: "+1" }, - { code: "GB", label: "+44" }, - { code: "CA", label: "+1" }, - { code: "AU", label: "+61" }, - ]; - const handlePhoneNumberChange = (phoneNumber: string) => { - console.log("Updated phone number:", phoneNumber); - }; - return ( - -
-
- -
- - - - -
-
-
- - -
{" "} -
- - -
-
-
- ); -} diff --git a/geradoresfe/src/components/form/form-elements/InputStates.tsx b/geradoresfe/src/components/form/form-elements/InputStates.tsx deleted file mode 100644 index 6d93d62..0000000 --- a/geradoresfe/src/components/form/form-elements/InputStates.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React, { useState } from "react"; -import ComponentCard from "../../common/ComponentCard"; -import Input from "../input/InputField"; -import Label from "../Label"; - -export default function InputStates() { - const [email, setEmail] = useState(""); - const [error, setError] = useState(false); - - // Simulate a validation check - const validateEmail = (value: string) => { - const isValidEmail = - /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value); - setError(!isValidEmail); - return isValidEmail; - }; - - const handleEmailChange = (e: React.ChangeEvent) => { - const value = e.target.value; - setEmail(value); - validateEmail(value); - }; - return ( - -
- {/* Error Input */} -
- - -
- - {/* Success Input */} -
- - -
- - {/* Disabled Input */} -
- - -
-
-
- ); -} diff --git a/geradoresfe/src/components/form/form-elements/RadioButtons.tsx b/geradoresfe/src/components/form/form-elements/RadioButtons.tsx deleted file mode 100644 index 0ad1c21..0000000 --- a/geradoresfe/src/components/form/form-elements/RadioButtons.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { useState } from "react"; -import ComponentCard from "../../common/ComponentCard"; -import Radio from "../input/Radio"; - -export default function RadioButtons() { - const [selectedValue, setSelectedValue] = useState("option2"); - - const handleRadioChange = (value: string) => { - setSelectedValue(value); - }; - return ( - -
- - - -
-
- ); -} diff --git a/geradoresfe/src/components/form/form-elements/SelectInputs.tsx b/geradoresfe/src/components/form/form-elements/SelectInputs.tsx deleted file mode 100644 index 95989ed..0000000 --- a/geradoresfe/src/components/form/form-elements/SelectInputs.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import React, { useState } from "react"; -import ComponentCard from "../../common/ComponentCard"; -import Label from "../Label"; -import Select from "../Select"; -import MultiSelect from "../MultiSelect"; - -export default function SelectInputs() { - const options = [ - { value: "marketing", label: "Marketing" }, - { value: "template", label: "Template" }, - { value: "development", label: "Development" }, - ]; - const handleSelectChange = (value: string) => { - console.log("Selected value:", value); - }; - const [selectedValues, setSelectedValues] = useState([]); - - const multiOptions = [ - { value: "1", text: "Option 1", selected: false }, - { value: "2", text: "Option 2", selected: false }, - { value: "3", text: "Option 3", selected: false }, - { value: "4", text: "Option 4", selected: false }, - { value: "5", text: "Option 5", selected: false }, - ]; - return ( - -
-
- -