Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

56 - Page for single help request #59

Merged
merged 2 commits into from
Apr 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions app/controllers/api/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,12 @@

module API
class BaseController < ApplicationController
rescue_from ActiveRecord::RecordNotFound, with: :record_not_found

private

def record_not_found(exception)
render json: { message: "Registo com ID #{exception.id} não encontrado.", code: 'not_found' }, status: :not_found
end
end
end
7 changes: 6 additions & 1 deletion app/controllers/api/helps_controller.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
# frozen_string_literal: true

module API
class HelpsController < ApplicationController
class HelpsController < BaseController
def index
helps = Help.paginate(page: params[:page], per_page: params[:per_page] || 10).order('updated_at DESC')
render json: helps, meta: meta_attributes(helps), status: :ok
end

def show
help = Help.find(params[:id])
render json: help, status: :ok
end

def create
help = Help.new(help_params)
if help.save
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/api/volunteers_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module API
class VolunteersController < ApplicationController
class VolunteersController < BaseController
def create
volunteer = Volunteer.new(volunteer_params)
if volunteer.save
Expand Down
6 changes: 5 additions & 1 deletion app/javascript/client/AppRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Footer from './components/Footer';
import HomePage from './components/HomePage';
import RequestHelpPage from './components/RequestHelpPage';
import HelpsPage from './components/HelpsPage';
import HelpPage from './components/HelpPage';
import HowItWorks from './components/HowItWorks';

const AppRouter = () => (
Expand All @@ -20,9 +21,12 @@ const AppRouter = () => (
<Route path="/preciso-de-ajuda">
<RequestHelpPage />
</Route>
<Route path="/quero-ajudar">
<Route exact path="/quero-ajudar">
<HelpsPage />
</Route>
<Route path="/quero-ajudar/:id">
<HelpPage />
</Route>
<Route path="/como-funciona">
<HowItWorks />
</Route>
Expand Down
61 changes: 61 additions & 0 deletions app/javascript/client/components/HelpPage/HelpPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import { useParams } from 'react-router-dom';
import PropTypes from 'prop-types';

import { loadHelp } from '../../store/helps/actions';

const HelpPage = (props) => {
const { id } = useParams();

useEffect(() => {
props.loadHelp(id);
}, []);

return (
<div className="container">
<br />
<h2 className="title" style={{ marginBottom: '0px' }}>
{props.help.title}
</h2>
<p style={{ marginBottom: '15px' }}>{props.help.type}</p>

<div>{props.help.description}</div>
<br />
<button className="button">Oferecer Ajuda</button>
<br />
<br />
<div className="tabs">
<ul>
<li className="is-active">
<a>Ofertas de Ajuda Concluídas</a>
</li>
<li>
<a>Ajudas Pendentes</a>
</li>
</ul>
</div>
<div>Em Desenvolvimento...</div>
<br />
<br />
</div>
);
};

HelpPage.propTypes = {};

const mapStateToProps = (state) => {
return {
isLoading: state.helps.loading,
errors: state.helps.errors,
help: state.helps.currentHelp,
};
};

const mapDispatchToProps = (dispatch) => {
return {
loadHelp: (id) => dispatch(loadHelp(id)),
};
};

export default connect(mapStateToProps, mapDispatchToProps)(HelpPage);
3 changes: 3 additions & 0 deletions app/javascript/client/components/HelpPage/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import HelpPage from './HelpPage';

export default HelpPage;
19 changes: 18 additions & 1 deletion app/javascript/client/store/helps/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ import helpsSlice from './slice';

const { actions } = helpsSlice;

const loadHelp = (id) => {
return (dispatch, getState) => {
const state = getState();

dispatch(actions.loadHelpInit());

axios
.get(`/api/helps/${id}`)
.then((response) => {
dispatch(actions.loadHelpSuccess(response.data));
})
.catch((error) => {
dispatch(actions.loadHelpFailure(error.response.data));
});
};
};

const loadHelps = (currentPage, totalPerPage) => {
return (dispatch, getState) => {
const state = getState();
Expand Down Expand Up @@ -60,4 +77,4 @@ const createHelp = (payload) => {
};
};

export { loadHelps, createHelp };
export { loadHelp, loadHelps, createHelp };
31 changes: 31 additions & 0 deletions app/javascript/client/store/helps/slice.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { createSlice } from '@reduxjs/toolkit';
const initialState = {
loading: false,
errors: [],
currentHelp: {},
collection: [],
meta: {},
};
Expand All @@ -13,6 +14,36 @@ const helpsSlice = createSlice({
initialState,

reducers: {
loadHelpInit: (state) => {
return produce(state, (draft) => {
draft.loading = true;
draft.errors = [];
draft.currentHelp = {};
draft.collection = [];
draft.meta = {};
});
},

loadHelpSuccess: (state, action) => {
return produce(state, (draft) => {
draft.loading = false;
draft.errors = [];
draft.currentHelp = action.payload.help;
draft.collection = [];
draft.meta = {};
});
},

loadHelpFailure: (state, action) => {
return produce(state, (draft) => {
draft.loading = false;
draft.errors = action.payload;
draft.currentHelp = {};
draft.collection = [];
draft.meta = {};
});
},

loadHelpsInit: (state) => {
return produce(state, (draft) => {
draft.loading = true;
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Rails.application.routes.draw do
namespace :api, defaults: { format: :json } do
resources :volunteers, only: %i[create]
resources :helps, only: %i[index create]
resources :helps, only: %i[index show create]
end

get '*path', to: 'pages#index', constraints: ->(req) { req.path.exclude? 'storage' }
Expand Down
35 changes: 35 additions & 0 deletions spec/requests/api/helps_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,41 @@
end
end

describe 'GET /api/help/:id' do
before do
get "/api/helps/#{help_id}", headers: headers
end

context 'with existing help request' do
let(:help) { create(:help) }
let(:help_id) { help.id }

it { expect(response.content_type).to eq('application/json; charset=utf-8') }
it { expect(response).to have_http_status(:ok) }

it { expect(response.parsed_body['help']).to include('id' => Integer) }
it { expect(response.parsed_body['help']).to include('type' => String) }
it { expect(response.parsed_body['help']).to include('title' => String) }
it { expect(response.parsed_body['help']).to include('description' => String) }
it { expect(response.parsed_body['help']).to include('fullname' => String) }
it { expect(response.parsed_body['help']).to include('province' => String) }
it { expect(response.parsed_body['help']).to include('county' => String) }
it { expect(response.parsed_body['help']).to include('district' => String) }
it { expect(response.parsed_body['help']).to exclude('neighborhood' => String) }
it { expect(response.parsed_body['help']).to exclude('address' => String) }
end

context 'with non existing help request' do
let(:help_id) { 99_999 }

it { expect(response.content_type).to eq('application/json; charset=utf-8') }
it { expect(response).to have_http_status(:not_found) }

it { expect(response.parsed_body).to include('message' => "Registo com ID #{help_id} não encontrado.") }
it { expect(response.parsed_body).to include('code' => 'not_found') }
end
end

describe 'POST /api/helps' do
before do
post '/api/helps', params: params, headers: headers
Expand Down