Skip to content
Snippets Groups Projects
Commit cb64f21d authored by snaqvi's avatar snaqvi
Browse files

QA fixes

parent 7b1549fe
No related branches found
No related tags found
1 merge request!112QA fixes
Pipeline #47173 failed
......@@ -39,6 +39,7 @@ defmodule Proptracker.Accounts.Advertisement do
|> validate_number(:rooms, greater_than_or_equal_to: 0, message: "must be a positive number")
|> validate_number(:floor, greater_than_or_equal_to: 0, message: "must be a positive number")
|> validate_number(:total_floors, greater_than_or_equal_to: 0, message: "must be a positive number")
|> validate_floor_not_greater_than_total_floors()
|> validate_pictures()
|> generate_reference()
end
......@@ -52,6 +53,17 @@ defmodule Proptracker.Accounts.Advertisement do
end
end
defp validate_floor_not_greater_than_total_floors(changeset) do
floor = get_field(changeset, :floor)
total_floors = get_field(changeset, :total_floors)
if floor && total_floors && floor > total_floors do
add_error(changeset, :floor, "Floor cannot be greater than total floors")
else
changeset
end
end
defp validate_pictures(changeset) do
pictures = get_field(changeset, :pictures) || []
......
......@@ -74,15 +74,17 @@ defmodule Proptracker.Accounts.User do
defp validate_phone_number(changeset) do
phone_number = get_field(changeset, :phone_number)
# Check if the phone number is a valid positive number with at least 6 digits
if phone_number && (String.length(phone_number) < 6 or String.to_integer(phone_number) < 0) do
add_error(changeset, :phone_number, "must be a positive number with at least 6 digits")
if phone_number && String.length(phone_number) < 6 do
add_error(changeset, :phone_number, "must be at least 6 characters long")
else
changeset
if phone_number && Regex.match?(~r/^\+?[0-9]+$/, phone_number) do
changeset
else
add_error(changeset, :phone_number, "must only contain digits and may start with '+'")
end
end
end
defp validate_date_of_birth(changeset) do
date_of_birth = get_field(changeset, :date_of_birth)
......
......@@ -26,27 +26,65 @@ defmodule ProptrackerWeb.AdvertisementController do
end
#for search special:
def user_search(conn, %{"type" => type,"location" => location, "query" => query}) do
def user_search(conn, params) do
user_id = get_session(conn, :user_id)
# Retrieve the current user if logged in
current_user = if user_id, do: Repo.get(Proptracker.Accounts.User, user_id), else: nil
advertisements = Advertisement.list_advertisements_by_user(current_user.id)
# Extract filter parameters
type = Map.get(params, "type", "")
query = Map.get(params, "query", "")
location = Map.get(params, "location", "")
state = Map.get(params, "state", "")
min_price = Map.get(params, "min_price") |> parse_optional_integer()
max_price = Map.get(params, "max_price") |> parse_optional_integer()
min_rooms = Map.get(params, "min_rooms") |> parse_optional_integer()
max_rooms = Map.get(params, "max_rooms") |> parse_optional_integer()
# Query with required fields and filters
advertisements =
advertisements
|> (fn ads -> if type != "", do: Enum.filter(ads, &(&1.type == type)), else: ads end).()
|> (fn ads -> if query != "", do: Enum.filter(ads, &(String.contains?(&1.title, query))), else: ads end).()
|> (fn ads -> if location != "", do: Enum.filter(ads, &(String.contains?(&1.location, location))), else: ads end).()
Advertisement
|> where([a], a.user_id == ^current_user.id) # Fetch only the current user's advertisements
|> (fn q -> if type != "", do: from(a in q, where: a.type == ^type), else: q end).()
|> (fn q -> if query != "", do: from(a in q, where: ilike(a.title, ^"%#{query}%")), else: q end).()
|> (fn q -> if location != "", do: from(a in q, where: ilike(a.location, ^"%#{location}%")), else: q end).()
|> (fn q -> if state != "", do: from(a in q, where: a.state == ^state), else: q end).()
|> (fn q -> if min_price, do: from(a in q, where: a.price >= ^min_price), else: q end).()
|> (fn q -> if max_price, do: from(a in q, where: a.price <= ^max_price), else: q end).()
|> (fn q -> if min_rooms, do: from(a in q, where: a.rooms >= ^min_rooms), else: q end).()
|> (fn q -> if max_rooms, do: from(a in q, where: a.rooms <= ^max_rooms), else: q end).()
|> where([a], a.state != "sold/rented") # Exclude 'sold/rented'
|> order_by([a], asc: a.state) # Order by state ('available' first)
|> select([a], %{
id: a.id,
title: a.title,
price: a.price,
location: a.location,
type: a.type,
rooms: a.rooms,
state: a.state
}) # Select only the required fields
|> Repo.all()
render(conn, "index.html",
advertisements: advertisements,
current_user: current_user,
location: location,
query: query,
type: nil,
query: ","
advertisements: advertisements,
current_user: current_user,
location: location,
query: query,
type: type
)
end
# Helper function to parse optional integers
defp parse_optional_integer(value) do
case Integer.parse(value || "") do
{num, _} -> num
:error -> nil
end
end
# Show form for creating a new advertisement
def new(conn, _params) do
changeset = Advertisement.changeset(%Advertisement{}, %{})
......@@ -174,7 +212,7 @@ defmodule ProptrackerWeb.AdvertisementController do
# Show advertisement details
def show(conn, %{"id" => id}) do
advertisement = Advertisement.get_advertisement!(id)
user_id = get_session(conn, :user_id)
user_id = advertisement.user_id
all_advertisements = Repo.all(Advertisement)
recommended_properties = Advertisement.get_similar_advertisements(advertisement, all_advertisements)
......
......@@ -74,19 +74,14 @@
<!-- Loop through each advertisement and display them in a box -->
<%= for ad <- @advertisements do %>
<div class="advertisement-box">
<.link navigate={~p"/advertisements/#{ad.id}"}>
<!-- If advertisement has an image, display it, otherwise fallback to a placeholder box -->
<div class="advertisement-image">
<%= if ad.pictures != nil and Enum.any?(ad.pictures) do %>
<%= for picture <- ad.pictures do %>
<img src={"http://localhost:4000#{URI.encode(picture)}"} alt="Advertisement Image" class="advertisement-image-img" />
<% end %>
<% else %>
<img src="https://media.istockphoto.com/id/1319269543/photo/new-homes-on-a-quiet-street-in-raleigh-nc.jpg?s=612x612&w=0&k=20&c=qaRMP-xgYqFAXR9aTpiG0dtkyqPhJiTAovvxyG1AxvM=" alt="Advertisement Image" class="advertisement-image-img" />
<% end %>
</div>
<.link navigate={~p"/advertisements/#{ad.id}"}>
<div class="advertisement-image">
<img src={List.first(ad.pictures)} alt="Advertisement Image" class="advertisement-image-img" />
</div>
</.link>
<div class="advertisement-info">
<div class="advertisement-title"><%= ad.title %></div>
<div class="advertisement-title">Title:<%= ad.title %></div>
<div class="advertisement-type" style="color:red"><%= ad.type %></div>
<div class="advertisement-price"><%= ad.price %></div>
<div class="advertisement-location"><%= ad.location %></div>
......@@ -97,26 +92,11 @@
Change Status
</button>
</div>
<div class="advertisement-interest">
<!-- Display current interest -->
<span id={"ad-interest-#{ad.id}"} hidden><%= ad.interest %></span>
<!-- Button to toggle interest -->
<button class="change-interest-button"
data-ad-id={ad.id}
data-current-interest={ad.interest}
style={"padding: 12px 20px; border-radius: 50px; border: none; color: #000; font-size: 1em; background-color: #{if ad.interest == "interest", do: "#FFD700", else: "#FF0000"};"}>
<%= if ad.interest == "interest", do: "Interest", else: "Not Interest" %>
</button>
</div>
<div class="advertisement-actions">
<.link navigate={~p"/advertisements/#{ad.id}/edit"}>Edit</.link> |
<.link href={~p"/advertisements/#{ad.id}"} method="delete" data-confirm="Are you sure?">Delete</.link>
</div>
</div>
</.link>
</div>
<% end %>
</div>
......
......@@ -195,7 +195,7 @@
<%= String.capitalize(@advertisement.state) %>
</span></p>
<p><strong>Reference:</strong> <%= @advertisement.reference %></p>
<a href="https://www.facebook.com/sharer/sharer.php?u=http://localhost:4000/advertisements/{@advertisement.id}" target="_blank">
<a href="https://www.facebook.com/sharer/sharer.php?u=http://193.40.11.154/advertisements/{@advertisement.id}" target="_blank">
<button class="social-button facebook">Share on Facebook</button>
</a>
......
......@@ -348,14 +348,14 @@
<!-- Price Range Group -->
<div class="form-group price-range-group">
<input type="number" name="min_price" id="min_price" class="search-bar" placeholder="Min Price" value={@min_price} />
<input type="number" name="min_price" id="min_price" class="search-bar" placeholder="Min Price" value={@min_price} min="0" />
<span class="price-range-divider">-</span>
<input type="number" name="max_price" id="max_price" class="search-bar" placeholder="Max Price" value={@max_price} />
<input type="number" name="max_price" id="max_price" class="search-bar" placeholder="Max Price" value={@max_price} min="0" />
</div>
<div class="form-group price-range-group">
<input type="number" name="min_rooms" id="min_rooms" class="search-bar" placeholder="Min Room" value={@min_rooms} />
<input type="number" name="min_rooms" id="min_rooms" class="search-bar" placeholder="Min Room" value={@min_rooms} min="0"/>
<span class="price-range-divider">-</span>
<input type="number" name="max_rooms" id="max_rooms" class="search-bar" placeholder="Max Room" value={@max_rooms} />
<input type="number" name="max_rooms" id="max_rooms" class="search-bar" placeholder="Max Room" value={@max_rooms} min="0"/>
</div>
<!-- General Search Query -->
......
......@@ -194,7 +194,7 @@
<div class="team-container">
<!-- Team Member 1 -->
<div class="team-member">
<img src="https://scontent-arn2-1.xx.fbcdn.net/v/t39.30808-6/462476088_7687672951335713_2417806445325039509_n.jpg?stp=cp6_dst-jpg&_nc_cat=103&ccb=1-7&_nc_sid=6ee11a&_nc_ohc=qaPJSMePkIIQ7kNvgHOPi7l&_nc_zt=23&_nc_ht=scontent-arn2-1.xx&_nc_gid=AflroXJvEQ93ANQExzHIFnW&oh=00_AYB9oRpEiIk1Emn0UYHILwWN-Jee8VQZxGZTQrjubwsnxQ&oe=67549893" alt="Syed Fakhar" />
<img src={"/adverts/syed.jpg"} alt="Default Image" class="main-image" />
<a href="https://www.linkedin.com/in/syedfakhar25/" class="name" target="_blank">
Syed Fakhar
</a>
......@@ -212,7 +212,7 @@
<!-- Team Member 3 -->
<div class="team-member">
<img src="https://scontent-arn2-1.xx.fbcdn.net/v/t39.30808-6/420082505_3478675459114118_8250845256068338403_n.jpg?_nc_cat=107&ccb=1-7&_nc_sid=6ee11a&_nc_ohc=YFaXC7FogfsQ7kNvgGqLbgn&_nc_zt=23&_nc_ht=scontent-arn2-1.xx&_nc_gid=AGx_FrXtHoSjU7vcSnMk9cJ&oh=00_AYAnn4HCFVyf9zayt5WYXEtXTbAK-KZfdzCJwq7LYO5Llg&oe=6754B796" alt="Zeshan" />
<img src={"/adverts/zeshan.jpg"} alt="Default Image" class="main-image" />
<a href="https://www.linkedin.com/in/se-zeshanhyder/" class="name" target="_blank">
Zeshan
</a>
......@@ -221,7 +221,7 @@
<!-- Team Member 4 -->
<div class="team-member">
<img src="https://scontent-arn2-1.xx.fbcdn.net/v/t39.30808-6/457624764_2948490998632349_2614846846593177558_n.jpg?_nc_cat=110&ccb=1-7&_nc_sid=6ee11a&_nc_ohc=OcO_XWtU78sQ7kNvgHp7MNb&_nc_zt=23&_nc_ht=scontent-arn2-1.xx&_nc_gid=AdkeVDnH0vgBgCdjxe-KYWE&oh=00_AYCp2PYB08BamygeJaYwYEsbLEv1kTnSsc4XGEEt44QNug&oe=6754A1CD" alt="Md Misu" />
<img src={"/adverts/misu.jpg"} alt="Default Image" class="main-image" />
<a href="https://www.linkedin.com/in/md-murad-alahi-misu-b39737184/" class="name" target="_blank">
Md Misu
</a>
......
......@@ -8,8 +8,20 @@ defmodule ProptrackerWeb.UserController do
import Ecto.Query
def index(conn, _params) do
users = Repo.all(User)
render(conn, "index.html", users: users)
# Get the current authenticated user from the connection assigns
current_user = conn.assigns[:current_user]
if current_user do
# Fetch only the current user's data
user = Repo.get!(User, current_user.id)
render(conn, "index.html", users: [user]) # Pass as a list for consistency
else
# Redirect or render an error page if no user is logged in
conn
|> put_flash(:error, "You need to log in to view this page.")
|> redirect(to: ~p"/login")
|> halt()
end
end
def new(conn, _params) do
......
priv/static/adverts/misu.jpg

87.9 KiB

priv/static/adverts/syed.jpg

314 KiB

priv/static/adverts/zeshan.jpg

101 KiB

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