Crud, react Js (Front-end), .Net 6 (Back-end) Banco SqLServer

Crud, react Js (Front-end), .Net 6 (Back-end) Banco SqLServer

Criar em qualquer vers?o mais ressente do microsoft Sql Server um banco de dados conforme a figura acima.

Vamos utilizar o visual studio para constru??o da Api Back-end e visual code para o front-end.

N?o irei entrar em detalhes sobre o que cada comando faz, mais podem conferir aqui nesse link para o back-end https://learn.microsoft.com/en-us/dotnet/ , https://learn.microsoft.com/pt-br/training/dotnet/ e para o front-end https://pt-br.reactjs.org/ esses link′s é possível entender e aprender o que cada comando faz.

Crie uma tabela no banco de dados conforme a figura abaixo.

N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem

N?o esque?a de colocar o campo (ID) como auto incremento, vou deixar o codigo da cria??o da tabela aqui, caso precisem.

USE [ColaboradorDB]

GO


/****** Object:?Table [dbo].[tb_tutorials]??Script Date: 05/02/2023 07:01:57 ******/

SET ANSI_NULLS ON

GO


SET QUOTED_IDENTIFIER ON

GO


CREATE TABLE [dbo].[tb_tutorials](

[id] [int] IDENTITY(1,1) NOT NULL,

[title] [nvarchar](100) NULL,

[description] [nvarchar](100) NULL,

[published] [nvarchar](100) NULL,

[status] [nvarchar](100) NULL

) ON [PRIMARY]


GO

N?o foi fornecido texto alternativo para esta imagem


Também é possível utilizar o modo Design para deixar o campo ID como auto incremento

Selecione o campo ID e nas op??es na grid abaixo do Sql Server selecione SIM e automaticamente é para aparecer nas duas op??es abaixo do campo identidade os valores 1,1. conforme a figura abaixo.

N?o foi fornecido texto alternativo para esta imagem

Feito isso, vamos criar a API em .net, vamos ao visual studio e crie uma aplica??o vazia, conforme a figura abaixo.

N?o foi fornecido texto alternativo para esta imagem

No próximo passo diga o nome do seu projeto.

N?o foi fornecido texto alternativo para esta imagem

No próximo passo algumas configura??es, desmarque ou n?o a op??o HTTPS, nesse exemplo n?o foi marcada.

N?o foi fornecido texto alternativo para esta imagem

No visual studio vamos montar a seguinte estrutura.

N?o foi fornecido texto alternativo para esta imagem

Antes de iniciar a cria??o das classes, instale os pacotes nuget utilizado no projeto, essas diretivas s?o importantes para o projeto funcionar corretamente.

N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem

Agora vamos criar as classes e pastas no gerenciador de solu??es do visual studio.

Vamos criar: 3 Pastas (Data, EndPoints, Extensions)

E 4 Classes: (Tutorials.cs, TutorialsContext.cs, TutorialsEndPoints.cs, ServiceColletionsExtensions.cs)

Conforme a figura abaixo.

N?o foi fornecido texto alternativo para esta imagem

Antes de iniciar com a cria??o das classes, vou deixar aqui o .json que é responsável pela a conex?o. appsettings.json


N?o foi fornecido texto alternativo para esta imagem


{

?"ConnectionString": "Data Source=DESKTOP-XXXXX\\SQLXXXXXXXEXPRESS;Initial Catalog=ColaboradorDB;Integrated Security=True",


?"Logging": {

??"LogLevel": {

???"Default": "Information",

???"Microsoft.AspNetCore": "Warning"

??}

?},

?"AllowedHosts": "*"

}

Essa string de conex?o é retirada da tela inicial do SQL Server conforme a figura abaixo.

N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem

launchSettings.json

N?o foi fornecido texto alternativo para esta imagem

{

?"iisSettings": {

??"windowsAuthentication": false,

??"anonymousAuthentication": true,

??"iisExpress": {

???"applicationUrl": "https://localhost:51569",

???"sslPort": 0

??}

?},

?"profiles": {

??"WebApiTutorials": {

???"commandName": "Project",

???"dotnetRunMessages": true,

???"launchBrowser": true,

???"launchUrl": "swagger",

???"applicationUrl": "https://localhost:5235",

???"environmentVariables": {

????"ASPNETCORE_ENVIRONMENT": "Development"

???}

??},

??"IIS Express": {

???"commandName": "IISExpress",

???"launchBrowser": true,

???"launchUrl": "swagger",

???"environmentVariables": {

????"ASPNETCORE_ENVIRONMENT": "Development"

???}

??}

?}

}



Agora vamos as classes


Tutorials.cs


using System.ComponentModel.DataAnnotations.Schema;

using System.Collections.Generic;

using System.Threading.Tasks;

[Table("Tb_tutorials")]

public record Tb_tutorials(int id, string title, string description, string published, string status);

//public List<Tb_tutorials> Tutorials { get; set; }

public interface ITutolialsRepository

{

??Task<List<Tb_tutorials>> GetTutorialsAsync();

??Task<Tb_tutorials> GetTutorialsByIdAsync(int id);

??Task<Tb_tutorials> GetTutorialsEContadorAsync();

??Task<int> SaveAsync(Tb_tutorials novoTutorial);

??Task<int> UpdateTutolialisStatusAsync(Tb_tutorials atualizaTutorial);

??Task<int> DeleteAsync(int id);

}


TutorialsContext.cs


using System.Data;


public class TutorialsContext

{

??public delegate Task<IDbConnection> GetConnection();

}



TutorialsEndPoints.cs


//using Microsoft.Extensions.Configuration;

using System;

using System.Threading.Tasks;

using Dapper; // Ativa o QueryFirstOrDefault

using System.Data.SqlClient;

using Dapper.Contrib.Extensions;

using static TutorialsContext;

//using System.Web.Http.Cors;

//using System.Text.Json;

//using Dapper; // Ativa o QueryFirstOrDefault

public static class TutorialsEndpoints

{

??public static void MapTutorialsEndpoints(this WebApplication app)

??{

????//app.EnableCors();

????app.MapGet("/", () => "Mini Tutorials API");


????app.MapGet("/tutorials", async (GetConnection connectionGetter) =>

????{

??????using var con = await connectionGetter();

??????//return con.GetAll<Tb_tutorials>().ToList();

??????string query = "SELECT * FROM dbo.Tb_tutorials";

??????List<Tb_tutorials> tutorials?= (await con.QueryAsync<Tb_tutorials>(sql:query)).ToList();

??????return tutorials;?

????});


????app.MapGet("/tutorials/{id}", async (GetConnection connectionGetter, int id) =>

????{

??????using var con = await connectionGetter();

??????//return con.Get<Tb_tutorials>(id);

??????return con.QueryFirstOrDefault<Tb_tutorials>("SELECT " + "id, " + "title, " + "description, " + "published, " + "status " + "FROM dbo.Tb_tutorials " + "WHERE id = @id ", new { id = id });


????});

????

????app.MapGet("/pesq-tutorials/title", async (GetConnection connectionGetter, string title) =>

????{

??????using var con = await connectionGetter();

??????return?con.QueryFirstOrDefault<Tb_tutorials>("SELECT " +"id, " +"title, " +"description, "+ "published, " + "status " +"FROM dbo.Tb_tutorials " + "WHERE title = @title ", new { title = title });


????});

????app.MapDelete("/del-tutorials/{id}", async (GetConnection connectionGetter, int id) =>

????{

??????using var con = await connectionGetter();

??????return con.QueryFirstOrDefault<Tb_tutorials>("DELETE " + "FROM dbo.Tb_tutorials " + "WHERE id = @id ", new { id = id });


????});


????app.MapPost("/novo-tutorials", async (GetConnection connectionGetter, Tb_tutorials Tutorials) =>

????{

??????using var con = await connectionGetter();

??????//var id = con.Insert(Tutorials);

??????//return Results.Created($"/tutorials/{id}", Tutorials);

??????string command = @"INSERT INTO dbo.Tb_tutorials(title, description, published, status)VALUES(@title, @description, @published, @status)";

??????var result = await con.ExecuteAsync(sql: command, param: Tutorials);

??????return result;

????});


????app.MapPut("/put-in-tutorials/{id}", async (GetConnection connectionGetter, int id, Tb_tutorials Tutorials) =>

????{

??????if (id > 0)

??????{

????????using var con = await connectionGetter();

????????string command = @"UPDATE dbo.Tb_tutorials SET title = @title, description = @description WHERE Id = @Id";

????????var result = await con.ExecuteAsync(sql: command, param: Tutorials);

????????return result;

??????}

??????else

??????{

????????using var con = await connectionGetter();

????????string command = @"INSERT INTO dbo.Tb_tutorials(title, description, published, status)VALUES(@title, @description, @published, @status)";

????????var result = await con.ExecuteAsync(sql: command, param: Tutorials);

????????return result;

??????}


????});


????app.MapPut("/tutorials", async (GetConnection connectionGetter, Tb_tutorials Tutorials) =>

????{

???????

????????using var con = await connectionGetter();

????????string command = @"UPDATE dbo.Tb_tutorials SET title = @title, description = @description WHERE Id = @Id";

????????var result = await con.ExecuteAsync(sql: command, param: Tutorials);

????????return result;

????});


????app.MapPut("/up-status-tutorials", async (GetConnection connectionGetter, Tb_tutorials Tutorials) =>

????{


??????using var con = await connectionGetter();

??????string command = @"UPDATE dbo.Tb_tutorials SET published = @published WHERE Id = @Id";

??????var result = await con.ExecuteAsync(sql: command, param: Tutorials);

??????return result;

????});

????app.MapPut("/put-tutorials", async (GetConnection connectionGetter, Tb_tutorials Tutorials) =>

????{

??????using var con = await connectionGetter();

??????string command = @"UPDATE dbo.Tb_tutorials SET title = @title, description = @description WHERE Id = @Id";

??????var result = await con.ExecuteAsync(sql: command, param: Tutorials);

??????return result;


??????});

??}

}


ServiceColletionsExtensions.cs

using System.Data.SqlClient;

using static TutorialsContext;


public static class ServiceCollectionsExtensions

{

??public static WebApplicationBuilder AddPersistence(this WebApplicationBuilder builder)

??{

????builder.Services.AddScoped<GetConnection>(sp =>

?????async () =>

?????{

???????string connectionString = sp.GetService<IConfiguration>()["ConnectionString"];

???????var connection = new SqlConnection(connectionString);

???????await connection.OpenAsync();

???????return connection;

?????});


????return builder;

??}

}

Por fim a classe program.cs


#region [Cors]

var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";


var builder = WebApplication.CreateBuilder(args);


builder.Services.AddCors(options =>

{

??options.AddPolicy(MyAllowSpecificOrigins,

?????????????policy =>

?????????????{

???????????????policy.WithOrigins("https://localhost:5235",

?????????????????????????"https://localhost:3000",

?????????????????????????"https://localhost:3000/tutorials",

?????????????????????????"https://localhost:3000/put-tutorials",

?????????????????????????"https://localhost:5235/put-tutorials",

?????????????????????????"https://localhost:3000/put-in-tutorials/",

?????????????????????????"https://localhost:5235/put-in-tutorials/",

?????????????????????????"https://localhost:3000/del-tutorials",

?????????????????????????"https://localhost:3000/novo-tutorials",

?????????????????????????"https://localhost:3000/pesq-tutorials/title")

?????????????????????????.AllowAnyHeader()

?????????????????????????//.AllowAnyMethod();

???????????????.WithMethods("POST","PUT", "DELETE", "GET", "PATCH", "OPTIONS")

???????????????.AllowCredentials();


?????????????});

});

builder.Services.AddEndpointsApiExplorer();

builder.Services.AddSwaggerGen();

builder.AddPersistence();

var app = builder.Build();

app.UseCors(MyAllowSpecificOrigins);

app.MapTutorialsEndpoints();

app.UseSwagger();

app.UseSwaggerUI(c => { });

app.Run();

#endregion

Execute a aplica??o.

N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem

Por fim, esse é o back-end.

Para o React Js, instale o node Js e o NMP. utilize esse link para mais detalhes https://docs.npmjs.com/downloading-and-installing-node-js-and-npm

Crie um projeto novo react seguindo esses passos.

Passo 1:

?- Criar uma pasta na área de trabalho (Desktop)

Passo 2:

?- Abrir a CMD do Windows como administrador

Passo 3:

?- Executar comandos:

???1 - cd C:\Users\XXXXXX\Desktop\React?

?????????- Substitua pelo o caminho do seu projeto.

???2 - npm install react@16

???3 - npx create-react-app nome-pasta-primeiro-projeto

???4 - Para abrir o projeto criado no navegador.

?????????- Continuando na CMD, digite o comando:

????????????1 - cd nome-pasta-primeiro-projeto

????????????2 - npm start.

No terminal dentro da pasta do projeto digite

npm install axios

npm add react-table

npm install react-router-dom

npm install react-bootstrap bootstrap

Instale também o visual code com esse link https://code.visualstudio.com/download

Execute a aplica??o no visual code conforme a figura abaixo. Abra um New Terminal e execute o comando nmp start.

N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem

Run

N?o foi fornecido texto alternativo para esta imagem

A estrutura segui conforme a figura abaixo.

N?o foi fornecido texto alternativo para esta imagem

Ent?o precisamos criar no projeto esses arquivos.

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

with-rounter.js

AddTutorial.js

Tutorial.js

TutorialsList.js

TutorialService.js

App.css

App.js

http-common.js

index.css

index.js

Pesquisa.js

serviceWorker.js

Table.css

Table.js

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

with-rounter.js

import { useLocation, useNavigate, useParams } from "react-router-dom";


export const withRouter = (Component) => {

? function ComponentWithRouterProp(props) {

? ? let location = useLocation();

? ? let navigate = useNavigate();

? ? let params = useParams();

? ? return <Component {...props} router={{ location, navigate, params }} />;

? }

? return ComponentWithRouterProp;

};

AddTutorial.js

import React, { useState } from "react";

import TutorialDataService from "../services/TutorialService";


const AddTutorial = () => {

? const initialTutorialState = {

? ? id: null,

? ? title: "",

? ? description: "",

? ? published: false

? };

? const [tutorial, setTutorial] = useState(initialTutorialState);

? const [submitted, setSubmitted] = useState(false);


? const handleInputChange = event => {

? ? const { name, value } = event.target;

? ? setTutorial({ ...tutorial, [name]: value });

? };


? const saveTutorial = () => {

? ? var data = {

? ? ? title: tutorial.title,

? ? ? description: tutorial.description

? ? ? //published: "Publicado"

? ? };


? ? TutorialDataService.create(data)

? ? ? .then(response => {

? ? ? ? setTutorial({

? ? ? ? ? id: response.data.id,

? ? ? ? ? title: response.data.title,

? ? ? ? ? description: response.data.description,

? ? ? ? ? published: response.data.published

? ? ? ? });


? ? ? ? if (tutorial.id){

? ? ? ? ? ?tutorial.published=true;

? ? ? ? ? ?console.log("Se tiver id:"+tutorial.id+": a variavél public recebe:"+tutorial.published);

? ? ? ? }


? ? ? ? setSubmitted(true);

? ? ? ? console.log(response.data);

? ? ? })

? ? ? .catch(e => {

? ? ? ? console.log(e);

? ? ? });

? };


? const newTutorial = () => {

? ? setTutorial(initialTutorialState);

? ? setSubmitted(false);

? };


? return (

? ? <div className="submit-form">

? ? ? {submitted ? (

? ? ? ? <div>

? ? ? ? ? <h4>Cadastro realizado com sucesso!</h4>

? ? ? ? ? <button className="btn btn-success" onClick={newTutorial}>

? ? ? ? ? ? Adicionar

? ? ? ? ? </button>

? ? ? ? </div>

? ? ? ) : (

? ? ? ? <div>

? ? ? ? ? <div className="form-group">

? ? ? ? ? ? <label htmlFor="title">Titulo</label>

? ? ? ? ? ? <input

? ? ? ? ? ? ? type="text"

? ? ? ? ? ? ? className="form-control"

? ? ? ? ? ? ? id="title"

? ? ? ? ? ? ? required

? ? ? ? ? ? ? value={tutorial.title}

? ? ? ? ? ? ? onChange={handleInputChange}

? ? ? ? ? ? ? name="title"

? ? ? ? ? ? />

? ? ? ? ? </div>


? ? ? ? ? <div className="form-group">

? ? ? ? ? ? <label htmlFor="description">Descri??o</label>

? ? ? ? ? ? <input

? ? ? ? ? ? ? type="text"

? ? ? ? ? ? ? className="form-control"

? ? ? ? ? ? ? id="description"

? ? ? ? ? ? ? required

? ? ? ? ? ? ? value={tutorial.description}

? ? ? ? ? ? ? onChange={handleInputChange}

? ? ? ? ? ? ? name="description"

? ? ? ? ? ? />

? ? ? ? ? </div>


? ? ? ? ? <button onClick={saveTutorial} className="btn btn-success">

? ? ? ? ? ? Salvar

? ? ? ? ? </button>

? ? ? ? </div>

? ? ? )}

? ? </div>

? );

};


export default AddTutorial;

Tutorial.js

import React, { Component } from "react";

//import TutorialDataService from "../services/tutorial.service";

import TutorialDataService from "../services/TutorialService";

import { withRouter } from '../common/with-router';


//import axios from "axios";

//import React from "react";



class Tutorial extends Component {

? constructor(props) {

? ? super(props);

? ? this.onChangeTitle = this.onChangeTitle.bind(this);

? ? this.onChangeDescription = this.onChangeDescription.bind(this);

? ? this.getTutorial = this.getTutorial.bind(this);

? ? this.updatePublished = this.updatePublished.bind(this);

? ? this.updateTutorial = this.updateTutorial.bind(this);

? ? this.deleteTutorial = this.deleteTutorial.bind(this);


? ? this.state = {

? ? ? currentTutorial: {

? ? ? ? id: null,

? ? ? ? title: "",

? ? ? ? description: "",

? ? ? ? published: "",

? ? ? ? status:""

? ? ? },

? ? ? message: ""

? ? };

? }


? componentDidMount() {

? ? this.getTutorial(this.props.router.params.id);

? }


? onChangeTitle(e) {

? ? const title = e.target.value;


? ? this.setState(function(prevState) {

? ? ? return {

? ? ? ? currentTutorial: {

? ? ? ? ? ...prevState.currentTutorial,

? ? ? ? ? title: title

? ? ? ? }

? ? ? };

? ? });

? }


? onChangeDescription(e) {

? ? const description = e.target.value;

? ?

? ? this.setState(prevState => ({

? ? ? currentTutorial: {

? ? ? ? ...prevState.currentTutorial,

? ? ? ? description: description

? ? ? }

? ? }));

? }


? getTutorial(id) {

? ? TutorialDataService.get(id)

? ? ? .then(response => {

? ? ? ? this.setState({

? ? ? ? ? currentTutorial: response.data

? ? ? ? });

? ? ? ? console.log(response.data);

? ? ? })

? ? ? .catch(e => {

? ? ? ? console.log(e);

? ? ? });

? }


? updatePublished(status) {


? ? var data = {

? ? ? id: this.state.currentTutorial.id,

? ? ? //title: this.state.currentTutorial.title,

? ? ? //description: this.state.currentTutorial.description,

? ? ? published: status.toString()

? ? };


? ?/* var dados = {

? ? ? ? 'id': this.state.currentTutorial.id,

? ? ? ? 'title': this.state.currentTutorial.title,

? ? ? ? 'description': this.state.currentTutorial.description,

? ? ? ? 'published': this.state.currentTutorial.published.toString()

? ? ? };*/


? ? TutorialDataService.updateStatus(this.state.currentTutorial.id, data)

? ? ? .then(response => {

? ? ? ? this.setState(prevState => ({

? ? ? ? ? currentTutorial: {

? ? ? ? ? ? ...prevState.currentTutorial,

? ? ? ? ? ? published: status

? ? ? ? ? }

? ? ? ? }));

? ? ? ? console.log(response.data);

? ? ? })

? ? ? .catch(e => {

? ? ? ? console.log(e);

? ? ? });

? }


? updateTutorial() {


? ? // console.log(this.state.currentTutorial.id);

? ? // console.log(this.state.currentTutorial);

? ? var data = {

? ? ? ? ? ? 'id': this.state.currentTutorial.id,

? ? ? ? ? ? 'title': this.state.currentTutorial.title,

? ? ? ? ? ? 'description': this.state.currentTutorial.description//,

? ? ? ? ? ? //'published': this.state.currentTutorial.published.toString()

? ? ? ? ? ? //published:"published",

? ? ? ? ? ? //status:"status"

? ? ? ? ? };

?

? ? const json = JSON.stringify(data);

? ? console.log("DATA<>::"+json);

? ? //console.log(typeof json);


? ? this.state.currentTutorial = data;

? ? console.log("CURRENT_TUTORIAL:::"+this.state.currentTutorial);

? ? TutorialDataService.update(

? ? ? this.state.currentTutorial.id,

? ? ? this.state.currentTutorial

? ? )

? ? ? .then(response => {

? ? ? ? console.log(response.data);

? ? ? ? this.setState({

? ? ? ? ? message: "Dados alterados com sucesso!"

? ? ? ? });

? ? ? })

? ? ? .catch(e => {

? ? ? ? console.log(e);

? ? ?

? ? ? });



? }


? deleteTutorial() { ? ?

? ? TutorialDataService.delete(this.state.currentTutorial.id)

? ? ? .then(response => {

? ? ? ? console.log(response.data);

? ? ? ? this.props.router.navigate('/tutorials');

? ? ? })

? ? ? .catch(e => {

? ? ? ? console.log(e);

? ? ? });

? }


? render() {

? ? const { currentTutorial } = this.state;


? ? return (

? ? ? <div>

? ? ? ? {currentTutorial ? (

? ? ? ? ? <div className="edit-form">

? ? ? ? ? ? <h4>Tutorial</h4>

? ? ? ? ? ? <form>

? ? ? ? ? ? ? <div className="form-group">

? ? ? ? ? ? ? ? <label htmlFor="title">Titulo</label>

? ? ? ? ? ? ? ? <input

? ? ? ? ? ? ? ? ? type="text"

? ? ? ? ? ? ? ? ? className="form-control"

? ? ? ? ? ? ? ? ? id="title"

? ? ? ? ? ? ? ? ? value={currentTutorial.title}

? ? ? ? ? ? ? ? ? onChange={this.onChangeTitle}

? ? ? ? ? ? ? ? />

? ? ? ? ? ? ? </div>

? ? ? ? ? ? ? <div className="form-group">

? ? ? ? ? ? ? ? <label htmlFor="description">Descri??o</label>

? ? ? ? ? ? ? ? <input

? ? ? ? ? ? ? ? ? type="text"

? ? ? ? ? ? ? ? ? className="form-control"

? ? ? ? ? ? ? ? ? id="description"

? ? ? ? ? ? ? ? ? value={currentTutorial.description}

? ? ? ? ? ? ? ? ? onChange={this.onChangeDescription}

? ? ? ? ? ? ? ? />

? ? ? ? ? ? ? </div>


? ? ? ? ? ? ? <div className="form-group">

? ? ? ? ? ? ? ? <label>

? ? ? ? ? ? ? ? ? <strong>Status:</strong>

? ? ? ? ? ? ? ? </label>

? ? ? ? ? ? ? ? {currentTutorial.published ? "Publicado" : "Pendente"}

? ? ? ? ? ? ? </div>

? ? ? ? ? ? </form>


? ? ? ? ? ? {currentTutorial.published ? (

? ? ? ? ? ? ? <></>

? ? ? ? ? ? ? /*<button

? ? ? ? ? ? ? ? className="btn btn-primary"

? ? ? ? ? ? ? ? onClick={() => this.updatePublished(false)}

? ? ? ? ? ? ? ? //onClick={() => ""}

? ? ? ? ? ? ? >

? ? ? ? ? ? ? ? DesPublicar

? ? ? ? ? ? ? </button>*/

? ? ? ? ? ? ) : (

? ? ? ? ? ? ? <></>

? ? ? ? ? ? ? /*<button

? ? ? ? ? ? ? ? className="btn btn-primary"

? ? ? ? ? ? ? ? onClick={() => this.updatePublished(true)}

? ? ? ? ? ? ? ? //onClick={() => ""}

? ? ? ? ? ? ? >

? ? ? ? ? ? ? ? Publicar

? ? ? ? ? ? ? </button>*/

? ? ? ? ? ? )}


? ? ? ? ? ? <button

? ? ? ? ? ? ? className="btn btn-danger"

? ? ? ? ? ? ? onClick={this.deleteTutorial}

? ? ? ? ? ? >

? ? ? ? ? ? ? Excluir

? ? ? ? ? ? </button>


? ? ? ? ? ? <button

? ? ? ? ? ? ? type="submit"

? ? ? ? ? ? ? className="btn btn-success"

? ? ? ? ? ? ? onClick={this.updateTutorial}

? ? ? ? ? ? >

? ? ? ? ? ? ? Alterar

? ? ? ? ? ? </button>

? ? ? ? ? ? <p>{this.state.message}</p>

? ? ? ? ? </div>

? ? ? ? ) : (

? ? ? ? ? <div>

? ? ? ? ? ? <br />

? ? ? ? ? ? <p>Por favor clique no item da lista...</p>

? ? ? ? ? </div>

? ? ? ? )}

? ? ? </div>

? ? );

? }

}


export default withRouter(Tutorial);

TutorialsList.js

import React, { useState, useEffect} from "react";

import TutorialDataService from "../services/TutorialService";

import { Link } from "react-router-dom";

//import Table from 'react-bootstrap/Table';


const TutorialsList = () => {

? const [tutorials, setTutorials] = useState([]);

? const [currentTutorial, setCurrentTutorial] = useState(null);

? const [currentIndex, setCurrentIndex] = useState(-1);

? const [searchTitle, setSearchTitle] = useState("");


?/* this.state = {

? ? message: ""

? };*/


? useEffect(() => {

? ? retrieveTutorials();

? }, []);


? const onChangeSearchTitle = e => {

? ? const searchTitle = e.target.value;

? ? setSearchTitle(searchTitle);

? };


? const retrieveTutorials = () => {

? ? TutorialDataService.getAll()

? ? ? .then(response => {

? ? ? ? setTutorials(response.data);

? ? ? ? console.log(response.data);

? ? ? })

? ? ? .catch(e => {

? ? ? ? console.log(e);

? ? ? });

? };


? const refreshList = () => {

? ? retrieveTutorials();

? ? setCurrentTutorial(null);

? ? setCurrentIndex(-1);

? };


? const setActiveTutorial = (tutorial, index) => {

? ? setCurrentTutorial(tutorial);

? ? setCurrentIndex(index);

? };


? const removeAllTutorials = () => {

? ? TutorialDataService.removeAll()

? ? ? .then(response => {

? ? ? ? console.log(response.data);

? ? ? ? refreshList();

? ? ? })

? ? ? .catch(e => {

? ? ? ? console.log(e);

? ? ? });

? };


? const findByTitle = () => {

? ? TutorialDataService.findByTitle(searchTitle)

? ? ? .then(response => {

? ? ? ?

? ? ? ? //setTutorials(response.data);

? ? ? ? //this.props.router.navigate('/tutorials/'+currentTutorial.id);

? ? ? ?/* this.setState({

? ? ? ? ? message: "Dados encontrados, "+this.state.currentTutorial.title

? ? ? ? });*/

? ? ? ? console.log(response.data);

? ? ? ? const json = JSON.stringify(response.data);

? ? ? ? console.log('Dados encontrato com sucesso! '+json);

? ? ? ? //console.log('Pesquisa encontrada, '+json.data("title"));

? ? ? ?/* this.setState({

? ? ? ? ? message: json

? ? ? ? });*/


? ? ? ? //setTutorials(json);


? ? ? })

? ? ? .catch(e => {

? ? ? ? console.log(e);

? ? ? });

? };


? return (

?

? ? <div className="list row">

? ? ? <div className="col-md-8">

? ? ? ? <div className="input-group mb-3">

? ? ? ? ? <input

? ? ? ? ? ? id="txt_consulta"

? ? ? ? ? ? type="text"

? ? ? ? ? ? className="form-control"

? ? ? ? ? ? placeholder="Informe o titulo que deseja pesquisar"

? ? ? ? ? ? value={searchTitle}

? ? ? ? ? ? onChange={onChangeSearchTitle}

? ? ? ? ? />

? ? ? ? ? <div className="input-group-append">

? ? ? ? ? ? <button

? ? ? ? ? ? ? className="btn btn-outline-secondary"

? ? ? ? ? ? ? type="button"

? ? ? ? ? ? ? onClick={findByTitle}

? ? ? ? ? ? >

? ? ? ? ? ? ? Pesquisar

? ? ? ? ? ? </button>

? ? ? ? ? </div>

? ? ? ? </div>

? ? ? </div>

? ? ? <div className="col-md-6">

? ? ? ? <h4>Lista de Tutorial</h4>


? ? ? ? <table id="tabela" class="table table-hover">

? ? ? ? <tbody><tr><th>

? ? ?

? ? ? ? <ul className="list-group">

? ? ? ? ? {tutorials &&

? ? ? ? ? ? tutorials.map((tutorial, index) => (

? ? ? ? ? ? ? <li

? ? ? ? ? ? ? ? className={

? ? ? ? ? ? ? ? ? "list-group-item " + (index === currentIndex ? "active" : "")

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? onClick={() => setActiveTutorial(tutorial, index)}

? ? ? ? ? ? ? ? key={index}

? ? ? ? ? ? ? >

? ? ? ? ? ? ? ? {tutorial.title}

? ? ? ? ? ? ? </li>

? ? ? ? ? ? ))}

? ? ? ? </ul>


? ? ? ? </th></tr></tbody></table>


? ? ? ? <button

? ? ? ? ? className="m-3 btn btn-sm btn-danger"

? ? ? ? ? onClick={removeAllTutorials}

? ? ? ? >

? ? ? ? ? Excluir todos

? ? ? ? </button>

? ? ? </div>

? ? ? <div className="col-md-6">

? ? ? ? {currentTutorial ? (

? ? ? ? ? <div>

? ? ? ? ? ? <h4>Tutorial</h4>

? ? ? ? ? ? <div>

? ? ? ? ? ? ? <label>

? ? ? ? ? ? ? ? <strong>Titulo:</strong>

? ? ? ? ? ? ? </label>{" "}

? ? ? ? ? ? ? {currentTutorial.title}

? ? ? ? ? ? </div>

? ? ? ? ? ? <div>

? ? ? ? ? ? ? <label>

? ? ? ? ? ? ? ? <strong>Descri??o:</strong>

? ? ? ? ? ? ? </label>{" "}

? ? ? ? ? ? ? {currentTutorial.description}

? ? ? ? ? ? </div>

? ? ? ? ? ? <div>

? ? ? ? ? ? ? <label>

? ? ? ? ? ? ? ? <strong>Status:</strong>

? ? ? ? ? ? ? </label>{" "}

? ? ? ? ? ? ? {currentTutorial.published ? "Publicado" : "Pendente"}

? ? ? ? ? ? </div>


? ? ? ? ? ? <Link

? ? ? ? ? ? ? to={"/tutorials/" + currentTutorial.id}

? ? ? ? ? ? ? className="btn btn-warning"

? ? ? ? ? ? >

? ? ? ? ? ? ?{currentTutorial.id}

? ? ? ? ? ? ? Editar

? ? ? ? ? ? </Link>

? ? ? ? ? </div>

? ? ? ? ) : (

? ? ? ? ? <div>

? ? ? ? ? ? <br />

? ? ? ? ? ? <p>Por favor clique em uma op??o da lista...</p>

? ? ? ? ? </div>

? ? ? ? )}

? ? ? </div>

? ? </div>


? );

};


export default TutorialsList;

TutorialService.js

import http from "../http-common";


class TutorialDataService {

? getAll() {

? ? return http.get("/tutorials");

? }


? get(id) {

? ? return http.get(`/tutorials/${id}`);

? }


? create(data) {

? ? return http.post("/novo-tutorials", data);

? }


? update(id, data) {

? ? console.log(http.put(id));

? ? return http.put(`/put-tutorials`,data);


? }


? updateStatus(id, data) {

? ? console.log(http.put(id));

? ? return http.put(`/up-status-tutorials`,data);

? }


? delete(id) {

? ? return http.delete(`/del-tutorials/${id}`);

? }


? deleteAll() {

? ? return http.delete(`/del-tutorials`);

? }


? findByTitle(title) {

? ? return http.get(`/pesq-tutorials/title?title=${title}`);

? }

}


export default new TutorialDataService();

App.css

.list {

? ? text-align: left;

? ? max-width: 750px;

? ? margin: auto;

? }

?

? .submit-form {

? ? max-width: 300px;

? ? margin: auto;

? }

?

? .edit-form {

? ? max-width: 300px;

? ? margin: auto;

? }


? .btn {

? ? border: none;

? ? padding: 10px;

? ? text-decoration: none;

? ? cursor: pointer;

? ? transition: background .3s;

? ? border-radius: 5px;

}


/*SUCCESS*/

.btn-sucesso {

? ? background-color: var(#006400);

? ? outline: none;

? ? color: var(#FFFAF0)

}


.btn-excluir {

? background-color: var(#FF0000);

? outline: none;

? color: var(#FFFAF0)

}

App.js

import React from "react";

import { Routes, Route, Link } from "react-router-dom";

import "bootstrap/dist/css/bootstrap.min.css";

import "./App.css";


import AddTutorial from "./components/AddTutorial";

import Tutorial from "./components/Tutorial";

import TutorialsList from "./components/TutorialsList";

import Pesquisa from "./Pesquisa";


function App() {


? return (

? ? <div>

? ? ? <nav className="navbar navbar-expand navbar-dark bg-dark">

? ? ? ? <a href="/tutorials" className="navbar-brand">

? ? ? ? ? Inicio

? ? ? ? </a>

? ? ? ? <div className="navbar-nav mr-auto">

? ? ? ? ? <li className="nav-item">

? ? ? ? ? ? <Link to={"/tutorials"} className="nav-link">

? ? ? ? ? ? ? Tutorial

? ? ? ? ? ? </Link>

? ? ? ? ? </li>

? ? ? ? ? <li className="nav-item">

? ? ? ? ? ? <Link to={"/add"} className="nav-link">

? ? ? ? ? ? ? Cadastro

? ? ? ? ? ? </Link>

? ? ? ? ? </li>

? ? ? ? ? <li className="nav-item">

? ? ? ? ? ? <Link to={"/Pesquisa"} className="nav-link">

? ? ? ? ? ? ? Pesquisa

? ? ? ? ? ? </Link>

? ? ? ? ? </li>

? ? ? ? ?

? ? ? ? ?

? ? ? ? </div>

? ? ? </nav>


? ? ? <div className="container mt-3">

? ? ? ? <Routes>

? ? ? ? ? <Route path="/" element={<TutorialsList/>} />

? ? ? ? ? <Route path="/tutorials" element={<TutorialsList/>} />

? ? ? ? ? <Route path="/add" element={<AddTutorial/>} />

? ? ? ? ? <Route path="/tutorials/:id" element={<Tutorial/>} />

? ? ? ? ? <Route path="/pesquisa" element={<Pesquisa/>} />

? ? ?

? ? ? ? </Routes>

? ? ? </div>

? ? </div>

? ); ?

}


export default App;

http-common.js

import axios from "axios";


export default axios.create({

? //baseURL: "https://localhost:8080/api",

? baseURL: "https://localhost:5235",

? headers: {

? ? "Content-type": "application/json",

? ? "Access-Control-Allow-Origin": "*",

? ? "Access-Control-Allow-Methods": "GET,PUT,POST,DELETE,PATCH,OPTIONS",

? ? "Access-Control-Allow-Headers":"*",

? ? "X-Requested-with":"*",

? ? "Content_Type":"*",

? ? "Accept":"*",

? ? "Authorization":"https://localhost:5235"

? }

});



index.css

body {

? margin: 0;

? font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',

? ? '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;

}


index.js

import React from "react";

//import ReactDOM from "react-dom";

import { BrowserRouter } from "react-router-dom";

import ReactDOM from 'react-dom/client';


import App from "./App";

import * as serviceWorker from "./serviceWorker";


/*ReactDOM.render(

? <BrowserRouter>

? ? <App />

? </BrowserRouter>,

? document.getElementById("root")

);*/


const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(

? <BrowserRouter>

? ? <App />

? </BrowserRouter>

);


serviceWorker.unregister();

Pesquisa.js

import './App.css';

import { useEffect, useMemo, useState } from 'react';

import axios from "axios"

import Table from './Table';


function Pesquisa() {


//--Para testar o table customizado

? // Array com os passageiros falsos da API

? const [data, setData] = useState([])

? // Número total de páginas

? const [totalPages, setTotalPages] = useState(1)

? // Número total de passageiros

? const [totalPassengers, setTotalPassengers] = useState(1)

? // Hook para fazer a primeira chamada do componente


? useEffect(() => {

? ? // Fun??o para recuperar informa??es da API

? ? axios.get("https://localhost:5235/tutorials")

? ? ? .then((res) => {


? ? ? ? const json = JSON.stringify(res);

? ? ? ? const obj = JSON.parse(json);


? ? ? ? console.log("json: "+json);

? ? ? ? console.log("obj: "+obj);

? ? ? ? console.log("res: "+res);

? ? ? ? console.log("res_data: "+res.data);


? ? ? ?const {data} = obj

? ? ? ?setData(data)

? ? ? ?

? ? ? })

? }, [])


? // Colunas da nossa tabela

? const columns = useMemo(

? ? () => [

? ? ? {

? ? ? ? //Tabela de teste inicio

? ? ? ? // Primeiro grupo - Informa??es do passageiro

? ? ? ? Header: "Informa??es dos tutoriais",

? ? ? ? // Colunas do primeiro grupo

? ? ? ? columns: [

? ? ? ? ? {

? ? ? ? ? ? Header: "Nome",

? ? ? ? ? ? accessor: "title"

? ? ? ? ? },

? ? ? ? ? {

? ? ? ? ? ? Header: "Descri??o",

? ? ? ? ? ? accessor: "description"

? ? ? ? ? }

? ? ? ? ]

? ? ? }

? ? ],

? ? []

? );


? return (

? ? ? <div className="App">

? ? ? ? <Table columns={columns} data={data} />

? ? ? </div>

? );


}

export default Pesquisa;

?

serviceWorker.js

const isLocalhost = Boolean(

? ? window.location.hostname === 'localhost' ||

? ? ? // [::1] is the IPv6 localhost address.

? ? ? window.location.hostname === '[::1]' ||

? ? ? // 127.0.0.0/8 are considered localhost for IPv4.

? ? ? window.location.hostname.match(

? ? ? ? /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/

? ? ? )

? );

?

? export function register(config) {

? ? if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {

? ? ? // The URL constructor is available in all browsers that support SW.

? ? ? const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);

? ? ? if (publicUrl.origin !== window.location.origin) {

? ? ? ? // Our service worker won't work if PUBLIC_URL is on a different origin

? ? ? ? // from what our page is served on. This might happen if a CDN is used to

? ? ? ? // serve assets; see https://github.com/facebook/create-react-app/issues/2374

? ? ? ? return;

? ? ? }

?

? ? ? window.addEventListener('load', () => {

? ? ? ? const swUrl = '${process.env.PUBLIC_URL}/service-worker.js';

?

? ? ? ? if (isLocalhost) {

? ? ? ? ? // This is running on localhost. Let's check if a service worker still exists or not.

? ? ? ? ? checkValidServiceWorker(swUrl, config);

?

? ? ? ? ? // Add some additional logging to localhost, pointing developers to the

? ? ? ? ? // service worker/PWA documentation.

? ? ? ? ? navigator.serviceWorker.ready.then(() => {

? ? ? ? ? ? console.log(

? ? ? ? ? ? ? 'This web app is being served cache-first by a service ' +

? ? ? ? ? ? ? ? 'worker. To learn more, visit https://bit.ly/CRA-PWA'

? ? ? ? ? ? );

? ? ? ? ? });

? ? ? ? } else {

? ? ? ? ? // Is not localhost. Just register service worker

? ? ? ? ? registerValidSW(swUrl, config);

? ? ? ? }

? ? ? });

? ? }

? }

?

? function registerValidSW(swUrl, config) {

? ? navigator.serviceWorker

? ? ? .register(swUrl)

? ? ? .then(registration => {

? ? ? ? registration.onupdatefound = () => {

? ? ? ? ? const installingWorker = registration.installing;

? ? ? ? ? if (installingWorker == null) {

? ? ? ? ? ? return;

? ? ? ? ? }

? ? ? ? ? installingWorker.onstatechange = () => {

? ? ? ? ? ? if (installingWorker.state === 'installed') {

? ? ? ? ? ? ? if (navigator.serviceWorker.controller) {

? ? ? ? ? ? ? ? // At this point, the updated precached content has been fetched,

? ? ? ? ? ? ? ? // but the previous service worker will still serve the older

? ? ? ? ? ? ? ? // content until all client tabs are closed.

? ? ? ? ? ? ? ? console.log(

? ? ? ? ? ? ? ? ? 'New content is available and will be used when all ' +

? ? ? ? ? ? ? ? ? ? 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'

? ? ? ? ? ? ? ? );

?

? ? ? ? ? ? ? ? // Execute callback

? ? ? ? ? ? ? ? if (config && config.onUpdate) {

? ? ? ? ? ? ? ? ? config.onUpdate(registration);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? // At this point, everything has been precached.

? ? ? ? ? ? ? ? // It's the perfect time to display a

? ? ? ? ? ? ? ? // "Content is cached for offline use." message.

? ? ? ? ? ? ? ? console.log('Content is cached for offline use.');

?

? ? ? ? ? ? ? ? // Execute callback

? ? ? ? ? ? ? ? if (config && config.onSuccess) {

? ? ? ? ? ? ? ? ? config.onSuccess(registration);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? };

? ? ? ? };

? ? ? })

? ? ? .catch(error => {

? ? ? ? console.error('Error during service worker registration:', error);

? ? ? });

? }

?

? function checkValidServiceWorker(swUrl, config) {

? ? // Check if the service worker can be found. If it can't reload the page.

? ? fetch(swUrl, {

? ? ? headers: { 'Service-Worker': 'script' }

? ? })

? ? ? .then(response => {

? ? ? ? // Ensure service worker exists, and that we really are getting a JS file.

? ? ? ? const contentType = response.headers.get('content-type');

? ? ? ? if (

? ? ? ? ? response.status === 404 ||

? ? ? ? ? (contentType != null && contentType.indexOf('javascript') === -1)

? ? ? ? ) {

? ? ? ? ? // No service worker found. Probably a different app. Reload the page.

? ? ? ? ? navigator.serviceWorker.ready.then(registration => {

? ? ? ? ? ? registration.unregister().then(() => {

? ? ? ? ? ? ? window.location.reload();

? ? ? ? ? ? });

? ? ? ? ? });

? ? ? ? } else {

? ? ? ? ? // Service worker found. Proceed as normal.

? ? ? ? ? registerValidSW(swUrl, config);

? ? ? ? }

? ? ? })

? ? ? .catch(() => {

? ? ? ? console.log(

? ? ? ? ? 'No internet connection found. App is running in offline mode.'

? ? ? ? );

? ? ? });

? }

?

? export function unregister() {

? ? if ('serviceWorker' in navigator) {

? ? ? navigator.serviceWorker.ready

? ? ? ? .then(registration => {

? ? ? ? ? registration.unregister();

? ? ? ? })

? ? ? ? .catch(error => {

? ? ? ? ? console.error(error.message);

? ? ? ? });

? ? }

? }

Table.css

table {

? ? font-family: Arial, Helvetica, sans-serif;

? ? border-collapse: collapse;

? ? width: 100%;

? }

? table td, table th {

? ? border: 1px solid #ddd;

? ? padding: 8px;

? }

? table tr:nth-child(even){background-color: #f2f2f2;}

? table tr:hover {background-color: #ddd;}

? table th {

? ? padding-top: 12px;

? ? padding-bottom: 12px;

? ? text-align: left;

? ? background-color: #04AA6D;

? ? color: white;

? }

Table.js

//instalar ?yarn add react-table ou npm add react-table

//import React from "react";

import { useTable, useFilters} from "react-table";

import React, { useState} from "react";

import "./Table.css";


function Table({ columns, data }) {


?


? // Utilizando o hook useTable e passando as colunas com os dados.

? // é retornado para a gente todas as informa??es necessárias para

? // montar a tabela.

? const {

? ? getTableProps, // propriedades da tabela

? ? getTableBodyProps, // propriedades do corpo da tabela

? ? headerGroups, // os valores de agrupamento de tabela, caso sua tabela use

? ? rows, // linhas da tabela baseado nos dados e colunas

? ? prepareRow, // Prepara a linha (Essa fun??o deve ser chamada para cada linha)

? ? setFilter // Com a passagem do hook useFilters, temos a possibilidade filtrar a tabela com a fun??o setFilter


? } = useTable({

? ? columns,

? ? data

? },

? ?useFilters//, // adicionando o hook useFilters na tabela

? ?//useSortBy // Este hook nos ajuda a reorganizar a tabela

);

? ? ?

? ? ? // Criando o estado

? ? ? const [valueInput, setValueInput] = useState("");

? ? ? // Atualiza o estado quando o valor muda

? ? ? const handleValueChange = e => {

? ? ? ? const value = e.target.value || undefined;

? ? ? ? setFilter("title", value); // Atualiza o nome filtro "name". Com isso, a tabela sabe fazer a busca e mostrar apenas elementos parecidos com esse

? ? ? ? setValueInput(value);

? ? ? };


? ?// Input element

? ?/*<input

? ? ? value={valueInput}

? ? ? onChange={handleValueChange}

? ? ? placeholder={"Busca pelo nome"}

? ? ? />*/


? /*

? ? Aqui renderizamos a nossa tabela.

? ? Como já sabemos, o React Table n?o possui nenhum comportamento visual, logo,

? ? depende que a gente adicione os elementos e estilo.

? ? O React Table vai ajudar a gente a controlar os estados e lógicas da tabela.

? */

? return (


? ? <table {...getTableProps()}>

? ? ? <thead>

? ? ? ? {headerGroups.map(headerGroup => (

? ? ? ? ? ?

? ? ? ? ? <tr {...headerGroup.getHeaderGroupProps()}>

? ? ? ? ? ? {headerGroup.headers.map(column => (

? ? ? ? ? ? ? <th {...column.getHeaderProps()}>{column.render("Header")}</th>

? ? ? ? ? ? ))}

? ? ? ? ? </tr>

? ? ? ? ))}

? ? ? </thead>

? ? ? <input

value={valueInput}

onChange={handleValueChange}

placeholder={"Busca pelo nome"}

/>

? ? ? <tbody {...getTableBodyProps()}>

? ? ? ? {rows.map((row, i) => {

? ? ? ? ? prepareRow(row);

? ? ? ? ? return (

? ? ? ? ? ? <tr {...row.getRowProps()}>

? ? ? ? ? ? ? {row.cells.map(cell => {

? ? ? ? ? ? ? ? return <td {...cell.getCellProps()}>{cell.render("Cell")}</td>;

? ? ? ? ? ? ? })}

? ? ? ? ? ? </tr>

? ? ? ? ? );

? ? ? ? })}

? ? ? </tbody>

? ? </table>

? );

}

export default Table;

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

Execute a aplica??o.

Abaixo as figuras da aplica??o funcionando.

N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem

Vamos adicionar dois bot?es na pesquisa, um para gerar o .csv e outro para chamar o print para gerar um .pdf ou enviar para a impressora padr?o.

N?o foi fornecido texto alternativo para esta imagem

Vamos mudar o nosso Table.js mais antes execute no terminal esses dois comandos.

npm add antd

npm add react-csv

npm add react-to-print

N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem

Table.js

import { useTable, useFilters} from "react-table";

import React, { useState, useRef} from "react";

import "./Table.css";


import {CSVLink} from "react-csv"

//import { Table} from "antd";

import { useReactToPrint } from 'react-to-print';

import { FilePdfOutlined } from '@ant-design/icons';

import { Button} from "antd";



function Table({ columns, data }) {



? const componentRef = useRef();

? const handlePrint = useReactToPrint({

? ? content: () => componentRef.current,

? });



? // Utilizando o hook useTable e passando as colunas com os dados.

? // é retornado para a gente todas as informa??es necessárias para

? // montar a tabela.

? const {

? ? getTableProps, // propriedades da tabela

? ? getTableBodyProps, // propriedades do corpo da tabela

? ? headerGroups, // os valores de agrupamento de tabela, caso sua tabela use

? ? rows, // linhas da tabela baseado nos dados e colunas

? ? prepareRow, // Prepara a linha (Essa fun??o deve ser chamada para cada linha)

? ? setFilter // Com a passagem do hook useFilters, temos a possibilidade filtrar a tabela com a fun??o setFilter


? } = useTable({

? ? columns,

? ? data

? },

? ?useFilters//, // adicionando o hook useFilters na tabela

? ?//useSortBy // Este hook nos ajuda a reorganizar a tabela

);

? ? ?

? ? ? // Criando o estado

? ? ? const [valueInput, setValueInput] = useState("");

? ? ? // Atualiza o estado quando o valor muda

? ? ? const handleValueChange = e => {

? ? ? ? const value = e.target.value || undefined;

? ? ? ? setFilter("title", value); // Atualiza o nome filtro "name". Com isso, a tabela sabe fazer a busca e mostrar apenas elementos parecidos com esse

? ? ? ? setValueInput(value);

? ? ? };


? ?// Input element

? ?/*<input

? ? ? value={valueInput}

? ? ? onChange={handleValueChange}

? ? ? placeholder={"Busca pelo nome"}

? ? ? />*/


? /*

? ? Aqui renderizamos a nossa tabela.

? ? Como já sabemos, o React Table n?o possui nenhum comportamento visual, logo,

? ? depende que a gente adicione os elementos e estilo.

? ? O React Table vai ajudar a gente a controlar os estados e lógicas da tabela.

? */


? ? /*

? ? <CSVLink

? ? ? ? ? ? ? filename={"Expense_Table.csv"}

? ? ? ? ? ? ? data={myList}

? ? ? ? ? ? ? className="btn btn-primary"

? ? ? ? ? ? >

? ? ? ? ? ? ? Export to CSV

? ? ? ? ? ? </CSVLink>


? ? ? ? ? ? <Button onClick={handlePrint} type="primary" danger> Export to PDF </Button>

? ? */

? return (

? ? <div ref={componentRef}>

? ? <table {...getTableProps()}>

? ? ? <thead>

? ? ? ? {headerGroups.map(headerGroup => (

? ? ? ? ? ?

? ? ? ? ? <tr {...headerGroup.getHeaderGroupProps()}>

? ? ? ? ? ? {headerGroup.headers.map(column => (

? ? ? ? ? ? ? <th {...column.getHeaderProps()}>{column.render("Header")}</th>

? ? ? ? ? ? ))}

? ? ? ? ? </tr>

? ? ? ? ))}

? ? ? </thead>

? ? ? <input

value={valueInput}

onChange={handleValueChange}

placeholder={"Busca pelo nome"}

/>


<>&nbsp;</>


? <CSVLink

? ? ? filename={"pesquisa_de_dados_tutorial.csv"}

? ? ? data={data}

? ? ? className="btn btn-primary">CSV

?</CSVLink>

?<>&nbsp;</>


?<Button onClick={handlePrint} type="primary" danger><FilePdfOutlined /> PDF </Button>


? ? ? <tbody {...getTableBodyProps()}>

? ? ? ? {rows.map((row, i) => {

? ? ? ? ? prepareRow(row);

? ? ? ? ? return (

? ? ? ? ? ? <tr {...row.getRowProps()}>

? ? ? ? ? ? ? {row.cells.map(cell => {

? ? ? ? ? ? ? ? return <td {...cell.getCellProps()}>{cell.render("Cell")}</td>;

? ? ? ? ? ? ? })}

? ? ? ? ? ? </tr>

? ? ? ? ? );

? ? ? ? })}

? ? ? </tbody>

? ? </table>

? ? </div>

? );

}

export default Table;

N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem


N?o foi fornecido texto alternativo para esta imagem

Fim.

要查看或添加评论,请登录

Miguel Franco的更多文章

社区洞察

其他会员也浏览了