Skip to content
This repository was archived by the owner on Aug 8, 2019. It is now read-only.

Commit ddc5a8e

Browse files
author
Lian Nivin
authored
Merge pull request #14 from codeableorg/feature-create-sport-field
Feature create sport field
2 parents f5f782f + f710de2 commit ddc5a8e

12 files changed

Lines changed: 415 additions & 0 deletions

File tree

.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
REACT_APP_VERSION=$npm_package_version
2+
REACT_APP_API_URL=http://localhost:4000/api
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class SportFieldsController < ApplicationController
2+
3+
def create
4+
sport_field = SportField.new(sport_field_params)
5+
if sport_field.save
6+
render json: sport_field, status: :created
7+
else
8+
render json: { errors: sport_field.errors}, status: :unprocessable_entity
9+
end
10+
end
11+
12+
private
13+
def sport_field_params
14+
params.permit(:name, :description, :price_day, :price_night, :image)
15+
end
16+
17+
end

api/app/models/sport_field.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class SportField < ApplicationRecord
2+
has_one_attached :image
3+
4+
validates :name, :description, :price_day, :price_night, presence: true
5+
end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class SportFieldSerializer < ActiveModel::Serializer
2+
include Rails.application.routes.url_helpers
3+
4+
attributes :id, :name, :description, :image, :price_day, :price_night
5+
6+
def image
7+
url_for(object.image) if self.object.image.attached?
8+
end
9+
end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class CreateSportFields < ActiveRecord::Migration[5.2]
2+
def change
3+
create_table :sport_fields do |t|
4+
t.string :name
5+
t.string :description
6+
t.integer :price_day
7+
t.integer :price_night
8+
t.references :club, foreign_key: true
9+
10+
t.timestamps
11+
end
12+
end
13+
end

api/db/schema.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@
6565
t.datetime "updated_at", null: false
6666
t.index ["token"], name: "index_users_on_token"
6767
end
68+
69+
create_table "sport_fields", force: :cascade do |t|
70+
t.string "name"
71+
t.string "description"
72+
t.integer "price_day"
73+
t.integer "price_night"
74+
t.bigint "club_id"
75+
t.datetime "created_at", null: false
76+
t.datetime "updated_at", null: false
77+
t.index ["club_id"], name: "index_sport_fields_on_club_id"
78+
end
6879

6980
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
7081
add_foreign_key "sport_fields", "clubs"
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
require 'rails_helper'
2+
3+
describe SportFieldsController do
4+
5+
before do
6+
@sport_field_params = {
7+
name: 'Sport green',
8+
description: 'Some desciptiom',
9+
price_day: 70,
10+
price_night: 120,
11+
}
12+
end
13+
14+
describe 'POST create' do
15+
it 'returns http status created' do
16+
post :create, params: @sport_field_params
17+
expect(response.status).to eq(201)
18+
expect(response).to have_http_status(:created)
19+
end
20+
21+
it 'returns the sport_field created' do
22+
post :create, params: @sport_field_params
23+
expected_sport_field = JSON.parse(response.body)
24+
expect(expected_sport_field).to have_key("id")
25+
expect(expected_sport_field["name"]).to eq("Sport green")
26+
end
27+
end
28+
29+
end

client/src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Login from "./views/login";
1212
import Signup from "./views/signup";
1313
import OwnerHome from "./views/owner-home";
1414
import CreateClub from "./views/create-club";
15+
import CreateSportField from "./views/create-sport-field";
1516
import Navbar from "./components/navbar";
1617
import { register } from "./service-worker";
1718

@@ -45,6 +46,7 @@ function App() {
4546
<Signup path="/signup" />
4647
<OwnerHome path="/owner" />
4748
<CreateClub path="/create-club" />
49+
<CreateSportField path="/create-sport-field" />
4850
</Router>
4951
</main>
5052
</>

client/src/services/sport-field.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { apiUrl } from "../utils";
2+
3+
async function postSportField(sportField) {
4+
const response = await fetch(`${apiUrl}/sport_fields`, {
5+
method: "POST",
6+
credentials: "include",
7+
body: sportField,
8+
contentType: "application/json"
9+
});
10+
11+
if (!response.ok) {
12+
const errors = await response.json();
13+
throw new Error(errors);
14+
}
15+
16+
return response.json();
17+
}
18+
19+
export { postSportField };
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`CreateSportField View 1`] = `
4+
<DocumentFragment>
5+
<div
6+
class="css-2dm21w-CreateSportField"
7+
>
8+
<form>
9+
<div
10+
class="css-fzhjnh-CreateSportField"
11+
>
12+
<label
13+
class="css-1vx6px3-Label"
14+
for="name"
15+
>
16+
Name
17+
</label>
18+
<input
19+
aria-label="enter name"
20+
autocomplete="off"
21+
class="css-s3z14w-Input"
22+
id="name"
23+
name="name"
24+
placeholder="Sports field's name"
25+
required=""
26+
type="text"
27+
value=""
28+
/>
29+
</div>
30+
<div
31+
class="css-fzhjnh-CreateSportField"
32+
>
33+
<label
34+
class="css-1vx6px3-Label"
35+
for="description"
36+
>
37+
Description
38+
</label>
39+
<input
40+
aria-label="enter description"
41+
class="css-s3z14w-Input"
42+
id="description"
43+
name="description"
44+
placeholder="Sports field's description"
45+
required=""
46+
type="text"
47+
value=""
48+
/>
49+
</div>
50+
<div
51+
class="css-fzhjnh-CreateSportField"
52+
>
53+
<label
54+
class="css-1vx6px3-Label"
55+
for="image"
56+
>
57+
Image(s)
58+
</label>
59+
<input
60+
aria-label="choose image"
61+
class="css-s3z14w-Input"
62+
id="image"
63+
name="image"
64+
required=""
65+
type="file"
66+
/>
67+
</div>
68+
<div
69+
class="css-fzhjnh-CreateSportField"
70+
>
71+
<label
72+
class="css-1vx6px3-Label"
73+
>
74+
Prices
75+
</label>
76+
<div
77+
class="css-111oolb-CreateSportField"
78+
>
79+
<label
80+
class="css-ypeytr-CreateSportField"
81+
for="price_day"
82+
>
83+
Day:
84+
</label>
85+
<input
86+
aria-label="enter price-day"
87+
class="css-uqawe0-CreateSportField"
88+
id="price_day"
89+
name="price_day"
90+
required=""
91+
type="number"
92+
value=""
93+
/>
94+
</div>
95+
<div
96+
class="css-111oolb-CreateSportField"
97+
>
98+
<label
99+
class="css-ypeytr-CreateSportField"
100+
for="price_night"
101+
>
102+
Night:
103+
</label>
104+
<input
105+
aria-label="enter price-night"
106+
class="css-uqawe0-CreateSportField"
107+
id="price_night"
108+
name="price_night"
109+
required=""
110+
type="number"
111+
value=""
112+
/>
113+
</div>
114+
</div>
115+
<div
116+
class="css-fzhjnh-CreateSportField"
117+
>
118+
<button
119+
class="css-lrasnk-Button"
120+
>
121+
Create
122+
</button>
123+
</div>
124+
</form>
125+
</div>
126+
</DocumentFragment>
127+
`;

0 commit comments

Comments
 (0)