Commit e1a5c262 by Mai Hoang Thai Ha

Merge branch 'top_view/suggest' into 'master'

Top view/suggest

See merge request !21
parents 9f9afa19 eabd44f2
...@@ -65,6 +65,8 @@ gem 'nokogiri', '~> 1.11', '>= 1.11.7' ...@@ -65,6 +65,8 @@ gem 'nokogiri', '~> 1.11', '>= 1.11.7'
gem 'httparty', '~> 0.18.1' gem 'httparty', '~> 0.18.1'
gem 'active_storage_validations', '~> 0.9.5' gem 'active_storage_validations', '~> 0.9.5'
gem 'devise', '~> 4.8' gem 'devise', '~> 4.8'
gem 'jquery-rails', '~> 4.4'
gem 'rsolr', '~> 2.3' gem 'rsolr', '~> 2.3'
gem 'rsolr-ext', '~> 1.0', '>= 1.0.3' gem 'rsolr-ext', '~> 1.0', '>= 1.0.3'
gem 'font-awesome-rails', '~> 4.7', '>= 4.7.0.7'
gem 'bootstrap', '~> 4.4.1'
gem 'jquery-rails', '~> 4.4'
...@@ -82,24 +82,31 @@ GEM ...@@ -82,24 +82,31 @@ GEM
addressable (2.8.0) addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0) public_suffix (>= 2.0.2, < 5.0)
ast (2.4.2) ast (2.4.2)
autoprefixer-rails (10.3.3.0)
execjs (~> 2)
bcrypt (3.1.16) bcrypt (3.1.16)
bindex (0.8.1) bindex (0.8.1)
bootsnap (1.9.1) bootsnap (1.9.1)
msgpack (~> 1.0) msgpack (~> 1.0)
bootstrap (4.4.1)
autoprefixer-rails (>= 9.1.0)
popper_js (>= 1.14.3, < 2)
sassc-rails (>= 2.0.0)
builder (3.2.4) builder (3.2.4)
bullet (6.1.5) bullet (6.1.5)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
uniform_notifier (~> 1.11) uniform_notifier (~> 1.11)
byebug (11.1.3) byebug (11.1.3)
capybara (3.35.3) capybara (3.36.0)
addressable addressable
matrix
mini_mime (>= 0.1.3) mini_mime (>= 0.1.3)
nokogiri (~> 1.8) nokogiri (~> 1.8)
rack (>= 1.6.0) rack (>= 1.6.0)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0) regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2) xpath (~> 3.2)
childprocess (3.0.0) childprocess (4.1.0)
coderay (1.1.3) coderay (1.1.3)
concurrent-ruby (1.1.9) concurrent-ruby (1.1.9)
crass (1.0.6) crass (1.0.6)
...@@ -110,6 +117,7 @@ GEM ...@@ -110,6 +117,7 @@ GEM
responders responders
warden (~> 1.2.3) warden (~> 1.2.3)
erubi (1.10.0) erubi (1.10.0)
execjs (2.8.1)
faraday (1.8.0) faraday (1.8.0)
faraday-em_http (~> 1.0) faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0) faraday-em_synchrony (~> 1.0)
...@@ -130,12 +138,14 @@ GEM ...@@ -130,12 +138,14 @@ GEM
faraday-patron (1.0.0) faraday-patron (1.0.0)
faraday-rack (1.0.0) faraday-rack (1.0.0)
ffi (1.15.4) ffi (1.15.4)
font-awesome-rails (4.7.0.7)
railties (>= 3.2, < 7)
globalid (0.5.2) globalid (0.5.2)
activesupport (>= 5.0) activesupport (>= 5.0)
httparty (0.18.1) httparty (0.18.1)
mime-types (~> 3.0) mime-types (~> 3.0)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
i18n (1.8.10) i18n (1.8.11)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
jbuilder (2.11.2) jbuilder (2.11.2)
activesupport (>= 5.0.0) activesupport (>= 5.0.0)
...@@ -152,11 +162,12 @@ GEM ...@@ -152,11 +162,12 @@ GEM
mail (2.7.1) mail (2.7.1)
mini_mime (>= 0.1.1) mini_mime (>= 0.1.1)
marcel (1.0.2) marcel (1.0.2)
matrix (0.4.2)
method_source (1.0.0) method_source (1.0.0)
mime-types (3.3.1) mime-types (3.3.1)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2021.0901) mime-types-data (3.2021.0901)
mini_mime (1.1.1) mini_mime (1.1.2)
minitest (5.14.4) minitest (5.14.4)
msgpack (1.4.2) msgpack (1.4.2)
multi_xml (0.6.0) multi_xml (0.6.0)
...@@ -169,15 +180,16 @@ GEM ...@@ -169,15 +180,16 @@ GEM
parallel (1.21.0) parallel (1.21.0)
parser (3.0.2.0) parser (3.0.2.0)
ast (~> 2.4.1) ast (~> 2.4.1)
popper_js (1.16.0)
pry (0.14.1) pry (0.14.1)
coderay (~> 1.1) coderay (~> 1.1)
method_source (~> 1.0) method_source (~> 1.0)
pry-rails (0.3.9) pry-rails (0.3.9)
pry (>= 0.10.4) pry (>= 0.10.4)
public_suffix (4.0.6) public_suffix (4.0.6)
puma (5.5.0) puma (5.5.2)
nio4r (~> 2.0) nio4r (~> 2.0)
racc (1.5.2) racc (1.6.0)
rack (2.2.3) rack (2.2.3)
rack-mini-profiler (2.3.3) rack-mini-profiler (2.3.3)
rack (>= 1.2.0) rack (>= 1.2.0)
...@@ -226,7 +238,7 @@ GEM ...@@ -226,7 +238,7 @@ GEM
faraday (>= 0.9.0) faraday (>= 0.9.0)
rsolr-ext (1.0.3) rsolr-ext (1.0.3)
rsolr (>= 1.0.2) rsolr (>= 1.0.2)
rubocop (1.22.0) rubocop (1.22.3)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 3.0.0.0) parser (>= 3.0.0.0)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
...@@ -235,9 +247,9 @@ GEM ...@@ -235,9 +247,9 @@ GEM
rubocop-ast (>= 1.12.0, < 2.0) rubocop-ast (>= 1.12.0, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0) unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.12.0) rubocop-ast (1.13.0)
parser (>= 3.0.1.1) parser (>= 3.0.1.1)
rubocop-rails (2.12.2) rubocop-rails (2.12.4)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
rack (>= 1.1) rack (>= 1.1)
rubocop (>= 1.7.0, < 2.0) rubocop (>= 1.7.0, < 2.0)
...@@ -254,8 +266,9 @@ GEM ...@@ -254,8 +266,9 @@ GEM
sprockets (> 3.0) sprockets (> 3.0)
sprockets-rails sprockets-rails
tilt tilt
selenium-webdriver (3.142.7) selenium-webdriver (4.0.3)
childprocess (>= 0.5, < 4.0) childprocess (>= 0.5, < 5.0)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2) rubyzip (>= 1.2.2)
semantic_range (3.0.0) semantic_range (3.0.0)
slim (4.1.0) slim (4.1.0)
...@@ -290,10 +303,10 @@ GEM ...@@ -290,10 +303,10 @@ GEM
activemodel (>= 6.0.0) activemodel (>= 6.0.0)
bindex (>= 0.4.0) bindex (>= 0.4.0)
railties (>= 6.0.0) railties (>= 6.0.0)
webdrivers (4.6.1) webdrivers (5.0.0)
nokogiri (~> 1.6) nokogiri (~> 1.6)
rubyzip (>= 1.3.0) rubyzip (>= 1.3.0)
selenium-webdriver (>= 3.0, < 4.0) selenium-webdriver (~> 4.0)
webpacker (5.4.3) webpacker (5.4.3)
activesupport (>= 5.2) activesupport (>= 5.2)
rack-proxy (>= 0.6.1) rack-proxy (>= 0.6.1)
...@@ -304,7 +317,7 @@ GEM ...@@ -304,7 +317,7 @@ GEM
websocket-extensions (0.1.5) websocket-extensions (0.1.5)
xpath (3.2.0) xpath (3.2.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
zeitwerk (2.4.2) zeitwerk (2.5.1)
PLATFORMS PLATFORMS
x86_64-linux x86_64-linux
...@@ -312,10 +325,12 @@ PLATFORMS ...@@ -312,10 +325,12 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
active_storage_validations (~> 0.9.5) active_storage_validations (~> 0.9.5)
bootsnap (>= 1.4.4) bootsnap (>= 1.4.4)
bootstrap (~> 4.4.1)
bullet (~> 6.1, >= 6.1.4) bullet (~> 6.1, >= 6.1.4)
byebug byebug
capybara (>= 3.26) capybara (>= 3.26)
devise (~> 4.8) devise (~> 4.8)
font-awesome-rails (~> 4.7, >= 4.7.0.7)
httparty (~> 0.18.1) httparty (~> 0.18.1)
jbuilder (~> 2.7) jbuilder (~> 2.7)
jquery-rails (~> 4.4) jquery-rails (~> 4.4)
......
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require_tree .
*= require_self
*/
@import "bootstrap";
@import "font-awesome";
@import "./scss/style.scss";
.ribbon {
text-align: center;
ul {
list-style: none;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
margin: 0;
padding: 0;
.item {
display: block;
float: left;
width: 30%;
height: 100%;
background: #f3f5fa;
text-align: center;
padding: 8px;
position: relative;
font-size: 16px;
font-weight: 700;
text-decoration: none;
color: #808080;
.circle {
display: inline-flex;
-ms-flex-line-pack: center;
align-content: center;
-ms-flex-pack: center;
justify-content: center;
width: 1.6em;
height: 1.6em;
padding: 0.25em 0;
margin-right: 10px;
line-height: 1em;
font-size: 1em;
color: #808080;
background-color: #e0e0e0;
border-radius: 50%;
}
&:after {
content: "";
border-top: 21px solid transparent;
border-bottom: 21px solid transparent;
border-left: 21px solid #f3f5fa;
position: absolute;
right: -21px;
top: 0;
z-index: 1;
}
&:last-child::after {
display: none;
}
&:first-child::before {
content: "";
border-top: 21px solid transparent;
border-bottom: 21px solid transparent;
border-left: 21px solid #fff;
position: absolute;
left: 0;
top: 0;
}
}
.active {
background: #0d6efd;
color: #fff;
.circle {
color: #0d6efd;
background-color: #fff;
}
&::after {
border-left-color: #0d6efd;
color: #fff;
}
}
}
}
.btn-height {
height: 50px;
}
.invalid {
.form-msg {
color: #f33a58;
}
input {
border-color: #f33a58;
}
}
.logout {
border: none;
padding: 0;
background-color: white;
outline: none;
}
.flash {
position: absolute;
top: 0;
right: 0;
left: 0;
z-index: 1000;
background-color: white;
}
.hide {
display: none;
}
.alert-notice {
color: #155724;
background-color: #d4edda;
border-color: #c3e6cb;
}
\ No newline at end of file
// Place all the styles related to the Favorite_industries controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: https://sass-lang.com/
/* About Content */
.about-content {
& .title {
margin-bottom: 20px;
}
& p {
margin-bottom: 20px;
}
& ul {
padding-left: 15px;
}
}
/* About Image */
.about-image {
height: 100%;
& img {
height: 100%;
object-fit: cover;
object-position: center;
}
}
\ No newline at end of file
/*----
/* 02.1 Accordion Elements CSS
/*----------------------------------------*/
.accordion {
& .card {
& .card-header {
background-color: transparent;
& .btn {
padding: 0;
color: $heading-color;
&:hover {
text-decoration: none;
color: $primary;
}
}
}
& .card-body {
}
}
}
\ No newline at end of file
/* App Content */
.app-content {
margin-bottom: 30px;
& .title {
margin-bottom: 15px;
}
& .lead {
max-width: 490px;
margin-bottom: 30px;
}
@media #{$tablet-device} {
& .title {
font-size: 32px;
}
}
}
/* App Image */
.app-image {
}
\ No newline at end of file
/*----
/* 02.2 Blockquote Elements CSS
/*----------------------------------------*/
.blockquote {
margin-top: 20px;
padding: 20px 30px;
border: 1px solid #EDEDED;
& p {
font-family: $special-font;
font-style: italic;
color: $heading-color;
}
}
.blockquote-footer {
font-size: 14px;
margin-top: 5px;
color: $primary;
}
\ No newline at end of file
/* Blog Wrapper */
.blog-wrap {
margin-bottom: -30px;
& > [class*="col"] {
margin-bottom: 30px;
}
}
/* Blog */
.blog {
& .media {
margin-bottom: 25px;
& a {
display: block;
width: 100%;
}
& img {
width: 100%;
}
}
& .content {
& .title {
font-size: 19px;
margin-bottom: 15px;
& a {
}
}
& .meta {
font-size: 13px;
display: flex;
flex-wrap: wrap;
margin-bottom: 10px;
padding: 0;
list-style: none;
& li {
margin-top: 0;
margin-right: 10px;
&:last-child {
margin-right: 0;
}
&:not(:last-child)::after {
margin-left: 10px;
content: "-";
}
& a {
}
}
}
& .desc {
margin-bottom: 20px;
& p {
}
}
& .read-more {
font-weight: 600;
color: $heading-color;
& i {
margin-left: 5px;
}
&:hover {
color: $primary;
}
}
& .blog-tags {
display: flex;
flex-wrap: wrap;
& ul {
display: flex;
flex-wrap: wrap;
margin: 0;
padding-left: 0;
list-style: none;
& li {
margin-top: 0;
margin-right: 5px;
&::after {
content: ",";
}
&:first-child {
margin-right: 10px;
&::after {
display: none;
}
}
&:last-child {
margin-right: 0;
}
& a {
}
}
}
}
& .blog-share {
display: flex;
flex-wrap: wrap;
& ul {
display: flex;
align-items: center;
flex-wrap: wrap;
margin: 0;
padding-left: 0;
list-style: none;
& li {
margin-top: 0;
margin-right: 5px;
&:first-child {
margin-right: 10px;
}
&:last-child {
margin-right: 0;
}
& a {
width: 30px;
height: 30px;
text-align: center;
border-radius: 50%;
background-color: rgba($black, 0.075);
& i {
line-height: 32px;
}
&:hover {
color: $white;
background-color: $primary;
}
}
}
}
}
}
// Blog Single
&.blog-single {
& .content {
& .title {
font-size: 23px;
}
& .desc {
margin-bottom: 30px;
}
}
}
}
/* Blog Navigation */
.blog-navigation {
padding: 20px 0;
list-style: none;
border-top: 1px solid #EDEDED;
border-bottom: 1px solid #EDEDED;
& li {
margin: 0;
& a {
position: relative;
&:hover {
color: $primary;
&::before {
color: $primary;
}
}
&::before {
font-family: $fontawesome;
font-size: 30px;
line-height: 24px;
position: absolute;
top: 0;
color: $body-light;
}
&.prev-blog {
margin-left: -15px;
padding-left: 30px;
text-align: left;
&::before {
left: 0;
content: "\f104";
}
}
&.next-blog {
margin-right: -15px;
padding-right: 30px;
text-align: right;
&::before {
right: 0;
content: "\f105";
}
}
}
}
}
\ No newline at end of file
/*----
/* 02.3 Button Elements CSS
/*----------------------------------------*/
.btn {
line-height: 24px;
padding: 10px 30px;
border-radius: 0;
}
.btn-lg {
padding: 20px 35px;
}
\ No newline at end of file
/* Comment List */
.comment-list {
margin: 0;
padding-left: 0;
list-style: none;
& > li {
margin: 0;
&:last-child {
& .comment {
&:last-child {
margin-bottom: 0;
}
}
}
}
}
/* Child Comment */
.child-comment {
margin: 0;
padding-left: 40px;
list-style: none;
& > li {
margin: 0;
}
@media #{$extra-small-mobile} {
padding-left: 0;
}
}
/* Comment */
.comment {
display: flex;
flex-wrap: wrap;
margin-bottom: 30px;
& .image {
width: 80px;
& img {
}
}
& .content {
max-width: calc(100% - 80px);
padding-left: 30px;
& .head {
display: flex;
align-items: center;
flex-wrap: wrap;
margin-bottom: 5px;
& .name {
font-size: 16px;
margin-right: 10px;
margin-bottom: 0;
}
& .date {
line-height: 1;
display: block;
color: $body-light;
&::before {
margin-right: 10px;
content: "-";
}
}
}
& p {
margin-bottom: 5px;
}
& .reply {
line-height: 1;
text-transform: capitalize;
color: $primary;
&:hover {
text-decoration: underline;
}
}
}
@media #{$extra-small-mobile} {
& .content {
max-width: 100%;
padding-top: 15px;
padding-left: 0;
}
}
}
\ No newline at end of file
/* Company Slider */
.company-slider {
}
/* Feature Company */
.feature-company {
display: block;
text-align: center;
& .company-logo {
display: inline-block;
margin-bottom: 10px;
}
& .title {
font-size: 19px;
transition: all 0.3s ease 0s;
}
& .open-job {
display: block;
color: $body-color;
}
&:hover {
& .title {
color: $primary;
}
}
}
/* Company List Wrapper */
.company-list-wrap {
margin-bottom: -30px;
& > div,
& > [class*="col"] {
margin-bottom: 30px;
}
}
/* Company List */
.company-list {
display: block;
padding: 30px;
text-align: center;
border: 1px solid #EDEDED;
& .company-logo {
display: inline-block;
margin-bottom: 10px;
}
& .title {
font-size: 19px;
transition: all 0.3s ease 0s;
}
& .open-job {
display: block;
margin-bottom: 6px;
color: $body-color;
}
& .location {
font-size: 13px;
color: $body-color;
& i {
margin-right: 10px;
}
}
&:hover {
z-index: 9;
border-color: transparent;
box-shadow: 0 0 30px rgba($black, 0.15);
& .title {
color: $primary;
}
}
}
\ No newline at end of file
/* Contact Map */
.contact-map {
padding-bottom: 40%;
@media #{$extra-small-mobile} {
padding-bottom: 60%;
}
}
/* Google Map */
.google-map {
background-color: #EDEDED;
}
/* Contact Information */
.contact-information {
& ul {
padding-left: 0;
list-style: none;
& li {
& + li {
margin-bottom: 10px;
}
& i {
margin-right: 15px;
}
}
}
}
/* Contact Social */
.contact-social {
display: flex;
flex-wrap: 0;
margin: -5px;
& a {
width: 36px;
height: 36px;
margin: 5px;
text-align: center;
border-radius: 50%;
background-color: rgba($black, 0.075);
& i {
line-height: 36px;
}
&:hover {
color: $white;
background-color: $primary;
}
}
}
\ No newline at end of file
/* Faq Card */
.faq-card {
margin-bottom: 30px;
border: none;
&:last-child {
margin-bottom: 0;
}
& .card-header {
padding: 0;
border: none;
background-color: transparent;
}
& .card-body {
padding: 0 0 0 28px;
}
}
\ No newline at end of file
/* Footer Top Section */
.footer-top-section {
padding: 80px 0;
background-color: #333333;
}
/* Footer Widget Wrapper */
.footer-widget-wrap {
margin-bottom: -30px;
}
/* Footer Widget */
.footer-widget {
margin-bottom: 30px;
color: lighten($body-color, 25);
& .title {
font-size: 19px;
line-height: 1;
margin-bottom: 20px;
color: $white;
}
}
/* Footer About */
.footer-widget-about {
& img {
margin-bottom: 20px;
}
& p {
max-width: 250px;
&:not(:last-child) {
margin-bottom: 20px;
}
}
}
/* Footer Social */
.footer-socail {
display: flex;
flex-wrap: wrap;
margin: 0 -5px -5px;
padding-left: 0;
list-style: none;
& li {
margin: 0 5px 5px;
& a {
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
color: $white;
border-radius: 50%;
background-color: rgba($white, 0.1);
&:hover {
background-color: $primary;
}
& i {
}
}
}
}
/* Footer Link */
.footer-widget-link {
& ul {
margin: 0;
padding-left: 0;
list-style: none;
& li {
& + li {
margin-top: 6px;
}
& a {
}
}
}
}
/* Footer Newsletter */
.footer-widget-newsletter {
& p {
margin-bottom: 20px;
}
& form {
position: relative;
& input {
font-size: 13px;
padding-right: 44px;
color: $white;
border: none;
background-color: rgba($white, 0.1);
}
& button {
position: absolute;
top: 0;
right: 0;
width: 44px;
padding: 10px;
color: $white;
border: none;
&:hover {
color: $white;
background-color: $primary;
}
}
}
}
/* Footer Bottom Section */
.footer-bottom-section {
padding: 20px 0;
background-color: $black;
}
/* Footer Copyright */
.footer-copyright {
color: lighten($body-color, 25);
& a {
color: $primary;
&:hover {
text-decoration: underline;
}
}
}
\ No newline at end of file
/*----
/* 02.4 Form Elements CSS
/*----------------------------------------*/
label {
font-size: 13px;
line-height: 1.25;
display: block;
margin-bottom: 10px;
}
input[type="text"],
input[type="search"],
input[type="email"],
input[type="password"],
textarea,
.form-control {
line-height: 24px;
display: block;
width: 100%;
padding: 10px 20px;
color: $body-color;
border: 1px solid #EDEDED;
border-radius: 0;
background-color: $white;
}
select {
line-height: 24px;
display: block;
width: 100%;
padding: 10px 15px;
padding-right: 40px;
color: $body-color;
border: 1px solid #EDEDED;
border-radius: 0;
background-color: $white;
// background-image: url("../images/icons/arrow-down.png");
background-repeat: no-repeat;
background-position: right center;
background-size: auto;
appearance: none;
}
// Custom Control Label
.custom-control-label {
font-size: inherit;
line-height: 1.65;
}
// Range Slider
.range-slider {
&.irs-hidden-input {
position: absolute;
top: 0;
left: 0;
display: block;
visibility: hidden;
width: 0;
height: 0;
opacity: 0;
}
}
// Ion Range Slider
.irs {
position: relative;
display: block;
width: 100%;
& .irs {
position: relative;
display: block;
padding-top: 30px;
& .irs-line {
display: block;
width: 100%;
height: 6px;
background-color: #F2F2F2;
}
& .irs-min {
display: none;
}
& .irs-max {
display: none;
}
& .irs-from {
position: absolute;
top: 0;
visibility: visible !important;
white-space: nowrap;
}
& .irs-to {
position: absolute;
top: 0;
visibility: visible !important;
white-space: nowrap;
}
& .irs-single {
display: none;
}
}
& .irs-grid {
display: none;
}
& .irs-bar {
position: absolute;
bottom: 0;
height: 6px;
background-color: $primary;
}
& .irs-handle {
position: absolute;
bottom: -7px;
display: block;
width: 20px;
height: 20px;
border-radius: 50px;
background-color: $primary;
box-shadow: 0 0 15px rgba($black, 0.3);
& i {
display: none;
}
&.from {
}
&.to {
}
}
}
\ No newline at end of file
/* Funfact Wrapper */
.funfact-wrap {
margin-bottom: -30px;
}
/* Funfact */
.funfact {
margin-bottom: 30px;
text-align: center;
color: $white;
& span {
line-height: 1;
display: block;
}
& .counter {
font-size: 50px;
margin-bottom: 10px;
}
& .title {
font-size: 23px;
line-height: 1.25;
}
// Responsive
@media #{$large-mobile} {
& .title {
font-size: 19px;
}
}
}
\ No newline at end of file
/* Job Category Slider */
.job-category-slider {
& .slick-list {
padding-top: 15px;
padding-bottom: 15px;
}
}
/* Job Category */
.job-category {
display: flex;
align-items: center;
justify-content: center;
height: 190px;
transition: all 0.3s ease 0s;
text-align: center;
& .inner {
& i {
font-size: 50px;
line-height: 1;
display: block;
}
& .title {
font-size: 14px;
font-weight: 600;
margin-top: 20px;
margin-bottom: 0;
text-transform: uppercase;
color: inherit;
}
}
}
\ No newline at end of file
/* Job Search Section */
.job-search-section {
position: relative;
z-index: 90;
}
/* Job Search Wrapper */
.job-search-wrap {
position: relative;
margin-top: -83px;
padding: 60px;
background-color: $white;
box-shadow: 0 0 30px rgba($black, 0.15);
// Responsive
@media #{$extra-small-mobile} {
padding: 30px;
}
}
/* Job Search Form */
.job-search-form {
& .btn {
display: block;
width: 100%;
}
}
/* Job Search Form 2 */
.job-search-form-2 {
& input[type="text"] {
padding: 15px 20px;
}
& select {
padding: 15px;
padding-right: 40px;
}
& .btn {
display: block;
width: 100%;
padding: 15px 20px;
}
}
\ No newline at end of file
.job-list-details {
& .job-details-head {
position: relative;
z-index: 1;
align-items: center;
margin-bottom: 30px;
padding-bottom: 25px;
border-bottom: 1px solid #EDEDED;
& .company-logo {
}
& .salary-type {
text-align: right;
& .salary-range {
font-weight: 600;
line-height: 1;
display: block;
margin-bottom: 8px;
color: lighten($body-color, 15);
}
& .badge {
font-size: 13px;
font-weight: 400;
padding: 4px 10px 5px;
border-radius: 0;
}
}
& .content {
& .title {
}
& .meta {
display: flex;
flex-wrap: wrap;
margin-bottom: 0;
padding-left: 0;
list-style: none;
color: lighten($body-color, 15);
& li {
margin-top: 0;
margin-right: 20px;
&:last-child {
margin-right: 0;
}
& i {
font-size: 16px;
margin-right: 3px;
}
}
}
}
// Responsive
@media #{$small-mobile} {
& .salary-type {
margin-left: auto;
}
& .content {
flex: 1 0 100%;
margin-top: 10px;
}
}
@media #{$extra-small-mobile} {
padding: 20px 5px;
}
}
& .job-details-body {
& ul {
padding-left: 25px;
}
}
}
\ No newline at end of file
/* Job List Toolbar */
.job-list-toolbar {
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: space-between;
margin: -10px -10px 20px;
& p {
display: flex;
align-items: center;
margin: 0;
padding: 10px;
white-space: nowrap;
& select {
margin-left: 10px;
}
}
}
/* Job List Wrapper */
.job-list-wrap {
padding: 1px;
}
/* Job List */
.job-list {
position: relative;
z-index: 1;
display: flex;
align-items: center;
flex-wrap: wrap;
margin: -1px;
padding: 23px 15px;
border-width: 1px;
border-style: solid;
border-color: #EDEDED transparent;
&:hover {
z-index: 9;
border-color: transparent;
box-shadow: 0 0 30px rgba($black, 0.15);
}
& .company-logo {
}
& .salary-type {
text-align: right;
& .salary-range {
font-weight: 600;
line-height: 1;
display: block;
margin-bottom: 8px;
color: lighten($body-color, 15);
}
& .badge {
font-size: 13px;
font-weight: 400;
padding: 4px 10px 5px;
border-radius: 0;
}
}
& .content {
& .title {
}
& .meta {
display: flex;
flex-wrap: wrap;
margin-bottom: 0;
padding-left: 0;
list-style: none;
color: lighten($body-color, 15);
& li {
margin-top: 0;
margin-right: 20px;
&:last-child {
margin-right: 0;
}
& i {
font-size: 16px;
margin-right: 3px;
}
}
}
}
// Responsive
@media #{$small-mobile} {
& .salary-type {
margin-left: auto;
& .badge {
font-size: 10px;
}
}
& .content {
flex: 1 0 100%;
margin-top: 10px;
}
}
@media #{$extra-small-mobile} {
padding: 20px 5px;
}
}
\ No newline at end of file
/* Login & Signup Tab Nav */
.loginSignupNav {
display: flex;
overflow: hidden;
flex: 1 0 100%;
flex-wrap: wrap;
margin: -20px -30px -21px;
text-align: center;
border-top-left-radius: 0.3rem;
border-top-right-radius: 0.3rem;
& li {
flex-grow: 1;
margin: 0;
& .nav-link {
padding: 15px 30px;
&.active {
color: $white;
background-color: $primary;
}
}
}
}
/* Login & Signup With Social */
.login-reg-social {
display: flex;
flex-wrap: wrap;
justify-content: center;
margin: 0 -5px -10px;
& a {
display: inline-block;
width: 40px;
height: 40px;
margin: 0 5px 10px;
text-align: center;
border-radius: 50%;
background-color: #EDEDED;
& i {
line-height: 40px;
}
&:hover {
color: $white;
background-color: $primary;
}
}
}
\ No newline at end of file
/*----
/* 02.5 Button Elements CSS
/*----------------------------------------*/
.modal {
}
.modal-dialog {
}
.modal-content {
}
.modal-header {
position: relative;
padding: 20px 30px;
border-color: #EDEDED;
& .close {
font-weight: 300;
position: absolute;
top: -20px;
right: -20px;
width: 40px;
height: 40px;
margin: 0;
padding: 0 0 3px;
opacity: 1;
border-radius: 50%;
background-color: $white;
box-shadow: 0 0 30px rgba($black, 0.15);
&:hover {
opacity: 1 !important;
color: $white;
background-color: $primary;
}
}
}
.modal-body {
padding: 30px;
}
\ No newline at end of file
/* Page Heading Section */
.page-heading-section {
padding: 200px 0 100px;
@media #{$large-mobile} {
padding: 130px 0 50px;
}
}
/* Page Heading Content */
.page-heading-content {
& .title {
color: $white;
}
& .breadcrumb {
justify-content: center;
margin: 0;
padding: 0;
color: $white;
background-color: transparent;
& .breadcrumb-item {
&::before {
color: $white;
}
&.active {
text-decoration: underline;
color: $white;
}
}
}
}
\ No newline at end of file
/*----
/* 02.6 Button Elements CSS
/*----------------------------------------*/
.pagination {
margin: 0 0 -10px;
& .page-item {
margin: 0 5px 10px;
& .page-link {
font-size: 14px;
line-height: 25px;
width: 35px;
height: 35px;
padding: 5px;
text-align: center;
color: $body-color;
border: none;
border-radius: 0;
&:hover {
color: $white;
background-color: $primary;
}
}
&.active {
& .page-link {
color: $white;
background-color: $primary;
}
}
}
&.pagination-center {
justify-content: center;
}
}
\ No newline at end of file
/* Pricing Wrapper */
.pricing-wrap {
margin-bottom: -30px;
}
/* Pricing */
.pricing {
margin-bottom: 30px;
& .inner {
padding: 40px;
border: 1px solid #EDEDED;
background-color: $white;
& .head {
margin-bottom: 40px;
& .title {
font-weight: 600;
line-height: 1;
display: block;
margin-bottom: 20px;
text-transform: uppercase;
}
& .price {
font-size: 50px;
line-height: 1;
margin-bottom: 5px;
& sup {
font-size: 20px;
margin-right: 3px;
vertical-align: super;
&:last-child {
margin-right: 0;
vertical-align: sub;
}
}
}
& .duration {
line-height: 1;
display: block;
}
}
& .body {
margin-bottom: 40px;
& ul {
font-size: 16px;
margin-bottom: 0;
padding-left: 0;
list-style: none;
& li {
& + li {
margin-top: 5px;
}
}
}
}
& .foot {
& .btn {
padding: 10px 30px;
color: $white;
background-color: $dark;
&:hover {
background-color: $primary;
}
}
}
}
}
\ No newline at end of file
/* Sidebar Wrapper */
.sidebar-wrap {
margin-bottom: -35px;
}
/* Sidebar Widget */
.sidebar-widget {
margin-bottom: 35px;
& > .inner {
padding: 25px;
border: 1px solid #EDEDED;
& > .title {
font-size: 19px;
line-height: 1;
margin-bottom: 20px;
}
}
}
/* Sidebar Job Location Map */
.job-location-map {
width: 100%;
max-height: 300px;
padding-top: 100%;
}
/* Sidebar Banner */
.banner {
display: block;
border: 1px solid #EDEDED;
& img {
width: 100%;
}
}
/* Sidebar Company */
.sidebar-company {
display: block;
& .company-logo {
display: inline-block;
margin-bottom: 10px;
}
& .title {
font-size: 19px;
transition: all 0.3s ease 0s;
}
& ul {
margin: 0;
padding-left: 0;
list-style: none;
& li {
& strong {
margin-right: 6px;
color: $heading-color;
}
}
}
}
/* Sidebar Company Location Map */
.company-location-map {
width: 100%;
max-height: 250px;
padding-top: 100%;
}
/* Sidebar List */
.sidebar-list {
margin: 0;
padding: 0;
list-style: none;
& li {
line-height: 1.5;
& + li {
margin-top: 10px;
}
& a {
display: inline;
}
}
// Sidebar List Comment
&.sidebar-list-comment {
& li {
color: $body-light;
& + li {
margin-top: 15px;
}
& a {
color: $heading-color;
&:hover {
color: $primary;
}
}
}
}
}
/* Sidebar Post */
.sidebar-post {
margin: 0;
padding: 0;
list-style: none;
& li {
line-height: 1.5;
display: flex;
flex-wrap: wrap;
& + li {
margin-top: 15px;
}
& .image {
max-width: 70px;
margin-right: 15px;
}
& .title {
max-width: calc(100% - 85px);
}
}
}
\ No newline at end of file
.slide-item {
position: relative;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
height: 750px;
// Responsive
@media #{$desktop-device,
$tablet-device
} {
height: 650px;
}
@media #{$large-mobile} {
height: 450px;
}
@media #{$extra-small-mobile} {
height: 400px;
}
}
.slider-content {
& .title {
font-size: 96px;
font-weight: 700;
color: $white;
}
& p {
font-size: 28px;
margin: 0;
color: $white;
}
// Responsive
@media #{$desktop-device} {
& .title {
font-size: 86px;
}
}
@media #{$tablet-device} {
& .title {
font-size: 60px;
}
}
@media #{$large-mobile} {
& .title {
font-size: 50px;
}
& p {
font-size: 23px;
}
}
@media #{$small-mobile} {
& .title {
font-size: 40px;
}
& p {
font-size: 18px;
}
}
@media #{$extra-small-mobile} {
& .title {
font-size: 24px;
}
& p {
font-size: 14px;
}
}
}
.slide-item-2 {
position: relative;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
height: 750px;
// Responsive
@media #{$desktop-device,
$tablet-device
} {
height: 650px;
}
@media #{$large-mobile} {
height: 600px;
padding-top: 70px;
padding-bottom: 40px;
}
}
.slider-content-2 {
&:not(:last-child) {
margin-bottom: 30px;
}
& .title {
font-size: 50px;
font-weight: 700;
color: $white;
}
& p {
font-size: 18px;
margin: 0;
color: $white;
}
// Responsive
@media #{$small-mobile} {
& .title {
font-size: 40px;
}
}
@media #{$extra-small-mobile} {
& .title {
font-size: 24px;
}
& p {
font-size: 14px;
}
}
}
\ No newline at end of file
/* Team Wrapper */
.team-wrap {
margin-bottom: -30px;
& [class*="col"] {
margin-bottom: 30px;
}
}
/* Team */
.team {
position: relative;
overflow: hidden;
& img {
width: 100%;
}
& .content {
position: absolute;
z-index: 9;
top: 0;
left: 0;
display: flex;
align-items: flex-end;
flex-wrap: wrap;
width: 100%;
height: 100%;
transition: all 0.3s ease 0s;
transform: scale(1.25);
transform-origin: left bottom;
opacity: 0;
background-color: rgba($black, 0.7);
& .inner {
padding: 25px;
color: $white;
& .name {
font-size: 19px;
margin-bottom: 6px;
color: inherit;
}
& .title {
font-size: 13px;
line-height: 1;
display: block;
margin-bottom: 20px;
}
& .social {
display: flex;
flex-wrap: 0;
margin: -5px;
& a {
width: 30px;
height: 30px;
margin: 5px;
text-align: center;
border-radius: 50%;
background-color: rgba($white, 0.15);
& i {
line-height: 30px;
}
&:hover {
color: $white;
background-color: $primary;
}
}
}
}
}
&:hover {
& img {
transform: scale(1.15) rotate(5deg);
}
& .content {
transform: scale(1);
opacity: 1;
}
}
}
\ No newline at end of file
/* Testimonial Slider */
.testimonial-slider {
& .slick-arrow {
color: $white;
background-color: transparent;
&:hover {
background-color: $primary;
}
}
}
/* Testimonial */
.testimonial {
& p {
font-family: $special-font;
font-size: 24px;
max-width: 650px;
margin-right: auto;
margin-bottom: 30px;
margin-left: auto;
}
& img {
width: 70px;
margin-right: auto;
margin-bottom: 15px;
margin-left: auto;
border: 3px solid $grey;
border-radius: 50%;
}
& .name {
font-weight: 700;
color: inherit;
}
& .title {
font-size: 14px;
line-height: 1;
display: block;
}
}
\ No newline at end of file
// Font Family
$body-font: "Open Sans",
sans-serif;
$heading-font: "Montserrat",
sans-serif;
$special-font: "Playfair Display",
serif;
$fontawesome: "FontAwesome";
// Colors ---------------
$white: #FFFFFF;
$black: #000000;
$grey: #F8F9FD;
// Body Color
$body-color: #454545;
$body-light: #999999;
// Heading Color
$heading-color: #333333;
// Template Colors
$primary: #007BFF;
$secondary: #6C757D;
$success: #4CAF50;
$danger: #F44336;
$warning: #FFC107;
$info: #17A2B8;
$light: #F8F9FA;
$dark: #343A40;
$templateColor: ("primary": $primary,
"secondary": $secondary,
"success": $success,
"danger": $danger,
"warning": $warning,
"info": $info,
"light": $light,
"dark": $dark,
);
// Socail Color
$android: #7AC157;
$apple: #B8B8B8;
$behance: #1869FF;
$codepen: $black;
$dribbble: #EA4C8A;
$dropbox: #007EE5;
$evernote: #78D525;
$facebook: #4867AA;
$github: #313131;
$google-drive: #1DA462;
$google-earth: #4285F4;
$google-glass: #EA4335;
$google-maps: #5083C3;
$google-play: #01B9FD;
$google-plus: #DD5144;
$google: #4285F4;
$instagram: #B23A94;
$css3: #0277BD;
$html5: #E44D26;
$javascript: #F9DC3D;
$python: #0C9DBF;
$lastfm: #E31B23;
$linkedin: #007BB6;
$paypal: #002F86;
$pinterest: #BD081B;
$pocket: #EF3E56;
$polymer: #F87292;
$rss: #F99C3A;
$share: #2C9CFF;
$stackoverflow: #F38024;
$steam: #15497B;
$twitter: #1DA1F2;
$vk: #5181B8;
$wikipedia: #E9E9E9;
$windows: #0078D6;
$s500px: $black;
$s8tracks: #122D4B;
$amazon: #F79B34;
$blogger: #F06A35;
$delicious: #0000FE;
$disqus: #2E9EFE;
$flattr: #7AB831;
$flickr: #FE0084;
$odnoklassniki: #F58220;
$outlook: #0072C6;
$playstation: #07418E;
$reddit: #FF4500;
$skype: #00A9F0;
$slideshare: #0077B5;
$soundcloud: #FE4900;
$tumblr: #36465D;
$twitch: #6441A4;
$vimeo: #1AB7EA;
$whatsapp: #189D0E;
$xbox: #107C0F;
$yahoo: #4101AF;
$youtube: #FE0000;
// Responsive Variables
$extraBig-device: "only screen and (min-width: 1500px)";
$laptop-device: "only screen and (min-width: 1200px) and (max-width: 1499px)";
$desktop-device: "only screen and (min-width: 992px) and (max-width: 1199px)";
$tablet-device: "only screen and (min-width: 768px) and (max-width: 991px)";
$large-mobile: "only screen and (max-width: 767px)";
$small-mobile: "only screen and (max-width: 575px)";
$extra-small-mobile: "only screen and (max-width: 479px)";
\ No newline at end of file
/*-----------------------------------------------------------------------------------
Template Name: Edwards - Lawyers Attorneys and Law Firm HTML Template
Version: 1.0
-----------------------------------------------------------------------------------
CSS INDEX
===================
01. Theme default CSS
02. Elements CSS
02.1 Accordion Elements CSS
02.2 Blockquote Elements CSS
02.3 Button Elements CSS
02.4 Form Elements CSS
02.5 Modal Elements CSS
02.6 Pagination Elements CSS
03. Header CSS
04. Login Signup Modal CSS
05. Slider/Hero CSS
06. Page Heading/Title CSS
07. Job Search CSS
08. Jobs/Job List CSS
09. Job Single/Details CSS
10. Job Category CSS
11. Company CSS
12. Blog CSS
13. Comment CSS
14. Sidebar CSS
15. About CSS
16. Team CSS
17. Pricing CSS
18. APP CSS
19. Testimonial CSS
20. Funfact CSS
21. FAQ CSS
22. Contact CSS
23. Footer CSS
-----------------------------------------------------------------------------------*/
@import "variabls";
/*----------------------------------------*/
/* 01. Theme default CSS
/*----------------------------------------*/
@import "common";
/*----------------------------------------*/
/* 02. Elements CSS
/*----------------------------------------*/
@import "form";
@import "button";
@import "modal";
@import "accordion";
@import "pagination";
@import "blockquote";
/*----------------------------------------*/
/* 03. Header CSS
/*----------------------------------------*/
@import "header";
/*----------------------------------------*/
/* 04. Login Signup Modal CSS
/*----------------------------------------*/
@import "loginSignupModal";
/*----------------------------------------*/
/* 05. Slider/Hero CSS
/*----------------------------------------*/
@import "slider";
/*----------------------------------------*/
/* 06. Page Heading/Title CSS
/*----------------------------------------*/
@import "page-heading";
/*----------------------------------------*/
/* 07. Job Search CSS
/*----------------------------------------*/
@import "job-search";
/*----------------------------------------*/
/* 08. Jobs/Job List CSS
/*----------------------------------------*/
@import "jobs";
/*----------------------------------------*/
/* 09. Job Single/Details CSS
/*----------------------------------------*/
@import "job-single";
/*----------------------------------------*/
/* 10. Job Category CSS
/*----------------------------------------*/
@import "job-category";
/*----------------------------------------*/
/* 11. Company CSS
/*----------------------------------------*/
@import "company";
/*----------------------------------------*/
/* 12. Blog CSS
/*----------------------------------------*/
@import "blog";
/*----------------------------------------*/
/* 13. Comment CSS
/*----------------------------------------*/
@import "comment";
/*----------------------------------------*/
/* 14. Sidebar CSS
/*----------------------------------------*/
@import "sidebar";
/*----------------------------------------*/
/* 15. About CSS
/*----------------------------------------*/
@import "about";
/*----------------------------------------*/
/* 16. Team CSS
/*----------------------------------------*/
@import "team";
/*----------------------------------------*/
/* 17. Pricing CSS
/*----------------------------------------*/
@import "pricing";
/*----------------------------------------*/
/* 18. App CSS
/*----------------------------------------*/
@import "app";
/*----------------------------------------*/
/* 19. Testimonial CSS
/*----------------------------------------*/
@import "testimonial";
/*----------------------------------------*/
/* 20. Funfact CSS
/*----------------------------------------*/
@import "funfact";
/*----------------------------------------*/
/* 21. FAQ CSS
/*----------------------------------------*/
@import "faq";
/*----------------------------------------*/
/* 22. Contact CSS
/*----------------------------------------*/
@import "contact";
/*----------------------------------------*/
/* 23. Footer CSS
/*----------------------------------------*/
@import "footer";
\ No newline at end of file
// Top page
// search
// banner
.banner {
background-image: url('banner.jpg');
min-height: 200px;
background-repeat: no-repeat;
background-size: cover;
}
// latest-job
.latest-job {
.job-item {
font-size: 14px;
.job-title {
text-decoration: none;
color: black;
font-size: 20px;
font-weight: 500;
}
.job-caption {
line-height: 18px;
.job-company {
text-decoration: none;
font-size: 14px;
color: #495057;
}
.job-salary {
color: #008563;
margin: 0;
}
.job-locations {
ul {
list-style: none;
margin: 0 0 6px 0;
padding: 0;
color: #495057;
}
}
.job-desc {
overflow: hidden;
text-overflow: ellipsis;
line-height: 18px;
-webkit-line-clamp: 2;
max-height: 36px;
display: -webkit-box;
-webkit-box-orient: vertical;
}
}
}
}
// top_cities
.top_cities {
.city-item {
margin-bottom: 12px;
a {
font-size: 18px;
text-decoration: none;
color: #287ab9;
margin: 10px 0;
}
}
.all-cities-btn {
color: #287ab9;
font-size: 20px;
text-decoration: none;
}
.all-cities-btn:hover {
text-decoration: underline;
}
}
// top_industries
.top_industries {
.industry-item {
margin-bottom: 12px;
a {
font-size: 18px;
text-decoration: none;
color: #287ab9;
margin: 10px 0;
}
}
.all-industries-btn {
color: #287ab9;
font-size: 20px;
text-decoration: none;
}
.all-industries-btn:hover {
text-decoration: underline;
}
}
class FavoriteIndustriesController < ApplicationController
before_action :authenticate_user!
before_action :load_industry, only: %i[create destroy]
def index
@favorite_industries = current_user.favorite_industries
.page(params[:page]).per(Job::JOB_PER_PAGE)
end
def create
@favorite_industry = current_user.favorite_industries.build(industry_id: @industry.id)
respond_to :js if @favorite_industry.save
end
def destroy
@favorite_industry = current_user.favorite_industries.find_by(industry_id: @industry.id)
respond_to :js if @favorite_industry.destroy
end
private
def load_industry
@industry = Industry.find_by(id: params[:industry_id])
end
end
class FavoriteJobsController < ApplicationController class FavoriteJobsController < ApplicationController
# before_action :logged_in_user
before_action :authenticate_user! before_action :authenticate_user!
before_action :load_job, only: %i[create destroy] before_action :load_job, only: %i[create destroy]
......
class JobsController < ApplicationController class JobsController < ApplicationController
before_action :history, only: :show before_action :history, only: :show
before_action :views_count, only: :show
before_action :salary_search before_action :salary_search
before_action :city_industry_list before_action :city_industry_list
before_action :name, only: :index before_action :name, only: :index
...@@ -31,6 +32,13 @@ class JobsController < ApplicationController ...@@ -31,6 +32,13 @@ class JobsController < ApplicationController
history.update(updated_at: Time.current) history.update(updated_at: Time.current)
end end
def views_count
job = Job.find_by(id: params[:id])
count = job.views_count + 1
job.update_attribute :views_count, count
end
def name def name
@name = if params[:city_slug] @name = if params[:city_slug]
City.find_by(slug: params[:city_slug]).name City.find_by(slug: params[:city_slug]).name
...@@ -44,6 +52,6 @@ class JobsController < ApplicationController ...@@ -44,6 +52,6 @@ class JobsController < ApplicationController
def get_jobs(query) def get_jobs(query)
jobs_ids = query['response']['docs'].map { |j| j['job_id'] } jobs_ids = query['response']['docs'].map { |j| j['job_id'] }
@jobs = Job.eager_load(:cities, :cities_jobs, :company).find(jobs_ids) @jobs = Job.eager_load(:cities, :cities_jobs, :company).find(jobs_ids)
@jobs_count = query['numFound'] @jobs_count = query['response']['numFound']
end end
end end
class TopController < ApplicationController class TopController < ApplicationController
before_action :salary_search before_action :salary_search
before_action :city_industry_list before_action :city_industry_list
before_action :solr
def index def index
solr = Solr.new(params) @latest_jobs = get_jobs(@solr.latest_jobs)
@latest_jobs = get_jobs(solr.latest_jobs) @attractive_jobs = Job.top_views
@total_job = solr.query_all['response']['numFound'] @total_job = @solr.query_all['response']['numFound']
@total_job = 100 @top_cities = @solr.facet_query('city_id')['vietnam'].take(City::TOP_JOB_COUNT)
@top_cities = solr.facet_query('city_id')['vietnam'].take(City::TOP_JOB_COUNT) @top_industries = @solr.facet_query('industry_id').take(Industry::TOP_JOB_COUNT)
@top_industries = solr.facet_query('industry_id').take(Industry::TOP_JOB_COUNT) @member = User.count
@resume = ApplyJob.count
@company = Company.count
suggest
end end
private private
def suggest
return unless user_signed_in? && current_user.industries?
industry_ids = current_user.fav_industries_ids
@suggest_jobs = get_jobs(@solr.suggest_jobs(industry_ids))
end
def solr
@solr = Solr.new(params)
end
def get_jobs(query) def get_jobs(query)
jobs_ids = query['response']['docs'].map { |j| j['job_id'] } jobs_ids = query['response']['docs'].map { |j| j['job_id'] }
Job.eager_load(:cities, :cities_jobs, :company).find(jobs_ids) Job.includes(:cities, :cities_jobs, :company).find(jobs_ids)
end end
end end
...@@ -16,12 +16,12 @@ module ApplicationHelper ...@@ -16,12 +16,12 @@ module ApplicationHelper
a = list.map do |item| a = list.map do |item|
case model case model
when :city when :city
link_to item.name, city_jobs_path(city_slug: item.slug), class: 'mx-1 text-decoration-none text-info' link_to item.name, city_jobs_path(city_slug: item.slug)
when :industry when :industry
link_to item.name, industry_jobs_path(industry_slug: item.slug), class: 'mx-1 text-decoration-none text-info' link_to item.name, industry_jobs_path(industry_slug: item.slug)
end end
end end
a.join('|').html_safe a.join(' | ').html_safe
end end
def view_search_result def view_search_result
......
module FavoriteIndustriesHelper
end
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
//= require jquery //= require jquery
//= require jquery_ujs //= require jquery_ujs
//= require popper
//= require bootstrap
//= require turbolinks //= require turbolinks
//= require_tree . //= require_tree .
...@@ -17,7 +19,5 @@ Rails.start() ...@@ -17,7 +19,5 @@ Rails.start()
Turbolinks.start() Turbolinks.start()
ActiveStorage.start() ActiveStorage.start()
import "bootstrap"
window.bootstrap = require("bootstrap");
import "../stylesheets/application.scss";
import "./validation"; import "./validation";
import "./main";
(function ($) {
"use strict";
/*--
Commons Variables
-----------------------------------*/
var $window = $(window),
$body = $('body'),
$mainWrapper = $('.main-wrapper'),
$headerHeight = $('.header').outerHeight();
/*______________________________ */
/*--
Custom script to call Background
Image form html data attribute
-----------------------------------*/
$('[data-bg-image]').each(function () {
var $this = $(this),
$image = $this.data('bg-image');
$this.css('background-image', 'url(' + $image + ')');
});
/*--
Parallax
-----------------------------------*/
$('.bg-parallax').each(function () {
$(this).parallax("50%", 0.5);
})
/*--
Header Sticky
-----------------------------------*/
$window.on('scroll', function () {
if ($window.scrollTop() > 350) {
$('.header').addClass('is-sticky');
} else {
$('.header').removeClass('is-sticky');
}
});
/*--
Mobile OffCanvas Open & Close
-----------------------------------*/
function mobileOffCanvasToggle() {
var $offCanvas = $('#offcanvas'),
$offCanvasOverlay = $('.offcanvas-overlay');
$('.offcanvas-toggle').on('click', function () {
$offCanvas.addClass('open');
$offCanvasOverlay.fadeIn();
$body.addClass('offcanvas-open');
});
$('.offcanvas-close, .offcanvas-overlay').on('click', function () {
$offCanvas.removeClass('open');
$offCanvasOverlay.fadeOut();
$body.removeClass('offcanvas-open');
});
}
mobileOffCanvasToggle();
/*--
Off Canvas Menu
-----------------------------------*/
function mobileOffCanvasMenu() {
var $offCanvasNav = $('.offcanvas-menu'),
$offCanvasNavSubMenu = $offCanvasNav.find('.sub-menu');
/*Add Toggle Button With Off Canvas Sub Menu*/
$offCanvasNavSubMenu.parent().prepend('<span class="menu-expand"><i></i></span>');
/*Category Sub Menu Toggle*/
$offCanvasNav.on('click', 'li a, li .menu-expand', function (e) {
var $this = $(this);
if ($this.siblings('.sub-menu').length && ($this.attr('href') === '#' || $this.hasClass('menu-expand'))) {
e.preventDefault();
if ($this.siblings('ul:visible').length) {
$this.parent('li').removeClass('active');
$this.siblings('ul').slideUp();
$this.parent('li').find('li').removeClass('active');
$this.parent('li').find('ul:visible').slideUp();
} else {
$this.parent('li').addClass('active');
$this.closest('li').siblings('li').removeClass('active').find('li').removeClass('active');
$this.closest('li').siblings('li').find('ul:visible').slideUp();
$this.siblings('ul').slideDown();
}
}
});
}
mobileOffCanvasMenu();
/*--
Slick Slider Activation
-----------------------------------*/
// Company Slider
$('.company-slider').slick({
slidesToShow: 6,
slidesToScroll: 1,
arrows: true,
autoplay: true,
prevArrow: '<button class="slick-prev"><i class="fa fa-angle-left"></i></button>',
nextArrow: '<button class="slick-next"><i class="fa fa-angle-right"></i></button>',
responsive: [{
breakpoint: 1200,
settings: {
slidesToShow: 5
}
}, {
breakpoint: 992,
settings: {
slidesToShow: 4
}
}, {
breakpoint: 767,
settings: {
slidesToShow: 3,
arrows: false
}
}, {
breakpoint: 480,
settings: {
slidesToShow: 2,
arrows: false
}
}]
});
// Job Category Slider
$('.job-category-slider').slick({
slidesToShow: 5,
slidesToScroll: 1,
arrows: true,
autoplay: true,
prevArrow: '<button class="slick-prev"><i class="fa fa-angle-left"></i></button>',
nextArrow: '<button class="slick-next"><i class="fa fa-angle-right"></i></button>',
responsive: [{
breakpoint: 1200,
settings: {
slidesToShow: 4
}
}, {
breakpoint: 992,
settings: {
slidesToShow: 3
}
}, {
breakpoint: 767,
settings: {
slidesToShow: 2,
arrows: false
}
}, {
breakpoint: 480,
settings: {
slidesToShow: 1
}
}]
});
// Testimonial Slider
$('.testimonial-slider').slick({
slidesToShow: 1,
slidesToScroll: 1,
arrows: true,
autoplay: true,
prevArrow: '<button class="slick-prev"><i class="fa fa-angle-left"></i></button>',
nextArrow: '<button class="slick-next"><i class="fa fa-angle-right"></i></button>',
responsive: [{
breakpoint: 767,
settings: {
slidesToShow: 1,
arrows: false
}
}]
});
// Blog Slider
$('.blog-slider').slick({
slidesToShow: 3,
slidesToScroll: 1,
arrows: false,
autoplay: true,
prevArrow: '<button class="slick-prev"><i class="fa fa-angle-left"></i></button>',
nextArrow: '<button class="slick-next"><i class="fa fa-angle-right"></i></button>',
responsive: [{
breakpoint: 992,
settings: {
slidesToShow: 2
}
}, {
breakpoint: 767,
settings: {
slidesToShow: 2,
arrows: false
}
}, {
breakpoint: 767,
settings: {
slidesToShow: 2,
arrows: false
}
}, {
breakpoint: 575,
settings: {
slidesToShow: 1
}
}]
});
/*--
Counter Up
-----------------------------------*/
$('.counter').counterUp({
time: 3000
});
/*--
Salary Range (Ion Range Slider)
-----------------------------------*/
$("#salary-range").ionRangeSlider({
type: "double",
min: 3000,
max: 25000,
step: 500,
from: 7000,
to: 15000,
grid: false,
});
/*--
Scroll Up
-----------------------------------*/
$.scrollUp({
scrollText: '<i class="fa fa-long-arrow-up"></i>',
});
})(jQuery);
class FavoriteIndustry < ApplicationRecord
belongs_to :user
belongs_to :industry
end
...@@ -2,6 +2,8 @@ class Industry < ApplicationRecord ...@@ -2,6 +2,8 @@ class Industry < ApplicationRecord
TOP_JOB_COUNT = 9 TOP_JOB_COUNT = 9
has_and_belongs_to_many :jobs has_and_belongs_to_many :jobs
has_many :favorite_industries, dependent: :destroy
validates :slug, presence: true, uniqueness: { case_sensitive: true } validates :slug, presence: true, uniqueness: { case_sensitive: true }
......
...@@ -14,4 +14,8 @@ class Job < ApplicationRecord ...@@ -14,4 +14,8 @@ class Job < ApplicationRecord
has_many :apply_jobs, dependent: :destroy has_many :apply_jobs, dependent: :destroy
has_many :favorite_jobs, dependent: :destroy has_many :favorite_jobs, dependent: :destroy
has_many :history_jobs, dependent: :destroy has_many :history_jobs, dependent: :destroy
def self.top_views
includes(:cities, :cities_jobs, :company).order(views_count: :desc).limit(LATEST_JOBS_LIMIT)
end
end end
...@@ -7,6 +7,7 @@ class User < ApplicationRecord ...@@ -7,6 +7,7 @@ class User < ApplicationRecord
has_many :apply_jobs, dependent: :destroy has_many :apply_jobs, dependent: :destroy
has_many :favorite_jobs, dependent: :destroy has_many :favorite_jobs, dependent: :destroy
has_many :history_jobs, dependent: :destroy has_many :history_jobs, dependent: :destroy
has_many :favorite_industries, dependent: :destroy
has_one_attached :cv has_one_attached :cv
...@@ -32,6 +33,20 @@ class User < ApplicationRecord ...@@ -32,6 +33,20 @@ class User < ApplicationRecord
@favorite_job_ids.include?(job.id) @favorite_job_ids.include?(job.id)
end end
def fav_industry?(industry_slug)
industry_id = Industry.find_by(slug: industry_slug).id
@fav_industry_ids ||= Set.new(favorite_industries.pluck(:industry_id))
@fav_industry_ids.include?(industry_id)
end
def industries?
favorite_industries.exists?
end
def fav_industries_ids
favorite_industries.pluck(:industry_id)
end
protected protected
def password_required? def password_required?
......
...@@ -62,7 +62,7 @@ class Solr ...@@ -62,7 +62,7 @@ class Solr
city_name = city.name city_name = city.name
q = "search:*#{@params[:search]}*" q = "search:*#{@params[:search]}*"
fq = if @params[:salary] fq = if @params[:salary].present?
["cities_name: \"#{escape_str(city_name)}\"", "min_salary: [#{@params[:salary]} TO *]"] ["cities_name: \"#{escape_str(city_name)}\"", "min_salary: [#{@params[:salary]} TO *]"]
else else
"cities_name: \"#{escape_str(city_name)}\"" "cities_name: \"#{escape_str(city_name)}\""
...@@ -78,7 +78,7 @@ class Solr ...@@ -78,7 +78,7 @@ class Solr
industry_name = industry.name industry_name = industry.name
q = "search:*#{@params[:search]}*" q = "search:*#{@params[:search]}*"
fq = if @params[:salary] fq = if @params[:salary].present?
["industries_name: \"#{escape_str(industry_name)}\"", "min_salary: [#{@params[:salary]} TO *]"] ["industries_name: \"#{escape_str(industry_name)}\"", "min_salary: [#{@params[:salary]} TO *]"]
else else
"industries_name: \"#{escape_str(industry_name)}\"" "industries_name: \"#{escape_str(industry_name)}\""
...@@ -87,6 +87,16 @@ class Solr ...@@ -87,6 +87,16 @@ class Solr
send_request(q, fq) send_request(q, fq)
end end
def suggest_jobs(arr)
parsed = arr.join(' ')
q = "industry_id: #{parsed}"
fq = []
facet = nil
sort = 'max_salary desc'
rows = 5
send_request(q, fq, facet, sort, rows)
end
def facet_query(facet_param) def facet_query(facet_param)
q = '*:*' q = '*:*'
fq = '*:*' fq = '*:*'
......
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
- provide(:title, 'All applies jobs') - provide(:title, 'All applies jobs')
/ search / search
.container.mt-5 = render 'shared/page_heading', title: 'Applies jobs', url: history_jobs_path
.section.section-padding
.container
= form_with(url: admin_applies_jobs_path, method: :get, local: true) do |f| = form_with(url: admin_applies_jobs_path, method: :get, local: true) do |f|
.row.mb-2.form-group .row.mb-2.form-group
.col-2 .col-2
...@@ -40,17 +42,14 @@ ...@@ -40,17 +42,14 @@
.col-6.d-flex.justify-content-center .col-6.d-flex.justify-content-center
= f.submit 'Export', name: 'csv',class: 'btn btn-primary w-50 my-4 btn-height',data: { disable_with: false } = f.submit 'Export', name: 'csv',class: 'btn btn-primary w-50 my-4 btn-height',data: { disable_with: false }
/result /result
.container .container.mb-3
h2.my-5.text-center
| All applies jobs
.container
.no-padding.d-flex.align-items-center.flex-column .no-padding.d-flex.align-items-center.flex-column
.page-info.p-2 .page-info.p-2
= page_entries_info @apply_jobs = page_entries_info @apply_jobs
.page-info.p-2 .page-info.p-2
= paginate @apply_jobs = paginate @apply_jobs
.container .container
- @apply_jobs.each do |apply| - @apply_jobs.each do |apply|
.apply-item .apply-item
.apply-job-title .apply-job-title
...@@ -81,7 +80,7 @@ ...@@ -81,7 +80,7 @@
span.fw-normal.text-dark span.fw-normal.text-dark
= apply.created_at.strftime('%d/%m/%Y') = apply.created_at.strftime('%d/%m/%Y')
hr hr
.container .container
.no-padding.d-flex.align-items-center.flex-column .no-padding.d-flex.align-items-center.flex-column
.page-info.p-2 .page-info.p-2
= page_entries_info @apply_jobs = page_entries_info @apply_jobs
......
<h2>Resend confirmation instructions</h2>
<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
<%= render "admins/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
</div>
<div class="actions">
<%= f.submit "Resend confirmation instructions" %>
</div>
<% end %>
<%= render "admins/shared/links" %>
- provide(:title, 'Resend confirmation instructions')
= render 'shared/page_heading', title: 'Resend'
.section.section-padding
.container
.row.justify-content-center
.col-lg-6.col-sm-6.col-12.flex-grow-1.mb-4
= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f|
= render "admins/shared/error_messages", resource: resource
.field
= f.label :email
br
= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email)
.actions
= f.submit "Resend confirmation instructions"
= render "admins/shared/links"
\ No newline at end of file
- provide(:title, 'Admin Forgot password') - provide(:title, 'Admin Forgot password')
= render 'shared/page_heading', title: 'Forgot password', url: login_path
.container .section.section-padding
.container
.row.justify-content-center .row.justify-content-center
.col-6 .col-lg-6.col-sm-6.col-12.flex-grow-1.mb-4
h2.text-center.my-5
| Forgot password
= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f|
= render 'admins/shared/error_messages', resource: resource = render 'admins/shared/error_messages', resource: resource
.field.row.form-group.mb-4 .field.row.form-group.mb-4
.col-2 .col-lg-2.col-sm-2.col-12
= f.label :email, class: 'form-label' = f.label :email, class: 'form-label'
.col-10 .col-lg-10.col-sm-10.col-12
= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control mb-2' = f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control mb-2'
span.form-msg span.form-msg
- if devise_mapping.confirmable? && controller_name != 'confirmations' - if devise_mapping.confirmable? && controller_name != 'confirmations'
p p
= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name), class: 'text-decoration-none' = link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name), class: 'text-decoration-none'
.actions.row.justify-content-end .actions.row.justify-content-end
.col-10.d-flex.justify-content-center .col-lg-10.col-12.d-flex.justify-content-around
= f.submit 'Confirm your email', class: 'btn btn-primary w-75 my-4', data: { disable_with: false } = f.submit 'Confirm your email', class: 'btn btn-primary w-100 my-4', data: { disable_with: false }
javascript: javascript:
Validator({ Validator({
......
- provide(:title, 'Admin Sign Up') - provide(:title, 'Admin Sign Up')
.container = render 'shared/page_heading', title: 'Sign up', url: new_admin_registration_path
.section.section-padding
.container
.row.justify-content-center .row.justify-content-center
.col-6 .col-lg-6.col-sm-6.col-12.flex-grow-1.mb-4
h2.text-center.my-5
| Sign up
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| = form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
= render 'users/shared/error_messages', resource: resource = render 'users/shared/error_messages', resource: resource
.field.row.form-group.mb-4 .field.row.form-group.mb-4
.col-2 .col-lg-2.col-sm-2.col-12
= f.label :email, class: 'form-label' = f.label :email, class: 'form-label'
.col-10 .col-lg-10.col-sm-10.col-12
= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control mb-2' = f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control mb-2'
span.form-msg span.form-msg
.field.row.form-group.mb-4 .field.row.form-group.mb-4
.col-2 .col-lg-2.col-sm-2.col-12
= f.label :password, class: 'form-label' = f.label :password, class: 'form-label'
.col-10 .col-lg-10.col-sm-10.col-12
= f.password_field :password, autocomplete: 'new-password', class: 'form-control mb-2' = f.password_field :password, autocomplete: 'new-password', class: 'form-control mb-2'
span.form-msg span.form-msg
.field.row.form-group.mb-4 .field.row.form-group.mb-4
.col-2 .col-lg-2.col-sm-2.col-12
= f.label :password_confirmation, class: 'form-label' = f.label :password_confirmation, class: 'form-label'
.col-10 .col-lg-10.col-sm-10.col-12
= f.password_field :password_confirmation, autocomplete: 'new-password', class: 'form-control mb-2' = f.password_field :password_confirmation, autocomplete: 'new-password', class: 'form-control mb-2'
span.form-msg span.form-msg
.actions .actions.row.justify-content-end
.col-lg-10.col-12.d-flex.justify-content-around
= f.submit 'Sign up', class: 'btn btn-primary w-100 my-5' = f.submit 'Sign up', class: 'btn btn-primary w-100 my-5'
javascript: javascript:
......
- provide(:title, 'Log in') - provide(:title, 'Log in')
.container = render 'shared/page_heading', title: 'Admin Login', url: admin_login_path
.section.section-padding
.container
.row.justify-content-center .row.justify-content-center
.col-6 .col-lg-6.col-sm-6.col-12.flex-grow-1.mb-4
h2.text-center.my-5
| Log in Admin
= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
.field.row.form-group.mb-4 .field.row.form-group.mb-4
.col-2 .col-lg-2.col-sm-2.col-12
= f.label :email, class: 'form-label' = f.label :email, class: 'form-label'
.col-10 .col-lg-10.col-sm-10.col-12
= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control mb-2' = f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control mb-2'
span.form-msg span.form-msg
.field.row.form-group.mb-4 .field.row.form-group.mb-4
.col-2 .col-lg-2.col-sm-2.col-12
= f.label :password, class: 'form-label' = f.label :password, class: 'form-label'
.col-10 .col-lg-10.col-sm-10.col-12
= f.password_field :password, autocomplete: 'current-password', class: 'form-control mb-2' = f.password_field :password, autocomplete: 'current-password', class: 'form-control mb-2'
span.form-msg span.form-msg
- if devise_mapping.rememberable? - if devise_mapping.rememberable?
.field .field
= f.check_box :remember_me = f.check_box :remember_me
= f.label :remember_me, class: 'form-label mx-2' = f.label :remember_me, class: 'form-label mx-2'
.d-flex.justify-content-between
- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' - if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations'
= link_to 'Forgot password?', forgot_password_path, class: 'text-decoration-none' = link_to 'Forgot password?', new_admin_password_path, class: 'text-decoration-none'
= link_to 'Sign up', new_registration_path(resource_name), class: 'text-decoration-none'
.actions.row.justify-content-end .actions.row.justify-content-end
.col-10.d-flex.justify-content-around .col-lg-10.col-12.d-flex.justify-content-around
= f.submit 'Log in', class: 'btn btn-primary w-25', data: { disable_with: false } = f.submit 'Log in', class: 'btn btn-primary w-100', data: { disable_with: false }
= link_to 'Sign up', new_registration_path(resource_name), class: 'text-decoration-none w-25 btn btn-secondary'
javascript: javascript:
Validator({ Validator({
......
.job-item / .job-item
.job-head.d-flex.align-items-center.justify-content-between / .job-head.d-flex.align-items-center.justify-content-between
= link_to applied_job.job.title, applied_job.job, class: 'job-title fs-3 text-decoration-none text-reset' / = link_to applied_job.job.title, applied_job.job, class: 'job-title fs-3 text-decoration-none text-reset'
- if user_signed_in? && current_user.favorite?(applied_job.job) / - if user_signed_in? && current_user.favorite?(applied_job.job)
= render 'shared/unfavorite', job_id: applied_job.job.id / = render 'shared/unfavorite', job_id: applied_job.job.id
- else / - else
= render 'shared/favorite', job_id: applied_job.job.id / = render 'shared/favorite', job_id: applied_job.job.id
.job-caption / .job-caption
= link_to applied_job.job.company.name, '#', class: 'job-company text-decoration-none text-secondary' / = link_to applied_job.job.company.name, '#', class: 'job-company text-decoration-none text-secondary'
p.job-salary.text-success / p.job-salary.text-success
| Salary: #{applied_job.job.salary} / | Salary: #{applied_job.job.salary}
ul.list-unstyled / ul.list-unstyled
/ = show_location(applied_job.job.cities)
/ .job-desc
/ = truncate(simple_format(applied_job.job.description), escape: false, length: 250)
/ .applied-at
/ strong Applied at:
/ = applied_job.updated_at.strftime('%d/%m/%Y')
/ hr.my-4
= link_to applied_job.job, class: 'job-list' do
.company-logo.col-auto
= image_tag('company-logo', width: '70')
.salary-type.col-auto.order-sm-3
span.salary-range
= applied_job.job.salary
span.badge.badge-success
= applied_job.job.job_type
.content.col
h6.title
= applied_job.job.title
ul.meta
li
strong.text-primary
= applied_job.job.company.name
li
i.fa.fa-map-marker
= show_location(applied_job.job.cities) = show_location(applied_job.job.cities)
.job-desc p.applied-at
= truncate(simple_format(applied_job.job.description), escape: false, length: 250)
.applied-at
strong Applied at: strong Applied at:
= applied_job.updated_at.strftime('%d/%m/%Y') = applied_job.updated_at.strftime('%d/%m/%Y')
hr.my-4
- provide(:title, 'Confirmation') - provide(:title, 'Confirmation')
.container = render 'shared/page_heading', title: 'Confirm', url: '#'
.section
.container
= render 'ribbon' = render 'ribbon'
.container .container
h1.my-5.text-center
| Confirmation
.col .col
= form_with(model: @apply, scope: :apply_job, url: done_job_path, local: true) do |f| = form_with(model: @apply, scope: :apply_job, url: done_job_path, local: true) do |f|
...@@ -31,7 +32,7 @@ ...@@ -31,7 +32,7 @@
.col-2 .col-2
= f.label :cv, 'Cv: ', class: 'form-label label' = f.label :cv, 'Cv: ', class: 'form-label label'
.col-10 .col-10
span.form-control span
= url_for(@apply.cv) = url_for(@apply.cv)
= link_to 'Edit', apply_job_path(job_id: @job.id), class: 'btn btn-secondary w-25 btn-height mr-5 my-5' = link_to 'Edit', apply_job_path(job_id: @job.id), class: 'btn btn-secondary w-25 btn-height mr-5 my-5'
......
- provide(:title, 'Done') - provide(:title, 'Done')
.container = render 'shared/page_heading', title: 'Done', url: '#'
.section.py-5
.container
=render 'ribbon' =render 'ribbon'
.container.text-center .container.text-center
h3.my-4 h3.my-4
| You have successfully applied for the #{@job.title} | You have successfully applied for the #{@job.title}
p Good luck! Thank you for using our service p Good luck! Thank you for using our service
......
- provide(:title, 'User Apply Jobs') - provide(:title, 'User Apply Jobs')
.container.py-5 = render 'shared/page_heading', title: 'APPlIED JOBS', url: apply_jobs_path
h1.text-center.my-job-label My Job
.no-padding.d-flex.align-items-center.flex-column .section.section-padding
.container
.job-list-toolbar
.page-info.p-2 .page-info.p-2
= page_entries_info @jobs = page_entries_info @jobs
.page-info.p-2 .job-list-wrap
= paginate @jobs
= render partial: "my_jobs", collection: @jobs, as: :applied_job = render partial: "my_jobs", collection: @jobs, as: :applied_job
.no-padding.d-flex.align-items-center.flex-column ul.pagination.pagination-center.mt-5
.page-info.p-2
= page_entries_info @jobs
.page-info.p-2
= paginate @jobs = paginate @jobs
\ No newline at end of file
- provide(:title, 'Apply job') - provide(:title, 'Apply job')
.container = render 'shared/page_heading', title: 'Apply form', url: '#'
.section
.container.py-5
= render 'ribbon' = render 'ribbon'
.container .container
h1.my-5.text-center h3.fs-5.fw-bold.mb-4.text-center
| Apply Form
p.fs-5.fw-bold.mb-4.text-center
= @job.title = @job.title
.col .col
= form_with(model: @apply, url: confirm_job_path, local: true, id: 'apply-form') do |f| = form_with(model: @apply, url: confirm_job_path, local: true, id: 'apply-form') do |f|
...@@ -29,7 +30,7 @@ ...@@ -29,7 +30,7 @@
.col-2 .col-2
= f.label :cv, class: 'form-label label' = f.label :cv, class: 'form-label label'
.col-10 .col-10
= f.file_field :cv, files: @blob, accept: ApplyJob::ACCEPT_CONTENT_TYPE, class: 'form-control' = f.file_field :cv, files: @blob, accept: ApplyJob::ACCEPT_CONTENT_TYPE
span.form-msg span.form-msg
br br
= f.submit 'Confirm', class: 'btn btn-primary w-25 my-4 btn-height',data: { disable_with: false } = f.submit 'Confirm', class: 'btn btn-primary w-25 my-4 btn-height',data: { disable_with: false }
......
- provide(:title, 'Cities')
= render 'shared/page_heading', title: 'Cities', url: cities_path
/region /region
.countries-list .section.section-padding
.container
.countries-list
.container.py-5 .container.py-5
h2.mt-0 REGION h2.mt-0 REGION
hr.my-4 hr.my-4
...@@ -7,9 +14,9 @@ ...@@ -7,9 +14,9 @@
- @regions.each do |region| - @regions.each do |region|
.col-lg-4.col-md-6.text-center .col-lg-4.col-md-6.text-center
.mt-5 .mt-5
h3.h4.mb-2.text-white.see-more-text= link_to region.upcase, anchor: region h3.mb-2.text-primary.see-more-text= link_to region.upcase, anchor: region
// cities list // cities list
.cities-list .cities-list
.container .container
- @job_quantity_by_region.each do |region, city_job_count| - @job_quantity_by_region.each do |region, city_job_count|
.countries-job-list id=region .countries-job-list id=region
...@@ -19,7 +26,7 @@ ...@@ -19,7 +26,7 @@
hr.my-4 hr.my-4
.row .row
- city_job_count.each do |city| - city_job_count.each do |city|
.col-lg-4.col-md-6.text-center .col-lg-4.col-md-6.col-12.text-center
.mt-5 .mt-5
.city-item .city-item
h3.h4.mb-2.see-more-text= link_to city[0], city_jobs_path(city_slug: city[1]) , class:'text-decoration-none fw-normal text-reset' h3.h4.mb-2.see-more-text= link_to city[0], city_jobs_path(city_slug: city[1]) , class:'text-decoration-none fw-normal text-reset'
......
div id="favorite-industry-#{industry_id}"
= button_to favorite_industries_path(industry_id: industry_id, format: :js),
method: :post,
remote: true,
class: 'btn' do
i.fa.fa-heart-o.mr-1
\ No newline at end of file
div id="unfavorite-industry-#{industry_id}"
= button_to favorite_industry_path(current_user, industry_id: industry_id, format: :js),
method: :delete,
remote: true,
class: 'btn' do
i.fa.fa-heart.mr-1
\ No newline at end of file
$("#favorite-industry-<%= @industry.id %>").html("<%= escape_javascript(render('unfavorite', industry_id: @industry.id)) %>");
$("#unfavorite-industry-<%= @industry.id %>").html("<%= escape_javascript(render('favorite', industry_id: @industry.id)) %>");
- provide(:title, 'History page') - provide(:title, 'History page')
= render 'shared/page_heading', title: 'FAVORITE', url: favorite_jobs_path
- if @favorite_jobs.empty? - if @favorite_jobs.empty?
h2 No jobs in your history .section.section-padding
.container.text-center
h2 You have not applied for any job yet
= link_to 'See more jobs', jobs_path, class: 'btn btn-primary m-3'
- else - else
= render partial: 'shared/jobs_list_index', object: @favorite_jobs, as: 'jobs' = render partial: 'shared/jobs_list_index', object: @favorite_jobs, as: 'jobs'
- provide(:title, 'History page') - provide(:title, 'History page')
= render 'shared/page_heading', title: 'HISTORY', url: history_jobs_path
- if @history_jobs.empty? - if @history_jobs.empty?
.section.section-padding
.container.text-center
h2 No jobs in your history h2 No jobs in your history
- else - else
= render partial: 'shared/jobs_list_index', object: @history_jobs, as: 'jobs' = render partial: 'shared/jobs_list_index', object: @history_jobs, as: 'jobs'
.countries-list - provide(:title, 'Industries')
.container.py-5
h2.mt-0 INDUSTRIES = render 'shared/page_heading', title: 'INDUSTRIES', url: industries_path
hr.my-4
.section.section-padding
.container
#info-box.row #info-box.row
- @job_quantity_by_industry.each do |industry| - @job_quantity_by_industry.each do |industry|
.col-lg-6.col-md-6.text-center .col-lg-6.col-sm-6.col-12.text-center
.mt-5 .mt-5
h3.h4.mb-2.see-more-text= link_to industry[0], industry_jobs_path(industry_slug: industry[1]) , class:'text-decoration-none fw-normal text-reset' .row
.col-10
h5.mb-2.see-more-text= link_to industry[0], industry_jobs_path(industry_slug: industry[1]) , class:'text-decoration-none fw-normal text-reset'
p.text-muted.mb-0= pluralize(industry[2], 'job') p.text-muted.mb-0= pluralize(industry[2], 'job')
.col-2
- if user_signed_in? && current_user.fav_industry?(industry[1])
= render 'favorite_industries/unfavorite', industry_id: Industry.find_by(slug: industry[1]).id
- else
= render 'favorite_industries/favorite', industry_id: Industry.find_by(slug: industry[1]).id
hr.divider.my-4 hr.divider.my-4
/ h3.h4.mb-2.see-more-text= link_to industry[0], industry_jobs_path(industry_slug: industry[1]) , class:'text-decoration-none fw-normal text-reset'
/ p.text-muted.mb-0= pluralize(industry[2], 'job')
/ hr.divider.my-4
- provide(:title, 'Job list page') - provide(:title, 'Job list page')
/ search box / search box
= render 'shared/page_heading', title: 'Jobs', url: jobs_path, name: @name
/ .page-heading-section.section.bg-parallax[data-bg-image="assets/images/bg/bg-1.jpg" data-overlay="50"]
/ .container
/ .page-heading-content.text-center
/ h3.title
/ | Browse Jobs
/ ol.breadcrumb
/ li.breadcrumb-item
/ = link_to 'Home', root_path
/ li.breadcrumb-item.active
/ = link_to 'Jobs', jobs_path
/ - if params[:city_slug] || params[:industry_slug]
/ li.breadcrumb-item.active
/ = @name
= render 'shared/search' = render 'shared/search'
.container .section.section-padding
.container
h3 h3
= view_search_result = view_search_result
hr.my-4 .job-list-toolbar
.no-padding.d-flex.align-items-center.flex-column
.page-info.p-2 .page-info.p-2
= page_entries_info @jobs = page_entries_info @jobs
.page-info.p-2 .job-list-wrap
= paginate @jobs
.container
.container
- @jobs.each do |job| - @jobs.each do |job|
/ job = link_to job, class: 'job-list' do
.job-item .company-logo.col-auto
.job-head.d-flex.align-items-center.justify-content-between = image_tag('company-logo', width: '120')
= link_to job.title, job, class: 'job-title fs-3 text-decoration-none text-reset' .salary-type.col-auto.order-sm-3
- if user_signed_in? && current_user.favorite?(job) span.salary-range
= render 'shared/unfavorite', job_id: job.id = job.salary
- else span.badge.badge-success
= render 'shared/favorite', job_id: job.id = job.job_type
.job-caption .content.col
= link_to job.company.name, '#', class: 'job-company text-decoration-none text-secondary' h6.title
p.job-salary.text-success = job.title
| Salary: #{job.salary} ul.meta
ul.list-unstyled li
strong.text-primary
= job.company.name
li
i.fa.fa-map-marker
- city_list = job.cities
= show_location(job.cities) = show_location(job.cities)
.job-desc / p
= truncate(simple_format(job.description), escape: false, length: 250) / = truncate(simple_format(job.description), escape: false, length: 150)
hr.my-4 ul.pagination.pagination-center.mt-5
.no-padding.d-flex.align-items-center.flex-column
.page-info.p-2
= page_entries_info @jobs
.page-info.p-2
= paginate @jobs = paginate @jobs
/ .section.section-padding
/ .container
/ h3
/ = view_search_result
/ hr.my-4
/ .no-padding.d-flex.align-items-center.flex-column
/ .page-info.p-2
/ = page_entries_info @jobs
/ .page-info.p-2
/ = paginate @jobs
/ .
/ - @jobs.each do |job|
/ / job
/ .job-item
/ .job-head.d-flex.align-items-center.justify-content-between
/ = link_to job.title, job, class: 'job-title fs-3 text-decoration-none text-reset'
/ - if user_signed_in? && current_user.favorite?(job)
/ = render 'shared/unfavorite', job_id: job.id
/ - else
/ = render 'shared/favorite', job_id: job.id
/ .job-caption
/ = link_to job.company.name, '#', class: 'job-company text-decoration-none text-secondary'
/ p.job-salary.text-success
/ | Salary: #{job.salary}
/ ul.list-unstyled
/ = show_location(job.cities)
/ .job-desc
/ = truncate(simple_format(job.description), escape: false, length: 250)
/ hr.my-4
/ .no-padding.d-flex.align-items-center.flex-column
/ .page-info.p-2
/ = page_entries_info @jobs
/ .page-info.p-2
/ = paginate @jobs
\ No newline at end of file
...@@ -2,90 +2,200 @@ ruby: ...@@ -2,90 +2,200 @@ ruby:
city_list = @job.cities city_list = @job.cities
industry_list = @job.industries industry_list = @job.industries
/ html .page-heading-section.section.bg-parallax[data-bg-image="assets/images/bg/bg-1.jpg" data-overlay="50"]
.container.my-5 .container
/ breadcrumb .page-heading-content.text-center
.breadcrumb h3.title
= link_to 'Home', root_path, class: 'text-decoration-none text-info' = @job.title
span.mx-1 > ol.breadcrumb
.text-info li.breadcrumb-item
= link_to 'Home', root_path
li.breadcrumb-item
= show_breadcrumb(city_list, :city) = show_breadcrumb(city_list, :city)
span.mx-1 > li.breadcrumb-item
.text-info
= show_breadcrumb(industry_list, :industry) = show_breadcrumb(industry_list, :industry)
span.mx-1 > li.breadcrumb-item.active
= @job.title = @job.title
hr.my-4 .section.section-padding
.container
/ job details .row.mb-n5
.job-detail.my5 .col-lg-8.col-12.mb-5.pr-lg-5
.job-apply.d-flex.align-items-center.justify-content-between .job-list-details
h2.align-items-start .job-details-head.row.mx-0
.company-logo.col-auto
= image_tag('company-logo', width: 120)
.salary-type.col-auto.order-sm-3
span.salary-range
= @job.salary
span.badge.badge-success
= @job.job_type
.content.col
h5.title
= @job.title = @job.title
= link_to 'Apply for this job', apply_job_path(job_id: @job.id), class: 'btn btn-primary' ul.meta
p.text-secondary li
strong.text-primary
= @job.company.name = @job.company.name
.row.bg-light
.col-4
ul.list-unstyled
li li
strong.d-block i.fa.fa-map-marker
| Location
p
= show_location(city_list) = show_location(city_list)
.job-details-body
h6.mb-3
| Job Description
= @job.description.html_safe
h6.mb-3.mt-4
| Requirement
= @job.requirement.html_safe
h6.mb-3.mt-4
| Benefits
ul
- @job.benefit.split('---').each do |benefit|
li.list-unstyled.col-4.text-secondary
= benefit
h6.mb-3.mt-4
| Other info
ul
- @job.other_info.split('---').each do |info|
li.text-secondary
= info
.col-lg-4.col-12.mb-5
.sidebar-wrap
.sidebar-widget
.inner
.row.m-n2
.col-xl-auto.col-lg-12.col-sm-auto.col-12.p-2
/ a.d-block.btn.btn-outline-secondary[href="#"]
/ i.fa.fa-heart-o.mr-1
/ | Save Job
- if user_signed_in? && current_user.favorite?(@job)
= render 'shared/unfavorite', job_id: @job.id
- else
= render 'shared/favorite', job_id: @job.id
.col-xl-auto.col-lg-12.col-sm-auto.col-12.p-2
= link_to 'Apply now', apply_job_path(job_id: @job.id), class: 'd-block btn btn-primary'
.sidebar-widget
.inner
h6.title
| Job Overview
ul.job-overview.list-unstyled
li li
strong strong
| Salary | Published on:
p.text-success = @job.created_at.strftime('%d/%m/%Y')
= @job.salary
.col-4
ul.list-unstyled
li li
strong strong
| Type | Experience:
p = @job.experience
li
strong
| Type:
= @job.job_type = @job.job_type
li li
strong strong
| Position | Position:
p
= @job.position = @job.position
.col-4
ul.list-unstyled
li li
strong strong
| Experience | Job Location:
p = show_location(city_list)
= @job.experience li
strong
| Salary:
= @job.salary
li li
strong strong
| Expiration date | Application Deadline:
p
= @job.expiration_date.strftime('%d/%m/%Y') = @job.expiration_date.strftime('%d/%m/%Y')
.job-benefits.my-4
h3
| Benefits / / html
.row / .container.my-5
- @job.benefit.split('---').each do |benefit| / / breadcrumb
li.list-unstyled.col-4.text-secondary / .breadcrumb
= benefit / = link_to 'Home', root_path, class: 'text-decoration-none text-info'
.job-desc.my-4 / span.mx-1 >
h3 / .text-info
| Description / = show_breadcrumb(city_list, :city)
= @job.description.html_safe / span.mx-1 >
.job-req.my-4 / .text-info
h3 / = show_breadcrumb(industry_list, :industry)
| Requirement / span.mx-1 >
= @job.requirement.html_safe / = @job.title
.job-info.my-4 / hr.my-4
h3
| Other info / / job details
- @job.other_info.split('---').each do |info| / .job-detail.my5
li.text-secondary / .job-apply.d-flex.align-items-center.justify-content-between
= info / h2.align-items-start
.job-apply.d-flex.align-items-center.justify-content-between / = @job.title
= link_to 'Apply for this job', apply_job_path(job_id: @job.id), class: 'btn btn-primary' / = link_to 'Apply for this job', apply_job_path(job_id: @job.id), class: 'btn btn-primary'
- if user_signed_in? && current_user.favorite?(@job) / p.text-secondary
= render 'shared/unfavorite', job_id: @job.id / = @job.company.name
- else / .row.bg-light
= render 'shared/favorite', job_id: @job.id / .col-4
/ ul.list-unstyled
/ li
/ strong.d-block
/ | Location
/ p
/ = show_location(city_list)
/ li
/ strong
/ | Salary
/ p.text-success
/ = @job.salary
/ .col-4
/ ul.list-unstyled
/ li
/ strong
/ | Type
/ p
/ = @job.job_type
/ li
/ strong
/ | Position
/ p
/ = @job.position
/ .col-4
/ ul.list-unstyled
/ li
/ strong
/ | Experience
/ p
/ = @job.experience
/ li
/ strong
/ | Expiration date
/ p
/ = @job.expiration_date.strftime('%d/%m/%Y')
/ .job-benefits.my-4
/ h3
/ | Benefits
/ .row
/ - @job.benefit.split('---').each do |benefit|
/ li.list-unstyled.col-4.text-secondary
/ = benefit
/ .job-desc.my-4
/ h3
/ | Description
/ = @job.description.html_safe
/ .job-req.my-4
/ h3
/ | Requirement
/ = @job.requirement.html_safe
/ .job-info.my-4
/ h3
/ | Other info
/ - @job.other_info.split('---').each do |info|
/ li.text-secondary
/ = info
/ .job-apply.d-flex.align-items-center.justify-content-between
/ = link_to 'Apply for this job', apply_job_path(job_id: @job.id), class: 'btn btn-primary'
/ - if user_signed_in? && current_user.favorite?(@job)
/ = render 'shared/unfavorite', job_id: @job.id
/ - else
/ = render 'shared/favorite', job_id: @job.id
footer.footer / footer.footer
small / small
| The / | The
= link_to 'VenJob', root_path / = link_to 'VenJob', root_path
| by Mai Hoàng Thái Hà / | by Mai Hoàng Thái Hà
nav / nav
/ ul
/ li
/ = link_to 'About', '#'
/ li
/ = link_to 'Contact', '#'
.footer-top-section.section
.container
.footer-widget-wrap.row
.col-lg-3.col-sm-6.col-12
.footer-widget
.footer-widget-about
= link_to image_tag('logo.png', alt: 'Zigexn logo', width: '150'),
- root_path
p
| Lorem ipsum dolor sit amet consecte tur adipisicing elit. Maiores officiis quod quo id inventore quis.
ul.footer-socail
li
a[href="#"]
i.fa.fa-facebook
li
a[href="#"]
i.fa.fa-twitter
li
a[href="#"]
i.fa.fa-linkedin
li
a[href="#"]
i.fa.fa-pinterest-p
.col-lg-3.col-sm-6.col-12
.footer-widget
h6.title
| Column 1
.footer-widget-link
ul ul
li li
= link_to 'About', '#' = link_to 'Item link', '#'
li
= link_to 'Item link', '#'
li
= link_to 'Item link', '#'
li
= link_to 'Item link', '#'
li
= link_to 'Item link', '#'
.col-lg-3.col-sm-6.col-12
.footer-widget
h6.title
| Column 2
.footer-widget-link
ul
li
= link_to 'Item link', '#'
li
= link_to 'Item link', '#'
li
= link_to 'Item link', '#'
li
= link_to 'Item link', '#'
li li
= link_to 'Contact', '#' = link_to 'Item link', '#'
\ No newline at end of file .col-lg-3.col-sm-6.col-12
.footer-widget
h6.title
| Newsletter
.footer-widget-newsletter
p
| Lorem ipsum dolor sit amet consecte tur adipisicing elit. Maiores officiis quod quo id inventore quis.
form#mc-form.mc-form
input#mc-email[autocomplete="off" type="email" placeholder="Enter your e-mail address"]
button#mc-submit.btn
i.fa.fa-envelope-o
.mailchimp-alerts.text-centre
.mailchimp-submitting
.mailchimp-success.text-success
.mailchimp-error.text-danger
.footer-bottom-section.section
.container
.row
.col-12
p.footer-copyright.text-center
| This is a sample website. Some functions won't work
header.navbar.navbar-fixed-top.navbar-inverse / header.navbar.navbar-fixed-top.navbar-inverse
/ .container
/ = link_to image_tag('logo.png', alt: 'Zigexn logo', width: '150'),
/ - root_path
/ nav
/ ul.nav.navbar-nav.navbar-right.text-light
/ - if user_signed_in?
/ li
/ = link_to "Apply jobs", apply_jobs_path
/ li
/ = link_to "History", history_jobs_path
/ li
/ = link_to "Favorite", favorite_jobs_path
/ li
/ = link_to "Profile", user_profile_path
/ li
/ = link_to "Log out", destroy_user_session_path, method: :delete
/ - elsif admin_signed_in?
/ li
/ = link_to "Applies job", admin_applies_jobs_path
/ li
/ = link_to "Profile", '#'
/ li
/ = link_to "Log out", destroy_admin_session_path, method: :delete
/ - else
li
= link_to "Admin", admin_login_path
li
= link_to "Log in", login_path
li
= link_to "Sign up", signup_path
header.header
.container .container
.row.justify-content-between.align-items-center
.col
.header-logo
= link_to image_tag('logo.png', alt: 'Zigexn logo', width: '150'), = link_to image_tag('logo.png', alt: 'Zigexn logo', width: '150'),
- root_path - root_path
nav .col-auto.d-lg-none.d-flex.align-items-center
ul.nav.navbar-nav.navbar-right.text-light button.offcanvas-toggle
span
- unless user_signed_in? || admin_signed_in?
.header-links.col-auto.order-lg-3
= link_to "Log in", login_path
span or
= link_to "Sign up", signup_path
span |
= link_to "Admin", admin_login_path
nav#main-menu.main-menu.col-lg-auto.order-lg-2
ul
li.has-children
= link_to 'Home', root_path
li.has-children
= link_to 'All jobs', jobs_path
li.has-children
= link_to 'Industries', industries_path
li.has-children
= link_to 'Cities', cities_path
- if admin_signed_in?
li
= link_to 'Admin', '#'
ul.sub-menu
li.has-children
= link_to "Applies job", admin_applies_jobs_path
hr
li.has-children
= button_to "Sign out", destroy_admin_session_path, class: 'logout', method: :delete
- if user_signed_in? - if user_signed_in?
li li
= link_to "Profile", user_profile_path
ul.sub-menu
li.has-children
= link_to "Apply jobs", apply_jobs_path = link_to "Apply jobs", apply_jobs_path
li li.has-children
= link_to "History", history_jobs_path = link_to "History", history_jobs_path
li li.has-children
= link_to "Favorite", favorite_jobs_path = link_to "Favorite", favorite_jobs_path
li li.has-children
= link_to "Profile", user_profile_path = link_to "Profile", user_profile_path
hr
li.has-children
= button_to "Log out", destroy_user_session_path, class: 'logout', method: :delete
#offcanvas.offcanvas-section
button.offcanvas-close[data-target="#offcanvas"]
| ×
.offcanvas-wrap
.inner
- unless user_signed_in? || admin_signed_in?
.offcanvas-user
= link_to "Log in", login_path
span or
= link_to "Sign up", signup_path
.offcanvas-menu
nav
ul
li.has-children
= link_to 'Home', root_path
li li
= link_to "Log out", destroy_user_session_path, method: :delete = link_to 'Jobs', jobs_path
- elsif admin_signed_in? ul.sub-menu
li li
= link_to "Applies job", admin_applies_jobs_path = link_to 'Industries', industries_path
li
= link_to 'Cities', cities_path
li li
= link_to "Profile", '#' = link_to 'Contact', '#'
- if user_signed_in?
li li
= link_to "Log out", destroy_admin_session_path, method: :delete = link_to current_user.name, user_profile_path
- else ul.sub-menu
li li
= link_to "Admin", admin_login_path = link_to 'Edit account', edit_profile_path
li li
= link_to "Log in", login_path = link_to 'Favorited', favorite_jobs_path
li li
= link_to "Sign up", signup_path = link_to 'History', history_jobs_path
\ No newline at end of file li
= link_to 'Applied', apply_jobs_path
li
= link_to "Log out", destroy_user_session_path, method: :delete
.offcanvas-overlay
...@@ -12,8 +12,13 @@ html ...@@ -12,8 +12,13 @@ html
= yield(:head) = yield(:head)
body body
= render 'layouts/header' = render 'layouts/header'
.container-fluid style ="min-height:80vh;" .flash
- flash.each do |message_type, message| - flash.each do |message_type, message|
div class=("text-center alert alert-#{message_type}") = message div class=("m-0 text-center alert alert-#{message_type}")
= message
.text-center
a.btn-close close
= yield = yield
= render 'layouts/footer' = render 'layouts/footer'
= javascript_pack_tag 'main'
div id="favorite-#{job_id}" div id="favorite-#{job_id}"
= link_to favorite_jobs_path(job_id: job_id, format: :js), = button_to favorite_jobs_path(job_id: job_id, format: :js),
method: :post, method: :post,
remote: true, remote: true,
class: 'btn btn-primary' class: 'd-block btn btn-outline-secondary' do
i.fa.fa-heart-o.mr-1
| Favorite | Favorite
/ = form_with(model: @favorite_job, url: favorite_jobs_path(job_id: job_id), id: "favorite-#{job_id}", remote: true) do |f|
/ = f.submit 'Favorite', class: 'd-block btn btn-outline-secondary'
.container.py-5 .section.section-padding
.no-padding.d-flex.align-items-center.flex-column .container
.job-list-toolbar
.page-info.p-2 .page-info.p-2
= page_entries_info jobs = page_entries_info jobs
.page-info.p-2 .job-list-wrap
= paginate jobs
.container
= form_with(url: apply_job_path, method: :get) do |f| = form_with(url: apply_job_path, method: :get) do |f|
- jobs.each do |item| - jobs.each do |item|
.row .row
.col-1.job-check.align-self-center .col-2.job-check.align-self-center
= f.radio_button :job_id, item.job.id, class: 'btn-check', id: "option-#{item.job.id}" = f.radio_button :job_id, item.job.id, class: 'btn-check', id: "option-#{item.job.id}"
= f.label 'Choose', class: 'btn btn-outline-primary', for: "option-#{item.job.id}" = f.label 'Choose', class: 'btn btn-outline-primary', for: "option-#{item.job.id}"
.job-item.col-10 .col-10
.job-head = link_to item.job, class: 'job-list' do
= link_to item.job.title, item.job, class: 'job-title fs-3 text-decoration-none text-reset' .company-logo.col-auto
.job-caption = image_tag('company-logo', width: '120')
= link_to item.job.company.name, '#', class: 'job-company text-decoration-none text-secondary' .salary-type.col-auto.order-sm-3
p.job-salary.text-success span.salary-range
| Salary: #{item.job.salary} = item.job.salary
ul.list-unstyled span.badge.badge-success
= item.job.job_type
.content.col
h6.title
= item.job.title
ul.meta
li
strong.text-primary
= item.job.company.name
li
i.fa.fa-map-marker
- city_list = item.job.cities
= show_location(item.job.cities) = show_location(item.job.cities)
.job-desc .d-flex.justify-content-center.my-5
= truncate(simple_format(item.job.description), escape: false, length: 250)
.job-fav.col-1
- if user_signed_in? && current_user.favorite?(item.job)
= render 'shared/unfavorite', job_id: item.job.id
- else
= render 'shared/favorite', job_id: item.job.id
hr.my-4
.d-flex.justify-content-center
= f.submit 'Apply job', class: 'btn btn-primary w-50' = f.submit 'Apply job', class: 'btn btn-primary w-50'
.no-padding.d-flex.align-items-center.flex-column ul.pagination.pagination-center.mt-5
.page-info.p-2
= page_entries_info jobs
.page-info.p-2
= paginate jobs = paginate jobs
/ .container.py-5
/ .no-padding.d-flex.align-items-center.flex-column
/ .page-info.p-2
/ = page_entries_info jobs
/ .page-info.p-2
/ = paginate jobs
/ .container
/ = form_with(url: apply_job_path, method: :get) do |f|
/ - jobs.each do |item|
/ .row
/ .col-1.job-check.align-self-center
/ = f.radio_button :job_id, item.job.id, class: 'btn-check', id: "option-#{item.job.id}"
/ = f.label 'Choose', class: 'btn btn-outline-primary', for: "option-#{item.job.id}"
/ .job-item.col-10
/ .job-head
/ = link_to item.job.title, item.job, class: 'job-title fs-3 text-decoration-none text-reset'
/ .job-caption
/ = link_to item.job.company.name, '#', class: 'job-company text-decoration-none text-secondary'
/ p.job-salary.text-success
/ | Salary: #{item.job.salary}
/ ul.list-unstyled
/ = show_location(item.job.cities)
/ .job-desc
/ = truncate(simple_format(item.job.description), escape: false, length: 250)
/ .job-fav.col-1
/ - if user_signed_in? && current_user.favorite?(item.job)
/ = render 'shared/unfavorite', job_id: item.job.id
/ - else
/ = render 'shared/favorite', job_id: item.job.id
/ hr.my-4
/ .d-flex.justify-content-center
/ = f.submit 'Apply job', class: 'btn btn-primary w-50'
/ .no-padding.d-flex.align-items-center.flex-column
/ .page-info.p-2
/ = page_entries_info jobs
/ .page-info.p-2
/ = paginate jobs
.page-heading-section.section.bg-parallax[data-bg-image="assets/banner-4.jpg" data-overlay="50"]
.container
.page-heading-content.text-center
h3.title
= title
ol.breadcrumb
li.breadcrumb-item
= link_to 'Home', root_path
li.breadcrumb-item.active
= link_to title, url: '#'
- if params[:city_slug] || params[:industry_slug]
li.breadcrumb-item.active
= name
\ No newline at end of file
.search.text-center.my-5 .job-search-section.section
.container .container
.job-search-wrap
.job-search-form
-if params[:city_slug] -if params[:city_slug]
= form_tag(city_jobs_path(city_slug: params[:city_slug]), method: :get, class: "form-inline") do = form_tag(city_jobs_path(city_slug: params[:city_slug]), method: :get) do
.row .row.mb-n4
.col-md-8.mb-md-0.no-padding .col-lg-6.col-sm-6.col-12.flex-grow-1.mb-4
= search_field_tag :search, params[:search], placeholder: 'Find a job (name, company, position)', class: 'form-control rounded-left no-border-radius bg-light h-100' = search_field_tag :search, params[:search], placeholder: 'Find a job (name, company, position)'
.col-md-2.mb-md-0.no-padding .col-lg-3.col-sm-6.col-12.flex-grow-1.mb-4
= select_tag(:salary, = select_tag(:salary,
options_for_select( @salary_range.collect {|s| [vnd_format(s), s]}, options_for_select( @salary_range.collect {|s| [vnd_format(s), s]},
params[:salary] ), params[:salary] ),
class:"form-select bg-light h-100") include_blank: 'Select salary')
.col-md-2.mb-md-0.no-padding .col-lg-3.col-sm-6.col-12.flex-grow-1.mb-4
= submit_tag "Search", class: "h-100 w-100 btn btn-block btn-lg btn-info" = submit_tag "Search", class: "btn btn-primary"
-elsif params[:industry_slug] -elsif params[:industry_slug]
= form_tag(industry_jobs_path(industry_slug: params[:industry_slug]), method: :get, class: "form-inline") do = form_tag(industry_jobs_path(industry_slug: params[:industry_slug]), method: :get) do
.row .row.mb-n4
.col-md-8.mb-md-0.no-padding .col-lg-6.col-sm-6.col-12.flex-grow-1.mb-4
= search_field_tag :search, params[:search], placeholder: 'Find a job (name, company, position)', class: 'form-control rounded-left no-border-radius bg-light h-100' = search_field_tag :search, params[:search], placeholder: 'Find a job (name, company, position)'
.col-md-2.mb-md-0.no-padding .col-lg-3.col-sm-6.col-12.flex-grow-1.mb-4
= select_tag(:salary, = select_tag(:salary,
options_for_select( @salary_range.collect {|s| [vnd_format(s), s]}, options_for_select( @salary_range.collect {|s| [vnd_format(s), s]},
params[:salary] ), params[:salary] ),
class:"form-select bg-light h-100") include_blank: 'Select salary')
.col-md-2.mb-md-0.no-padding .col-lg-3.col-sm-6.col-12.flex-grow-1.mb-4
= submit_tag "Search", class: "h-100 w-100 btn btn-block btn-lg btn-info" = submit_tag "Search", class: "btn btn-primary"
- else - else
= form_tag(jobs_path, method: :get, class: "form-inline") do = form_tag(jobs_path, method: :get) do
.row .row.mb-n4
.col-md-4.mb-md-0.no-padding .col-lg-4.col-sm-6.col-12.flex-grow-1.mb-4
= search_field_tag :search, params[:search], placeholder: 'Find a job (name, company, position)', class: 'form-control rounded-left no-border-radius bg-light h-100' = search_field_tag :search, params[:search], placeholder: 'Find a job (name, company, position)'
.col-md-2.mb-md-0.no-padding .col-lg-2.col-sm-6.col-12.flex-grow-1.mb-4
= select_tag(:city, = select_tag(:city,
options_for_select( @city_slug_list, options_for_select( @city_slug_list,
params[:city] ), params[:city] ),
include_blank: 'Select city', include_blank: 'Select city')
class:"form-select bg-light h-100") .col-lg-2.col-sm-6.col-12.flex-grow-1.mb-4
.col-md-2.mb-md-0.no-padding
= select_tag(:industry, = select_tag(:industry,
options_for_select( @industry_slug_list, options_for_select( @industry_slug_list,
params[:industry] ), params[:industry] ),
include_blank: 'Select city', include_blank: 'Select city')
class:"form-select bg-light h-100") .col-lg-2.col-sm-6.col-12.flex-grow-1.mb-4
.col-md-2.mb-md-0.no-padding
= select_tag(:salary, = select_tag(:salary,
options_for_select( @salary_range.collect {|s| [vnd_format(s), s]}, options_for_select( @salary_range.collect {|s| [vnd_format(s), s]},
params[:salary] ), params[:salary] ),
include_blank: 'Select salary', include_blank: 'Select salary')
class:"form-select bg-light h-100")
.col-md-2.mb-md-0.no-padding .col-lg-2.col-sm-12.col-12.flex-grow-1.mb-4
= submit_tag "Search", class: "h-100 w-100 btn btn-block btn-lg btn-info" = submit_tag "Search", class: "btn btn-primary"
div id="unfavorite-#{job_id}" div id="unfavorite-#{job_id}"
= link_to favorite_job_path(current_user, job_id: job_id, format: :js), = button_to favorite_job_path(current_user, job_id: job_id, format: :js),
method: :delete, method: :delete,
remote: true, remote: true,
class: 'btn btn-secondary' class: 'btn btn-secondary'
| UnFavorite | UnFavorite
/ = form_with(model: @favorite_job, url: favorite_job_path(current_user, job_id: job_id), id: "unfavorite-#{job_id}", method: :delete, remote: true) do |f|
/ = f.submit 'UnFavorite', class: 'btn btn-secondary'
.section.section-padding
.container
.section-title
h2.title
= title
p
= desc
.job-list-wrap
- jobs.each do |job|
= link_to job, class: 'job-list' do
.company-logo.col-auto
= image_tag('company-logo', width: '70', height: '70')
.salary-type.col-auto.order-sm-3
span.salary-range
= job.salary
span.badge.badge-success
= job.job_type
.content.col
h6.title
= job.title
ul.meta
li
strong.text-primary
= job.company.name
li
i.fa.fa-map-marker
- city_list = job.cities
= show_location(job.cities)
.text-center.mt-4.mt-lg-5
= link_to 'View All Jobs', jobs_path , class: 'btn btn-primary'
- provide(:title, 'Home page') - provide(:title, 'Home page')
/ search box
.container / banner
.banner.d-flex.justify-content-center.align-items-center .slider-section.section
.row .slide-item.bg-parallax[data-bg-image="assets/banner-1" data-overlay="50"]
.col
h2.text-white
| Total: #{pluralize(@total_job, "job")}
= render 'shared/search'
/ , url_options: jobs_path
/ latest job
.latest-job.mb-5
.container.mb-5
h2
| Latest jobs
hr.my-2
- @latest_jobs.each do |job|
.job-item.mb-4
= link_to job.title, job, class: 'job-title'
.job-caption
= link_to job.company.name, '#', class: 'job-company'
p.job-salary
| Salary:
= job.salary
.job-locations
- city_list = job.cities
= show_location(job.cities)
.job-desc
= truncate(simple_format(job.description), escape: false, length: 250)
hr.my-2
/ top cities
.top_cities.mb-5
.container .container
h2 Top cities .slider-content.text-center
hr.my-2 h2.title
.row.align-items-start.mb-3 | Find Your Next Job
- @top_cities.each do |city| p
.col-4.city-item | More then
= link_to city[0], city_jobs_path(city_slug: city[1]), class: 'city-name' span
span.job-count = @total_job
| ( | job listed here.
= pluralize(city[2], 'job')
|) / search
= link_to 'See all cities', cities_path, class:'all-cities-btn' = render 'shared/search'
/ top industries
.top_industries.mb-5 / latest jobs
= render 'section_jobs', title: 'Latest Jobs',
desc: "Here's the most recent job listed on the website.",
jobs: @latest_jobs
/ quotes
.section.section-padding.bg-parallax[data-bg-image="assets/banner-5.jpg" data-overlay="50"]
.container
.funfact-wrap.row
.funfact.col-12
span.counter
| Something quotes
span.title
| Something quotes
/ suggest or topviews
- if user_signed_in? && current_user.industries?
= render 'section_jobs', title: 'Recommend for you',
desc: 'Here are the hot jobs based on your favorite industries',
jobs: @suggest_jobs
- else
= render 'section_jobs', title: 'Attractive jobs',
desc: "Here's the most viewed jobs",
jobs: @attractive_jobs
/ count
.section.section-padding.bg-parallax[data-bg-image="assets/banner-2.jpg" data-overlay="50"]
.container .container
h2 Top industries .funfact-wrap.row
hr.my-2 .funfact.col-md-3.col-sm-6.col-12
.row.align-items-start span.counter
= @total_job
span.title
| Job Post
.funfact.col-md-3.col-sm-6.col-12
span.counter
= @member
span.title
| Members
.funfact.col-md-3.col-sm-6.col-12
span.counter
= @resume
span.title
| Resume
.funfact.col-md-3.col-sm-6.col-12
span.counter
= @company
span.title
| Company
/ industries
.section.section-padding
.container
.section-title
h2.title
| Industry
p
| Here's the most job listed by those industries.
.company-slider.row
- @top_industries.each do |industry| - @top_industries.each do |industry|
.col-4.industry-item .col
= link_to industry[0], industry_jobs_path(industry_slug: industry[1]), class: 'industry-name' = link_to industry_jobs_path(industry_slug: industry[1]) do
span.job-count = image_tag('logo-sample')
h6.title
= industry[0]
span.open-job
| ( | (
= pluralize(industry[2], 'job') = pluralize(industry[2], 'job')
|) |)
= link_to 'See all industries', industries_path, class:'all-industries-btn' .text-center.mt-4.mt-lg-5
\ No newline at end of file = link_to 'See all industries', industries_path, class:'btn btn-primary'
/ quotes
.section.section-padding.bg-parallax[data-bg-image="assets/banner-3.jpg" data-overlay="65"]
.container
.testimonial-slider.row
.col
.testimonial.text-center.text-white
p
| Lorem, ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, modi sed praesentium necessitatibus tenetur neque, veritatis esse voluptatem
= image_tag('avt')
h6.name
| Ha Mai
span.title
| Marketer of VeNJob
.col
.testimonial.text-center.text-white
p
| Lorem, ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, modi sed praesentium necessitatibus tenetur neque, veritatis esse voluptatem
= image_tag('avt')
h6.name
| Ha Mai
span.title
| CEO of VeNJob
.col
.testimonial.text-center.text-white
p
| Lorem, ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, modi sed praesentium necessitatibus tenetur neque, veritatis esse voluptatem
= image_tag('avt')
h6.name
| Ha Mai
span.title
| Admin of VeNJob
/ cities
.section.section-padding
.container
.section-title
h2.title
| Cities
p
| Here's the most job listed by those industries.
.company-slider.row
- @top_cities.each do |city|
.col
= link_to city_jobs_path(city_slug: city[1]) do
= image_tag('logo-sample')
h6.title
= city[0]
span.open-job
| (
= pluralize(city[2], 'job')
|)
.text-center.mt-4.mt-lg-5
= link_to 'See all cities', cities_path, class:'btn btn-primary'
\ No newline at end of file
<h2>Resend confirmation instructions</h2>
<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
<%= render "users/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
</div>
<div class="actions">
<%= f.submit "Resend confirmation instructions" %>
</div>
<% end %>
<%= render "users/shared/links" %>
- provide(:title, 'Resend confirmation instructions')
= render 'shared/page_heading', title: 'Resend', url: new_user_confirmation_path
.section.section-padding
.container
.row.justify-content-center
.col-lg-6.col-sm-6.col-12.flex-grow-1.mb-4
= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f|
= render "users/shared/error_messages", resource: resource
.field
= f.label :email
br
= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email)
.actions
= f.submit "Resend confirmation instructions", class: 'btn btn-primary'
= render "users/shared/links"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment