Commit 87e27025 by Abhisarika Singh

worked on library module perform create,retrieve,update,delete & search operation

parent ebb60b88
......@@ -50,4 +50,6 @@
height: 100%;
width: 100%;
opacity: 0.4;
}
\ No newline at end of file
}
\ No newline at end of file
class Api::V1::BooksController < ApplicationController
def index
recipe = Book.all.order(created_at: :desc)
render json: recipe
end
def create
book = Book.create!(book_params)
if book
render json: book
else
render json: book.errors
end
end
def show
if book
render json: book
else
render json: book.errors
end
end
def destroy
puts "hhhgh"
book&.destroy
render json: { message: 'Book deleted!' }
end
def search
if params[:name].blank?
redirect_to(root_path, alert: "Empty field!") and return
else
if bookFound
render json: bookFound;
else
render json: {message: "Book Not Found"}
end
end
end
end
def update
if book
book.update({name: 'Math'})
render json: book
else
render json: {message: 'Book Not Found'}
end
end
private
def book_params
params.permit(:name, :writterName, :courseName)
end
def book
@book ||= Book.find(params[:id])
end
def bookFound
@parameter= params[:name].downcase
@bookFound ||= Book.all.where("name LIKE :name", name: @parameter)
end
......@@ -5,6 +5,7 @@ class Api::V1::EmployeesController < ApplicationController
end
def create
puts employee
employee = Employee.create!(employee_params)
if employee
render json: employee
......
......@@ -40,6 +40,7 @@ class Api::V1::RecipesController < ApplicationController
private
def recipe_params
puts params
params.permit(:name, :image, :ingredients, :instruction)
end
......
......@@ -27,6 +27,14 @@ export default () => (
>
View Employees
</Link>
<br></br>
<Link
to="/library"
className="btn btn-lg custom-button"
role="button"
>
View Library
</Link>
</div>
</div>
</div>
......
......@@ -27,8 +27,9 @@ class Recipe extends React.Component {
}
throw new Error("Network response was not ok.");
})
.then(response => this.setState({ recipe: response }))
.then(response => this.setState({ recipe: response }) )
.catch(() => this.props.history.push("/recipes"));
}
......
......@@ -25,6 +25,8 @@ class Recipes extends React.Component {
render() {
const { recipes } = this.state;
console.log(recipes);
const allRecipes = recipes.map((recipe, index) => (
<div key={index} className="col-md-6 col-lg-4">
<div className="card mb-4">
......
import React, { Component } from 'react';
import { Link, useHistory } from 'react-router-dom';
import { Router } from 'react-router';
import { data } from 'jquery';
class AddBooks extends Component {
constructor(props) {
super(props)
this.saveBook = this.saveBook.bind(this)
this.getFieldValue = this.getFieldValue.bind(this)
this.goBack = this.goBack.bind(this)
this.state = {
name: 'ftgre',
writterName: 'tert',
courseName: 'rtre'
}
}
goBack() {
Router.history.goBack();
}
saveBook(event) {
event.preventDefault();
const url = "/api/v1/books/create";
const { name, writterName, courseName } = this.state;
if (name.length == 0 || writterName.length == 0 || courseName.length == 0)
return;
const body = {
name,
writterName,
courseName
};
const token = document.querySelector('meta[name="csrf-token"]').content;
fetch(url, {
method: "POST",
headers: {
"X-CSRF-Token": token,
"Content-Type": "application/json"
},
body: JSON.stringify(body)
})
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error("Network response was not ok.");
})
.then(response => this.props.history.push('/booksList'))
.catch(error => console.log(error.message));
}
getFieldValue(event) {
this.setState({ [event.target.name]: event.target.value })
}
render() {
return (<>
<section className="jumbotron jumbotron-fluid text-center">
<div className="container py-5">
<h1 className="display-4">ADD BOOk</h1>
</div>
</section>
<div className="py-5">
<main className="container">
<div className="row">
<form onSubmit={this.saveBook}>
<div className="form-group">
<label htmlFor="name">Book name</label>
<input
onChange={this.getFieldValue}
// ref={ac => this.state.bookName = ac.value}
type="text"
name="name"
id="name"
className="form-control"
required
/>
</div>
<div className="form-group">
<label htmlFor="writterName">Writter name</label>
<input
onChange={this.getFieldValue}
// ref={ac => this.state.writterName = ac.value}
type="text"
name="writterName"
id="writterName"
className="form-control"
required
/>
</div>
<div className="form-group">
<label htmlFor="courseName">Course name</label>
<input
onChange={this.getFieldValue}
// ref={ac => this.state.courseName = ac.value}
type="text"
name="courseName"
id="courseName"
className="form-control"
required
/>
</div>
<button type="submit" className="btn custom-button mt-3" /* onClick={this.saveBook} */>ADD</button>
</form>
</div>
<button onClick={this.goBack} >Go Back</button>
<Link to="/" className="btn btn-link">
Home
</Link>
</main>
</div>
</>)
}
}
export default AddBooks;
\ No newline at end of file
import React, {Component} from 'react';
import {Link} from 'react-router-dom';
class BookDetails extends Component{
constructor(props){
super(props);
this.setState = this.setState.bind(this)
this.deleteBook = this.deleteBook.bind(this)
this.state= { book: {} }
}
componentDidMount(){
const id = this.props.location.search.split('?')[1].split('=')[1]
const url = `/api/v1/book/show/${id}`;
const token = document.querySelector('meta[name="csrf-token"]').content;
fetch(url, {
method: "GET",
headers: {
"X-CSRF-Token": token,
"Content-Type": "application/json"
}
})
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error("Network response was not ok.");
})
.then((response) => this.setState({book: response}))
.catch(error => console.log(error.message));
}
deleteBook() {
const id = this.props.location.search.split('?')[1].split('=')[1]
const url = `/api/v1/book/destroy/${id}`;
const token = document.querySelector('meta[name="csrf-token"]').content;
fetch(url, {
method: "DELETE",
headers: {
"X-CSRF-Token": token,
"Content-Type": "application/json"
}
})
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error("Network response was not ok.");
})
.then((response) => this.props.history.push('/booksList'))
.catch(error => console.log(error.message));
}
render(){
const {book} = this.state
return (
<>
<section className="jumbotron jumbotron-fluid text-center">
<div className="container py-5">
<h1 className="display-4">Book Details</h1>
</div>
</section>
<div className="py-5">
<main className="container">
<div className="text-right mb-3">
</div >
<div className="row">
<div>{book.name}</div>
<div>{book.writterName}</div>
<div>{book.courseName}</div>
<button >edit</button>
<button onClick={this.deleteBook}>delete</button>
</div>
</main>
</div>
</>)
}
}
export default BookDetails
\ No newline at end of file
import React,{Component} from 'react';
import {Link,Route} from 'react-router-dom'
import BookDetails from './BookDetails';
class BooksList extends Component{
constructor(props){
super(props);
this.getName = this.getName.bind(this)
this.searchByBookName = this.searchByBookName.bind(this)
this.routeToBookDetais = this.routeToBookDetais.bind(this)
this.state={
books: [],
name: ''
}
}
componentDidMount() {
const url = "/api/v1/books/index";
fetch(url)
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error("Network response was not ok.");
})
.then(response => this.setState({ books: response }))
.catch((error) => console.log(error))
}
getName(){
this.setState({ [event.target.name]: event.target.value })
}
searchByBookName(event) {
event.preventDefault();
const { name } = this.state;
if (name.length == 0)
return;
const url = `/api/v1/book/search/${name}`;
const token = document.querySelector('meta[name="csrf-token"]').content;
fetch(url, {
method: "GET",
headers: {
"X-CSRF-Token": token,
"Content-Type": "application/json"
}
})
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error("Network response was not ok.");
})
.then((response) => this.setState({book: response}))
.catch(error => console.log(error.message));
}
routeToBookDetais(e){
e.preventDefault()
console.log(e,"gf");
this.props.history.push(`/bookDetails`)
}
render(){
const {books} = this.state
const showBooks = books.map((book, i) => (
<div key={i} className="col-md-6 col-lg-4">
<div className="card mb-4">
{/* <img
src={"../../../assets/images/book.png"}
className="card-img-top"
alt={`book`}
/> */}
<div className="card-body">
<h5 className="card-title">{book.name}</h5>
<Link to={`/bookDetails?id=${book.id}`}>view book details</Link>
</div>
</div>
</div>
));
const noBooks = (
<div className="vw-100 vh-50 d-flex align-items-center justify-content-center">
<h4>
books not avalaible <Link to="/addBooks">create one</Link>
</h4>
</div>
);
return (
<>
<section className="jumbotron jumbotron-fluid text-center">
<div className="container py-5">
<h1 className="display-4">Available books in library</h1>
</div>
</section>
<div className="py-5">
<main className="container">
<div className="text-right mb-3">
<Link to="/addBooks" className="btn custom-button">
Add New book
</Link>
</div >
<div className="row">
<input
onChange={this.getName}
type="text"
name="name"
id="name"
className="form-control"
/>
<button onClick={this.searchByBookName}>search</button>
</div>
<div className="row">
{books.length > 0 ? showBooks : noBooks}
</div>
<Link to="/" className="btn btn-link">
Home
</Link>
</main>
</div>
</>
)
}
}
export default BooksList;
\ No newline at end of file
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
class Library extends Component {
render() {
return (<>
<section className="jumbotron jumbotron-fluid text-center">
<div className="container py-5">
<h1 className="display-4">Library</h1>
</div>
</section>
<div className="py-5">
<main className="container">
<div className="text-right mb-3">
Manage your books
</div>
<Link to="/addBooks" className="btn btn-link">
create books
</Link>
<Link to="/" className="btn btn-link">
Home
</Link>
</main>
</div>
</>)
}
}
export default Library;
\ No newline at end of file
......@@ -7,6 +7,10 @@ import NewRecipe from "../components/NewRecipe";
import Employees from "../components/Employees";
import Employee from "../components/Employee";
import NewEmployee from "../components/NewEmployee";
import Library from '../components/library/Library';
import AddBooks from '../components/library/AddBooks';
import BooksList from '../components/library/BooksList';
import BookDetails from "../components/library/BookDetails";
export default (
<Router>
......@@ -18,6 +22,10 @@ export default (
<Route path="/employees" exact component={Employees} />
<Route path="/employee/:id" exact component={Employee} />
<Route path="/employee" exact component={NewEmployee} />
<Route path="/library" exact component={Library} />
<Route path="/addBooks" exact component={AddBooks} />
<Route path="/booksList" exact component={BooksList}/>
<Route path="/bookDetails" exact component={BookDetails}/>
</Switch>
</Router>
);
\ No newline at end of file
class Book < ApplicationRecord
validates :name, presence: true
validates :writterName, presence: true
validates :courseName, presence: true
end
class Employee < ApplicationRecord
puts "ttt"
validates :firstName, presence: true
validates :lastName, presence: true
validates :email, presence: true
......
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
get 'books/index'
post 'books/create'
get 'book/search/:name', to: 'books#search'
get 'book/show/:id', to: 'books#show'
get 'book/update/:id', to: 'books#update'
delete 'book/destroy/:id', to: 'books#destroy'
end
end
namespace :api do
namespace :v1 do
get 'employees/index'
post 'employees/create'
get 'employee/show/:id', to: 'employees#show'
......@@ -17,6 +27,7 @@ Rails.application.routes.draw do
post 'recipes/uploadFile'
end
end
root 'homepage#index'
get '/*path' => 'homepage#index'
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
......
class CreateBooks < ActiveRecord::Migration[5.2]
def change
create_table :books do |t|
t.string :name
t.string :writterName
t.text :courseName
t.timestamps
end
end
end
......@@ -10,11 +10,19 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_09_30_024252) do
ActiveRecord::Schema.define(version: 2020_10_02_112159) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "books", force: :cascade do |t|
t.string "name"
t.string "writterName"
t.text "courseName"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "employees", force: :cascade do |t|
t.string "firstName", null: false
t.string "lastName", null: false
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -15,6 +15,7 @@
"prop-types": "^15.7.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0"
},
"devDependencies": {
......
require 'rails_helper'
RSpec.describe Book, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end
require 'rails_helper'
RSpec.describe "Api::V1::Books", type: :request do
describe "GET /index" do
it "returns http success" do
get "/api/v1/book/index"
expect(response).to have_http_status(:success)
end
end
describe "GET /create" do
it "returns http success" do
get "/api/v1/book/create"
expect(response).to have_http_status(:success)
end
end
describe "GET /show" do
it "returns http success" do
get "/api/v1/book/show"
expect(response).to have_http_status(:success)
end
end
describe "GET /destroy" do
it "returns http success" do
get "/api/v1/book/destroy"
expect(response).to have_http_status(:success)
end
end
end
......@@ -7493,7 +7493,7 @@ react-router-dom@^5.2.0:
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react-router@5.2.0:
react-router@5.2.0, react-router@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293"
integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment