Version 3 #40
|
@ -228,6 +228,13 @@ span.jjj-audio-clip:hover {
|
|||
border: solid 1px lightgray;
|
||||
border-radius: .5rem;
|
||||
}
|
||||
/* Collapse Panel styling */
|
||||
a[data-bs-toggle] {
|
||||
color: var(--bs-body-color);
|
||||
}
|
||||
a[data-bs-toggle]:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
/* Footer styling */
|
||||
footer {
|
||||
display: flex;
|
||||
|
|
|
@ -100,16 +100,16 @@ let markdownEditor attrs name value editorLabel isHtmx =
|
|||
]
|
||||
|
||||
/// Wrap content in a collapsing panel
|
||||
let collapsePanel header content =
|
||||
let collapsePanel header isShown content =
|
||||
let showClass = if isShown then " show" else ""
|
||||
div [ _class "card" ] [
|
||||
div [ _class "card-body" ] [
|
||||
h6 [ _class "card-title" ] [
|
||||
// TODO: toggle collapse
|
||||
//a [ _href "#"; _class "{ 'cp-c': collapsed, 'cp-o': !collapsed }"; @click.prevent="toggle">{{headerText}} ]
|
||||
txt header
|
||||
div [ _class "card-header" ] [
|
||||
h6 [ _class "mb-0 card-title" ] [
|
||||
a [ _href "#jjjCollapse"; _data "bs-toggle" "collapse"; _roleButton; _ariaControls "#jjjCollapse"
|
||||
_ariaExpanded (isShown.ToString().ToLowerInvariant ()) ] [ txt header ]
|
||||
]
|
||||
yield! content
|
||||
]
|
||||
div [ _id "jjjCollapse"; _class $"card-body collapse{showClass}" ] content
|
||||
]
|
||||
|
||||
/// "Yes" or "No" based on a boolean value
|
||||
|
@ -242,7 +242,7 @@ module Layout =
|
|||
if ctx.IsLoggedOn then
|
||||
navLink "/citizen/dashboard" "view-dashboard-variant" "Dashboard"
|
||||
navLink "/help-wanted" "newspaper-variant-multiple-outline" "Help Wanted!"
|
||||
navLink "/profile/search" "view-list-outline" "Employment Profiles"
|
||||
navLink "/profile/search" "view-list-outline" "Job Seekers"
|
||||
navLink "/success-stories" "thumb-up" "Success Stories"
|
||||
div [ _class "separator" ] []
|
||||
navLink "/citizen/account" "account-edit" "My Account"
|
||||
|
@ -252,7 +252,7 @@ module Layout =
|
|||
navLink "/citizen/log-off" "logout-variant" "Log Off"
|
||||
else
|
||||
navLink "/" "home" "Home"
|
||||
navLink "/profile/search" "view-list-outline" "Employment Profiles"
|
||||
navLink "/profile/search" "view-list-outline" "Job Seekers"
|
||||
navLink "/citizen/log-on" "login-variant" "Log On"
|
||||
navLink "/how-it-works" "help-circle-outline" "How It Works"
|
||||
]
|
||||
|
|
|
@ -854,14 +854,15 @@ module Help =
|
|||
|
||||
h5 [] [ txt "Search Criteria" ]
|
||||
p [] [
|
||||
txt "The employment profile search form is the same whether there is a user logged on or not; however, "
|
||||
txt "the results are different. There are three sections to the search form. "
|
||||
strong [] [ txt "Continent" ]; txt " will select profiles from the selected continent, while "
|
||||
strong [] [ txt "Seeking Remote Work?" ]; txt " will select profiles based whether the citizen has "
|
||||
txt "selected remote work in their profile. "; strong [] [ txt "Text Search" ]; txt " will search "
|
||||
txt "several aspects of the employment profile for matches; it is case-insensitive and will match "
|
||||
txt "using English stemming rules (ex. searching for “force” will match words like "
|
||||
txt "“force”, “forced”, or “forcing”)."
|
||||
txt "The "; span [ linkedPage ] [ txt "Job Seekers" ]; txt " page and its search form is the same "
|
||||
txt "whether there is a user logged on or not; however, the results are different. There are three "
|
||||
txt "sections to the search form. "; strong [] [ txt "Continent" ]; txt " will select profiles from "
|
||||
txt "the selected continent, while "; strong [] [ txt "Seeking Remote Work?" ]; txt " will select "
|
||||
txt "profiles based whether the citizen has selected remote work in their profile. "
|
||||
strong [] [ txt "Text Search" ]; txt " will search several aspects of the employment profile for "
|
||||
txt "matches; it is case-insensitive and will match using English stemming rules (ex. searching for "
|
||||
txt "“force” will match words like “force”, “forced”, or "
|
||||
txt "“forcing”)."
|
||||
]
|
||||
p [] [
|
||||
txt "If more than one field has a value selected, profiles must match all of those selections to be "
|
||||
|
|
|
@ -9,41 +9,40 @@ open JobsJobsJobs.Listings.Domain
|
|||
|
||||
/// Job listing edit page
|
||||
let edit (m : EditListingForm) continents isNew isHtmx csrf =
|
||||
pageWithTitle $"""{if isNew then "Add a" else "Edit"} Job Listing""" [
|
||||
form [ _class "row g-3"; _method "POST"; _action "/listing/save" ] [
|
||||
antiForgery csrf
|
||||
input [ _type "hidden"; _name (nameof m.Id); _value m.Id ]
|
||||
div [ _class "col-12 col-sm-10 col-md-8 col-lg-6" ] [
|
||||
textBox [ _type "text"; _maxlength "255"; _autofocus ] (nameof m.Title) m.Title "Title" true
|
||||
div [ _class "form-text" ] [
|
||||
txt "No need to put location here; it will always be show to seekers with continent and region"
|
||||
]
|
||||
form [ _class "row g-3"; _method "POST"; _action "/listing/save" ] [
|
||||
antiForgery csrf
|
||||
input [ _type "hidden"; _name (nameof m.Id); _value m.Id ]
|
||||
div [ _class "col-12 col-sm-10 col-md-8 col-lg-6" ] [
|
||||
textBox [ _type "text"; _maxlength "255"; _autofocus ] (nameof m.Title) m.Title "Title" true
|
||||
div [ _class "form-text" ] [
|
||||
txt "No need to put location here; it will always be show to seekers with continent and region"
|
||||
]
|
||||
div [ _class "col-12 col-sm-6 col-md-4" ] [
|
||||
continentList [] (nameof m.ContinentId) continents None m.ContinentId true
|
||||
]
|
||||
div [ _class "col-12 col-sm-6 col-md-8" ] [
|
||||
textBox [ _type "text"; _maxlength "255" ] (nameof m.Region) m.Region "Region" true
|
||||
div [ _class "form-text" ] [ txt "Country, state, geographic area, etc." ]
|
||||
]
|
||||
div [ _class "col-12" ] [
|
||||
checkBox [] (nameof m.RemoteWork) m.RemoteWork "This opportunity is for remote work"
|
||||
]
|
||||
markdownEditor [ _required ] (nameof m.Text) m.Text "Job Description" isHtmx
|
||||
div [ _class "col-12 col-md-4" ] [
|
||||
textBox [ _type "date" ] (nameof m.NeededBy) m.NeededBy "Needed By" false
|
||||
]
|
||||
div [ _class "col-12" ] [ submitButton "content-save-outline" "Save" ]
|
||||
]
|
||||
div [ _class "col-12 col-sm-6 col-md-4" ] [
|
||||
continentList [] (nameof m.ContinentId) continents None m.ContinentId true
|
||||
]
|
||||
div [ _class "col-12 col-sm-6 col-md-8" ] [
|
||||
textBox [ _type "text"; _maxlength "255" ] (nameof m.Region) m.Region "Region" true
|
||||
div [ _class "form-text" ] [ txt "Country, state, geographic area, etc." ]
|
||||
]
|
||||
div [ _class "col-12" ] [
|
||||
checkBox [] (nameof m.RemoteWork) m.RemoteWork "This opportunity is for remote work"
|
||||
]
|
||||
markdownEditor [ _required ] (nameof m.Text) m.Text "Job Description" isHtmx
|
||||
div [ _class "col-12 col-md-4" ] [
|
||||
textBox [ _type "date" ] (nameof m.NeededBy) m.NeededBy "Needed By" false
|
||||
]
|
||||
div [ _class "col-12" ] [ submitButton "content-save-outline" "Save" ]
|
||||
]
|
||||
|> List.singleton
|
||||
|> pageWithTitle $"""{if isNew then "Add a" else "Edit"} Job Listing"""
|
||||
|
||||
|
||||
open System.Net
|
||||
|
||||
/// Page to expire a job listing
|
||||
let expire (m : ExpireListingForm) (listing : Listing) isHtmx csrf =
|
||||
pageWithTitle $"Expire Job Listing ({WebUtility.HtmlEncode listing.Title})" [
|
||||
p [ _class "fst-italic" ] [
|
||||
[ p [ _class "fst-italic" ] [
|
||||
txt "Expiring this listing will remove it from search results. You will be able to see it via your "
|
||||
txt "“My Job Listings” page, but you will not be able to “un-expire” it."
|
||||
]
|
||||
|
@ -65,14 +64,14 @@ let expire (m : ExpireListingForm) (listing : Listing) isHtmx csrf =
|
|||
]
|
||||
jsOnLoad "jjj.listing.toggleFromHere()" isHtmx
|
||||
]
|
||||
|> pageWithTitle $"Expire Job Listing ({WebUtility.HtmlEncode listing.Title})"
|
||||
|
||||
|
||||
/// "My Listings" page
|
||||
let mine (listings : ListingForView list) tz =
|
||||
let active = listings |> List.filter (fun it -> not it.Listing.IsExpired)
|
||||
let expired = listings |> List.filter (fun it -> it.Listing.IsExpired)
|
||||
pageWithTitle "My Job Listings" [
|
||||
p [] [ a [ _href "/listing/new/edit"; _class "btn btn-outline-primary" ] [ txt "Add a New Job Listing" ] ]
|
||||
[ p [] [ a [ _href "/listing/new/edit"; _class "btn btn-outline-primary" ] [ txt "Add a New Job Listing" ] ]
|
||||
if not (List.isEmpty expired) then h4 [ _class "pb-2" ] [ txt "Active Job Listings" ]
|
||||
if List.isEmpty active then p [ _class "pb-3 fst-italic" ] [ txt "You have no active job listings" ]
|
||||
else
|
||||
|
@ -117,6 +116,7 @@ let mine (listings : ListingForView list) tz =
|
|||
|> tbody []
|
||||
]
|
||||
]
|
||||
|> pageWithTitle "My Job Listings"
|
||||
|
||||
open NodaTime.Text
|
||||
|
||||
|
@ -125,13 +125,12 @@ let private neededBy dt =
|
|||
(LocalDatePattern.CreateWithCurrentCulture "MMMM d, yyyy").Format dt
|
||||
|
||||
let search (m : ListingSearchForm) continents (listings : ListingForView list option) =
|
||||
pageWithTitle "Help Wanted" [
|
||||
if Option.isNone listings then
|
||||
[ if Option.isNone listings then
|
||||
p [] [
|
||||
txt "Enter relevant criteria to find results, or just click “Search” to see all active job "
|
||||
txt "listings."
|
||||
]
|
||||
collapsePanel "Search Criteria" [
|
||||
collapsePanel "Search Criteria" (List.isEmpty (defaultArg listings [])) [
|
||||
form [ _class "container"; _method "GET"; _action "/help-wanted" ] [
|
||||
input [ _type "hidden"; _name "searched"; _value "true" ]
|
||||
div [ _class "row" ] [
|
||||
|
@ -201,11 +200,12 @@ let search (m : ListingSearchForm) continents (listings : ListingForView list op
|
|||
]
|
||||
| None -> ()
|
||||
]
|
||||
|> pageWithTitle "Help Wanted"
|
||||
|
||||
/// The job listing view page
|
||||
let view (it : ListingForView) =
|
||||
article [] [
|
||||
h3 [] [
|
||||
h3 [ _class "mb-1" ] [
|
||||
str it.Listing.Title
|
||||
if it.Listing.IsExpired then
|
||||
span [ _class "jjj-heading-label" ] [
|
||||
|
@ -214,11 +214,17 @@ let view (it : ListingForView) =
|
|||
txt " "; span [ _class "badge bg-success" ] [ txt "Filled via Jobs, Jobs, Jobs" ]
|
||||
]
|
||||
]
|
||||
h4 [ _class "pb-3 text-muted" ] [ str it.ContinentName; rawText " / "; str it.Listing.Region ]
|
||||
h4 [ _class "mb-3 text-muted" ] [
|
||||
str $"{it.ContinentName} / {it.Listing.Region}"
|
||||
if it.Listing.IsRemote then
|
||||
span [ _class "jjj-heading-label" ] [
|
||||
txt " "; span [ _class "badge text-bg-info" ] [ txt "Remote" ]
|
||||
]
|
||||
]
|
||||
p [] [
|
||||
match it.Listing.NeededBy with
|
||||
| Some needed ->
|
||||
strong [] [ em [] [ txt "NEEDED BY "; str ((neededBy needed).ToUpperInvariant ()) ] ]; txt " • "
|
||||
strong [] [ em [] [ txt "NEEDED BY "; str ((neededBy needed).ToUpperInvariant ()) ] ]; br [] // txt " • "
|
||||
| None -> ()
|
||||
txt "Listed by "; strong [ _class "me-4" ] [ str (Citizen.name it.Citizen) ]; br []
|
||||
span [ _class "ms-3" ] []; yield! contactInfo it.Citizen false
|
||||
|
|
|
@ -354,8 +354,8 @@ let editHistory (history : EmploymentHistory list) idx csrf =
|
|||
// ~~~ PROFILE SEARCH ~~~ //
|
||||
|
||||
/// The search form
|
||||
let private searchForm (m : ProfileSearchForm) continents =
|
||||
collapsePanel "Search Criteria" [
|
||||
let private searchForm (m : ProfileSearchForm) continents isShown =
|
||||
collapsePanel "Search Criteria" isShown [
|
||||
form [ _class "container"; _method "GET"; _action "/profile/search" ] [
|
||||
input [ _type "hidden"; _name "searched"; _value "true" ]
|
||||
div [ _class "row" ] [
|
||||
|
@ -474,7 +474,7 @@ let search m continents tz (results : ProfileForView list option) isPublic =
|
|||
if isPublic then txt "publicly searchable or viewable "
|
||||
txt "profiles."
|
||||
]
|
||||
searchForm m continents
|
||||
searchForm m continents (List.isEmpty (defaultArg results []))
|
||||
match results with
|
||||
| Some r when List.isEmpty r -> p [ _class "pt-3" ] [ txt "No results found for the specified criteria" ]
|
||||
| Some r -> if isPublic then yield! publicResults r else privateResults r tz
|
||||
|
|
Loading…
Reference in New Issue
Block a user