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

Added search bar in Patients #141

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
19 changes: 1 addition & 18 deletions app/controllers/patients_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,7 @@ class PatientsController < ApplicationController

# GET /patients/
def index
@search_text = params.fetch(:search, "")
@facility_id = params.fetch(:facility, "")

@facilities = policy_scope(Facility).map { |f| [f.name, f.id] }
@facilities.unshift(["all", nil])

# filter and paginate
@patients = filter_patients(@search_text, @facility_id)
authorize Patient
@patients = Patient.get_formatted
end

# GET /patients/new
Expand Down Expand Up @@ -102,13 +94,4 @@ def patient_params
:facility_id,
)
end

def filter_patients(search_text, facility_id)
return policy_scope(Patient).where(facility_id: facility_id) if (facility_id != "")

policy_scope(Patient).where(
"full_name ILIKE :search_text",
search_text: "%#{search_text}%",
)
end
end
47 changes: 47 additions & 0 deletions app/javascript/Patient/Patients.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
type patient = Patients__Types.patient
type props = Patients__Types.props

let s = React.string

@react.component
let make = (~props: props) => {
let (patients, setPatients) = React.useState(_ => props.patients)
let (searchTerm, setSearchTerm) = React.useState(_ => "")

React.useEffect1(() => {
let search_term = searchTerm->Js.String.toLowerCase
let filtered_patients =
props.patients->Js.Array2.filter(patient =>
search_term->Js.String.includes(patient.name->Js.String.toLowerCase) ||
search_term->Js.String.includes(patient.address->Js.String.toLowerCase) ||
search_term->Js.String.includes(patient.phone->Js.String.toLowerCase)
)

setPatients(_ => filtered_patients)
None
}, [searchTerm])

<div className=" py-6">
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div className="flex mb-5 ml-1 items-center justify-between">
<div className="font-semibold text-xl">{s("Patients")}</div>

<div className="flex space-x-4">
<Link
className="cursor-pointer inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
href="patients/new"
text="Create New Patient"
/>
</div>
</div>
<div className="flex flex-col">
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
<Patients__Search placeholder="Search Patients" setSearchTerm />
<Patients__PatientsTable patients />
</div>
</div>
</div>
</div>
</div>
}
23 changes: 23 additions & 0 deletions app/javascript/Patient/Patients__Types.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
type patient = {
id: string,
name: string,
dob: Js.Date.t,
phone: string,
address: string,
}

type patients = array<patient>

type props = {patients: patients}


let decode = json => {
open Json.Decode
{
id: field("id", string, json),
name: field("name", string, json),
dob: field("dob", date, json),
phone: field("phone", string, json),
address: field("address", string, json)
}
}
15 changes: 15 additions & 0 deletions app/javascript/Patient/components/Link.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@val external window: {..} = "window"

let s = React.string

@react.component
let make = (~className: string, ~href: string, ~text: string) => {
<a
className={className}
onClick={event => {
event->ReactEvent.Mouse.stopPropagation
window["location"]["href"] = href
}}>
{s(text)}
</a>
}
84 changes: 84 additions & 0 deletions app/javascript/Patient/components/Patients__PatientsTable.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
type patient = Patients__Types.patient
type patients = Patients__Types.patients

let s = React.string


module Patient = {
@react.component
let make = (~patient: patient) => {
<tr className="bg-white">
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
{s(patient.name)}
</td>

<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{s(patient.dob->Js.Date.toDateString)}
</td>

<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{s(patient.phone)}
</td>

<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{s(patient.address)}
</td>

<td className="px-6 py-4 whitespace-nowrap text-center text-sm font-medium">
<Link
className="cursor-pointer text-indigo-600 hover:text-indigo-900"
href={`patients/${patient.id}`}
text="Visit"
/>
</td>
</tr>
}
}


@react.component
let make = (~patients: patients) => {


<div className="shadow overflow-hidden border-b border-gray-200 rounded-lg">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<tr>
<th
scope="col"
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
{s("Full Name")}
</th>
<th
scope="col"
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
{s("Date of Birth")}
</th>
<th
scope="col"
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
{s("Phone")}
</th>
<th
scope="col"
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
{s("Address")}
</th>
<th
scope="col"
colSpan={2}
className="px-6 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">
{s("Actions")}
</th>
</tr>
</thead>
<tbody>
{
patients->Js.Array2.map(patient =>
<Patient key={patient.id} patient />
)->React.array
}
</tbody>
</table>
</div>
}
23 changes: 23 additions & 0 deletions app/javascript/Patient/components/Patients__Search.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@react.component
let make = (~setSearchTerm, ~placeholder="Search") => {
let onSearchTermChange = event => {
let value = ReactEvent.Form.currentTarget(event)["value"]

setSearchTerm(_ => value)
}

<div className="relative mb-4">
<input
type_="text"
className="block w-full bg-white border border-gray-300 rounded-md py-2 pl-3 text-sm placeholder-gray-500 focus:outline-none focus:text-gray-900 focus:placeholder-gray-400 focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
placeholder={placeholder}
onChange={onSearchTermChange}
/>

<div className="absolute inset-y-0 right-0 pr-3 flex items-center">
<div className="cursor-pointer focus:outline-none">
<i className="fas fa-search" />
</div>
</div>
</div>
}
15 changes: 15 additions & 0 deletions app/javascript/packs/PatientsPack.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
type props = Patients__Types.props

let decode: Js.Json.t => props = json => {
open Json.Decode
{
patients: field("patients", array(Patients__Types.decode), json),
}
}
let props = DomUtils.parseJSONTag(~id="patients-data", ()) |> decode


switch ReactDOM.querySelector(`#patients`) {
| Some(id) => ReactDOM.render(<Patients props />, id)
| None => ()
}
14 changes: 7 additions & 7 deletions app/javascript/schedule/Schedule.res
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ let make = (~props: props) => {
let (sortOption, setSortOption) = React.useState(_ => "next_visit")
let (sortAscending, setSortAscending) = React.useState(_ => true)
let (patients, updatePatients) = React.useReducer(
Patients.reducer,
Schedule__Patients.reducer,
{unselectedPatients: props.patients, selectedPatients: []},
)
let (filters, updateFilters) = React.useReducer(Filter.reducer, {procedures: [], wards: []})
let (filters, updateFilters) = React.useReducer(Schedule__Filter.reducer, {procedures: [], wards: []})

React.useEffect4(() => {
let procedure_filtered_patients = !(filters.procedures->length == 0)
Expand Down Expand Up @@ -41,20 +41,20 @@ let make = (~props: props) => {

let sorted_patients = filtered_patients->Schedule__Utils.jssort(sortOption, sortAscending)

Patients.SetUnSelectedPatients(sorted_patients)->updatePatients
Schedule__Patients.SetUnSelectedPatients(sorted_patients)->updatePatients
None
}, (searchTerm, sortOption, sortAscending, filters))

<div>
<div className="p-8 sm:flex items-center justify-center self-center text-center bg-white">
<Search setSearchTerm placeholder="Search Patients" />
<Sort setSortOption sortAscending setSortAscending />
<Filter
<Schedule__Search setSearchTerm placeholder="Search Patients" />
<Schedule__Sort setSortOption sortAscending setSortAscending />
<Schedule__Filter
procedures={props.patients->Schedule__Utils.jsunion("procedures")}
selectedFilters={filters}
updateFilters
/>
</div>
<Patients patients updatePatients />
<Schedule__Patients patients updatePatients />
</div>
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ module FilterSection = {

<div className="py-1">
<div className="text-center p-2 font-bold"> {s(name ++ "(s)")} </div>
{searchbar ? <Search setSearchTerm placeholder={"Search " ++ name ++ "(s)"} /> : <div />}
{searchbar ? <Schedule__Search setSearchTerm placeholder={"Search " ++ name ++ "(s)"} /> : <div />}
<div className="grid grid-cols-1 justify-items-start md:grid-cols-2">
{options
->Belt.Array.map(option =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,20 @@ let make = (~patients, ~updatePatients) => {
upatients
->Js.Array2.slice(~start=(pageNumber - 1) * perPage, ~end_=pageNumber * perPage)
->Js.Array2.map(patient =>
<UnselectedPatient
<Schedule__UnselectedPatient
key={patient.id} patient selectPatient={patient => patient->SelectPatient->updatePatients}
/>
)

<div>
<SelectedPatients
<Schedule__SelectedPatients
selectedPatients={spatients}
unselectPatient={patient => patient->UnselectPatient->updatePatients}
/>
<ul className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
{patientList->React.array}
</ul>
<Pagination
<Schedule__Pagination
pageNumber
setPageNumber
maxPages={
Expand Down
12 changes: 12 additions & 0 deletions app/models/patient.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ class Patient < ApplicationRecord
very_poor: "Very Poor",
}

def self.get_formatted
all.map do |patient|
{
name: patient.full_name,
dob: patient.dob,
phone: patient.phone,
address: patient.address,
id: patient.id
}
end
end

def add_users(user_ids)
user_ids.each do |user_id|
self.users << User.find(user_id)
Expand Down
2 changes: 1 addition & 1 deletion app/views/patients/_table-row.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<tr class="bg-white" x-description="Odd row">
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
<%= patient.full_name %>
<%= patient.name %>
</td>

<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
Expand Down
Loading