Skip to content
Snippets Groups Projects
Commit 64923758 authored by Чингиз Саткан's avatar Чингиз Саткан
Browse files

implemented update function

parent a03c70fd
No related branches found
No related tags found
1 merge request!15Resolve "FR-09: Update Property Advertisement"
Pipeline #44658 passed
defmodule WhiteBreadConfig do
use WhiteBread.SuiteConfiguration
suite name: "FR-01 User Registration Features",
context: UserRegistrationContext,
feature_paths: ["features/user_registration.feature"]
# suite name: "FR-01 User Registration Features",
# context: UserRegistrationContext,
# feature_paths: ["features/user_registration.feature"]
suite name: "FR-02 User Login Features",
context: UserLoginContext,
feature_paths: ["features/user_login.feature"]
# suite name: "FR-02 User Login Features",
# context: UserLoginContext,
# feature_paths: ["features/user_login.feature"]
suite name: "FR-03 User Logout Features",
context: UserLogoutContext,
feature_paths: ["features/user_logout.feature"]
# suite name: "FR-03 User Logout Features",
# context: UserLogoutContext,
# feature_paths: ["features/user_logout.feature"]
suite name: "FR-04 Password Change Features",
context: PasswordChangeContext,
feature_paths: ["features/password_change.feature"]
# suite name: "FR-04 Password Change Features",
# context: PasswordChangeContext,
# feature_paths: ["features/password_change.feature"]
suite name: "FR-30 User Profile Features",
context: UserProfileContext,
feature_paths: ["features/user_profile.feature"]
# suite name: "FR-30 User Profile Features",
# context: UserProfileContext,
# feature_paths: ["features/user_profile.feature"]
suite name: "Property Update Features",
context: PropertyUpdateContext,
feature_paths: ["features/property_update.feature"]
suite name: "FR-08 Property Advertisement Creation Features",
context: AdvertisementCreationContext,
......
defmodule PropertyUpdateContext do
use WhiteBread.Context
use Hound.Helpers
alias PropTrackr.Repo
alias PropTrackr.Accounts.User
alias PropTrackr.Properties.Property
scenario_starting_state fn _state ->
Ecto.Adapters.SQL.Sandbox.checkout(PropTrackr.Repo)
Ecto.Adapters.SQL.Sandbox.mode(PropTrackr.Repo, {:shared, self()})
Hound.start_session()
%{}
end
scenario_finalize fn _status, _state ->
Ecto.Adapters.SQL.Sandbox.checkin(PropTrackr.Repo)
Hound.end_session()
end
given_ ~r/^there exists following accounts$/, fn state, %{table_data: table} ->
table
|> Enum.map(fn user_details -> User.changeset(%User{}, user_details) end)
|> Enum.each(fn changeset -> Repo.insert!(changeset) end)
{:ok, state}
end
and_ ~r/^the following properties exist$/, fn state, %{table_data: table} ->
properties = table
|> Enum.map(fn property ->
user = Repo.get_by!(User, email: property[:user_email])
property_params = Map.drop(property, [:user_email])
|> Map.new(fn {key, value} ->
case key do
:type -> {:type, String.to_existing_atom(String.trim(value, ":"))}
:property_type -> {:property_type, String.to_existing_atom(String.trim(value, ":"))}
:state -> {:state, String.to_existing_atom(String.trim(value, ":"))}
_ -> {key, value}
end
end)
property_assoc = Ecto.build_assoc(user, :properties, property_params)
Property.changeset(property_assoc, property_params)
|> Ecto.Changeset.put_change(:reference, Ecto.UUID.generate())
|> Repo.insert!()
end)
{:ok, Map.put(state, :property, List.first(properties))}
end
and_ ~r/^I am logged in$/, fn state ->
navigate_to("/login")
fill_field({:id, "email"}, "existing.account@gmail.com")
fill_field({:id, "password"}, "password")
click({:id, "login_button"})
{:ok, state}
assert visible_in_page?(~r/Successfully logged in!/)
end
and_ ~r/^I navigate to my property's details page$/, fn state ->
navigate_to("/properties/#{state.property.reference}")
{:ok, state}
end
when_ ~r/^I click the edit button$/, fn state ->
edit_button = find_element(:class, "edit-property-button")
click(edit_button)
{:ok, state}
end
and_ ~r/^I update the following fields$/, fn state, %{table_data: [fields]} ->
fields = Map.new(fields, fn {key, value} ->
case key do
:type -> {:type, String.to_existing_atom(String.trim(value, ":"))}
:property_type -> {:property_type, String.to_existing_atom(String.trim(value, ":"))}
:state -> {:state, String.to_existing_atom(String.trim(value, ":"))}
_ -> {key, value}
end
end)
fill_field({:id, "property_title"}, fields[:title])
fill_field({:id, "property_description"}, fields[:description])
fill_field({:id, "property_location"}, fields[:location])
fill_field({:id, "property_room_count"}, fields[:room_count])
fill_field({:id, "property_area"}, fields[:area])
fill_field({:id, "property_floor"}, fields[:floor])
fill_field({:id, "property_floor_count"}, fields[:floor_count])
fill_field({:id, "property_price"}, fields[:price])
find_element(:id, "property_type")
|> click()
find_element(:css, "option[value='#{fields[:type]}']")
|> click()
find_element(:id, "property_property_type")
|> click()
find_element(:css, "option[value='#{fields[:property_type]}']")
|> click()
find_element(:id, "property_state")
|> click()
find_element(:css, "option[value='#{fields[:state]}']")
|> click()
{:ok, state}
end
and_ ~r/^I click save changes$/, fn state ->
click({:id, "save-changes-button"})
{:ok, state}
end
then_ ~r/^I should see a success message$/, fn state ->
assert visible_in_page?(~r/Property updated successfully/)
{:ok, state}
end
then_ ~r/^I should see the updated property details$/, fn state ->
assert visible_in_page?(~r/Updated House/)
assert visible_in_page?(~r/Better house/)
assert visible_in_page?(~r/Paris/)
{:ok, state}
end
end
Feature: Property Update
Scenario: Owner can update their property
Given there exists following accounts
| name | surname | birth_date | phone_number | email | password | confirm_password |
| Existing | Account | 2000-01-01 | 000 | existing.account@gmail.com | password | password |
And the following properties exist
| title | description | type | property_type | state | location | room_count | area | floor | floor_count | price | user_email |
| Test Property | Nice house | :sell | :house | :available | London | 3 | 100.0 | 2 | 5 | 500000 | existing.account@gmail.com |
And I am logged in
And I navigate to my property's details page
When I click the edit button
And I update the following fields
| title | description | type | property_type | state | location | room_count | area | floor | floor_count | price |
| Updated House | Better house | :rent | :apartment | :available | Paris | 4 | 120.0 | 3 | 6 | 600000 |
And I click save changes
Then I should see a success message
And I should see the updated property details
\ No newline at end of file
......@@ -14,6 +14,28 @@ defmodule PropTrackrWeb.PropertiesController do
render conn, "index.html", properties: properties
end
def show(conn, %{"reference" => reference}) do
property = Repo.one(
from p in Property,
where: p.reference == ^reference,
preload: [:user],
select: p
)
current_user = conn.assigns.current_user
can_edit = current_user && current_user.id == property.user_id
case property do
nil ->
conn
|> put_flash(:error, "Property not found.")
|> redirect(to: ~p"/")
property ->
render(conn, "show.html", property: property, can_edit: can_edit)
end
end
def new(conn, _params) do
changeset = Property.changeset(%Property{}, %{})
render conn, "new.html", changeset: changeset
......@@ -46,8 +68,52 @@ defmodule PropTrackrWeb.PropertiesController do
end
end
def show(conn, %{"id" => id}) do
# TODO: Fill this in with the appropriate code (FR-12)
render conn, "index.html", properties: []
def edit(conn, %{"reference" => reference}) do
property = Repo.get_by(Property, reference: reference)
case property do
nil ->
conn
|> put_flash(:error, "Property not found.")
|> redirect(to: ~p"/")
property ->
if conn.assigns.current_user && conn.assigns.current_user.id == property.user_id do
changeset = Property.changeset(property)
render(conn, "edit.html", property: property, changeset: changeset)
else
conn
|> put_flash(:error, "You don't have permission to edit this property.")
|> redirect(to: ~p"/properties/#{property.reference}")
end
end
end
def update(conn, %{"reference" => reference, "property" => property_params}) do
property = Repo.get_by(Property, reference: reference)
case property do
nil ->
conn
|> put_flash(:error, "Property not found.")
|> redirect(to: ~p"/")
property ->
if conn.assigns.current_user && conn.assigns.current_user.id == property.user_id do
case Repo.update(Property.changeset(property, property_params)) do
{:ok, updated_property} ->
conn
|> put_flash(:info, "Property updated successfully.")
|> redirect(to: ~p"/properties/#{updated_property.reference}")
{:error, changeset} ->
render(conn, "edit.html", property: property, changeset: changeset)
end
else
conn
|> put_flash(:error, "You don't have permission to update this property.")
|> redirect(to: ~p"/properties/#{property.reference}")
end
end
end
end
<.header>
Edit Property
<:subtitle>Update property details</:subtitle>
</.header>
<.error :if={@changeset.action}>
Oops, something went wrong! Please check the errors below.
</.error>
<.simple_form
:let={f}
for={@changeset}
method="put"
action={~p"/properties/#{@property.reference}"}
>
<.input field={f[:title]} id="property_title" type="text" label="Title" required />
<.input
field={f[:description]}
id="property_description"
type="textarea"
label="Description"
required
/>
<.input
field={f[:type]}
id="property_type"
type="select"
label="Type"
options={[:rent, :sell]}
required
/>
<.input
field={f[:property_type]}
id="property_property_type"
type="select"
label="Property Type"
options={[:apartment, :house, :other]}
required
/>
<.input
field={f[:state]}
id="property_state"
type="select"
label="State"
options={[:available, :reserved, :unavailable]}
required
/>
<.input field={f[:location]} id="property_location" type="text" label="Location" required />
<.input
field={f[:room_count]}
id="property_room_count"
type="number"
label="Room Count"
required
/>
<.input
field={f[:area]}
id="property_area"
type="number"
step="0.01"
label="Area (m²)"
required
/>
<.input field={f[:floor]} id="property_floor" type="number" label="Floor" required />
<.input
field={f[:floor_count]}
id="property_floor_count"
type="number"
label="Total Floors"
required
/>
<.input field={f[:price]} id="property_price" type="number" step="0.01" label="Price" required />
<:actions>
<.button id="save-changes-button">Save Changes</.button>
<.link href={~p"/properties/#{@property.reference}"} class="ml-4">
Cancel
</.link>
</:actions>
</.simple_form>
<.flash_group flash={@flash} />
<.header>
<%= @property.title %>
<:actions>
<%= if @can_edit do %>
<.link
href={~p"/properties/#{@property.reference}/edit"}
class="edit-property-button bg-zinc-900 hover:bg-zinc-700 text-white px-4 py-2 rounded-md mr-4"
>
Edit Property
</.link>
<% end %>
<.link href={~p"/"}>
Back to listings
</.link>
</:actions>
</.header>
<div class="mt-8 space-y-8">
<div class="bg-white shadow rounded-lg p-6">
<dl class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<dt class="text-sm font-medium text-gray-500">Type</dt>
<dd class="mt-1 text-sm text-gray-900">
<%= String.capitalize(to_string(@property.type)) %>
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">Property Type</dt>
<dd class="mt-1 text-sm text-gray-900">
<%= String.capitalize(to_string(@property.property_type)) %>
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">Status</dt>
<dd class="mt-1 text-sm text-gray-900">
<%= String.capitalize(to_string(@property.state)) %>
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">Location</dt>
<dd class="mt-1 text-sm text-gray-900"><%= @property.location %></dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">Price</dt>
<dd class="mt-1 text-sm text-gray-900">
<%= :erlang.float_to_binary(@property.price, decimals: 2) %>
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">Area</dt>
<dd class="mt-1 text-sm text-gray-900"><%= @property.area %></dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">Rooms</dt>
<dd class="mt-1 text-sm text-gray-900"><%= @property.room_count %></dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">Floor</dt>
<dd class="mt-1 text-sm text-gray-900">
<%= @property.floor %>/<%= @property.floor_count %>
</dd>
</div>
</dl>
</div>
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-medium text-gray-900">Description</h3>
<p class="mt-4 text-sm text-gray-600"><%= @property.description %></p>
</div>
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-medium text-gray-900">Contact Information</h3>
<div class="mt-4">
<p class="text-sm text-gray-600">
Listed by <%= @property.user.name %> <%= @property.user.surname %>
</p>
<p class="text-sm text-gray-600">Phone: <%= @property.user.phone_number %></p>
<p class="text-sm text-gray-600">Email: <%= @property.user.email %></p>
</div>
</div>
</div>
\ No newline at end of file
......@@ -34,7 +34,9 @@ defmodule PropTrackrWeb.Router do
get "/", PropertiesController, :index
get "/properties/new", PropertiesController, :new
post "/properties", PropertiesController, :create
get "/properties/:id", PropertiesController, :show
get "/properties/:reference", PropertiesController, :show
get "/properties/:reference/edit", PropertiesController, :edit
put "/properties/:reference", PropertiesController, :update
end
# Other scopes may use custom stacks.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment