From 1290edefde298fce4b9d8a519ad1efff7fca48a0 Mon Sep 17 00:00:00 2001 From: Tin Date: Sat, 24 Jun 2017 10:38:21 +0800 Subject: [PATCH] Style refector (#167) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 小教室 refector * style login button * add home banner * index experiences block * sort index experience * use slice * add rwd style to exp page * search bar rwd * add g0v to footer * Fix typo --- .../ExperienceSearch/ExperienceBlock.js | 42 +-- .../ExperienceBlock.module.css | 56 +++- .../ExperienceSearch.module.css | 128 +++------ src/components/ExperienceSearch/Searchbar.js | 80 ++++++ .../ExperienceSearch/Searchbar.module.css | 80 ++++++ src/components/ExperienceSearch/index.js | 259 ++++++++---------- src/components/LaborRightsMenu/About.js | 25 ++ .../LaborRightsMenu/About.module.css | 18 ++ src/components/LaborRightsMenu/index.js | 9 +- src/components/LaborRightsSingle/Body.js | 25 +- .../LaborRightsSingle/Body.module.css | 15 +- .../LaborRightsSingle/CallToAction.js | 17 +- .../LaborRightsSingle/CallToAction.module.css | 23 +- src/components/LandingPage/HomeBanner.js | 23 +- .../LandingPage/HomeBanner.module.css | 81 +++--- .../LandingPage/LandingPage.module.css | 38 +++ src/components/LandingPage/index.js | 84 +++++- src/components/Layout/App.module.css | 17 +- .../Layout/Footer/Footer.module.css | 25 +- src/components/Layout/Footer/index.js | 5 + .../Layout/Header/Header.module.css | 38 ++- src/components/Layout/Header/index.js | 17 +- src/components/common/base/Heading.js | 4 +- src/components/common/base/Heading.module.css | 12 +- src/components/common/base/Section.js | 8 +- src/components/common/base/Section.module.css | 21 ++ src/components/common/base/Wrapper.module.css | 2 +- .../common/form/Checkbox.module.css | 20 +- src/components/common/form/Radio.module.css | 15 +- .../common/form/TextInput.module.css | 18 +- src/components/common/global.module.css | 13 + src/components/common/icons/Magnifiner.js | 11 + src/components/common/reset.module.css | 2 + src/components/common/variables.module.css | 6 +- src/containers/LandingPage/index.js | 11 +- 35 files changed, 810 insertions(+), 438 deletions(-) create mode 100644 src/components/ExperienceSearch/Searchbar.js create mode 100644 src/components/ExperienceSearch/Searchbar.module.css create mode 100644 src/components/LaborRightsMenu/About.js create mode 100644 src/components/LaborRightsMenu/About.module.css create mode 100644 src/components/common/icons/Magnifiner.js diff --git a/src/components/ExperienceSearch/ExperienceBlock.js b/src/components/ExperienceSearch/ExperienceBlock.js index 2ae29bec1..64123a8cb 100644 --- a/src/components/ExperienceSearch/ExperienceBlock.js +++ b/src/components/ExperienceSearch/ExperienceBlock.js @@ -1,5 +1,6 @@ import React, { Component, PropTypes } from 'react'; import { Link } from 'react-router'; +import cn from 'classnames'; import { Heading, P } from 'common/base'; import i from 'common/icons'; @@ -8,8 +9,8 @@ import Comment from 'common/reaction/Comment'; import { formatWithCommas } from '../../utils/numberUtil'; import styles from './ExperienceBlock.module.css'; -const Label = ({ Icon, text }) => ( -
+const Label = ({ Icon, text, className }) => ( +

{text}

@@ -17,16 +18,20 @@ const Label = ({ Icon, text }) => ( Label.propTypes = { Icon: PropTypes.func.isRequired, text: PropTypes.string.isRequired, + className: PropTypes.string, }; class ExperienceBlock extends Component { static propTypes = { - to: PropTypes.string.isRequired, data: PropTypes.object.isRequired, + size: PropTypes.oneOf(['s', 'm', 'l']), + } + static defaultProps = { + size: 'm', } render() { - const { data, to } = this.props; + const { data, size } = this.props; const expType = data.type === 'interview' ? '面試' : '工作'; const date = new Date(Date.parse(data.created_at)); const year = date.getFullYear(); @@ -54,32 +59,35 @@ class ExperienceBlock extends Component { } return ( - -
+ +

{`${expType}${splitter}${year} 年 ${month} 月`}

- + {data.title}
-
-

+

{data.preview} ... ... 閱讀更多

- -
- - -
+
+ + +
); } diff --git a/src/components/ExperienceSearch/ExperienceBlock.module.css b/src/components/ExperienceSearch/ExperienceBlock.module.css index f977de2e6..1a4dd7e51 100644 --- a/src/components/ExperienceSearch/ExperienceBlock.module.css +++ b/src/components/ExperienceSearch/ExperienceBlock.module.css @@ -1,9 +1,8 @@ -@value gray-dark, link-blue from "../common/variables.module.css"; +@value gray-dark, link-blue, border-gray, page-gutter-s from "common/variables.module.css"; .container { display: block; background-color: #fff; - padding: 24px; box-shadow: 0 0 4px rgba(0,0,0, .15); margin-bottom: 40px; transition-property: background, box-shadow; @@ -20,33 +19,32 @@ } } +.contentWrapper { + padding: 24px; +} + .heading { margin-bottom: 16px; margin-top: 16px; } .labels { - display: flex; margin-bottom: 16px; } .label { margin-right: 24px; - display: flex; + display: inline-flex; align-items: center; svg { - width: 18px; - height: 18px; + width: 16px; + height: 16px; fill: #C3C3C3; margin-right: 8px; } } -.content { - margin-bottom: 16px; -} - .more { color: link-blue; } @@ -54,7 +52,45 @@ .reaction { display: flex; align-items: center; + padding: 8px 24px; > div { margin-right: 24px; } } + +.m { + &.container { + height: 100%; + position: relative; + } + + .location, .salary { + display: none; + } + + .contentWrapper { + margin-bottom: 40px; + } + + .reaction { + position: absolute; + right: 0; + left: 0; + bottom: 0; + border-top: 1px solid border-gray; + } +} + +.l { + &.container { + @media (max-width: 850px) { + margin-left: calc(page-gutter-s * -1); + margin-right: calc(page-gutter-s * -1); + margin-bottom: 24px; + } + } + + .reaction { + padding-bottom: 20px; + } +} diff --git a/src/components/ExperienceSearch/ExperienceSearch.module.css b/src/components/ExperienceSearch/ExperienceSearch.module.css index c6be6cd5b..48d4bddc7 100644 --- a/src/components/ExperienceSearch/ExperienceSearch.module.css +++ b/src/components/ExperienceSearch/ExperienceSearch.module.css @@ -1,100 +1,54 @@ -@value main-yellow, main-gray, gray-dark, gray-light from "../common/variables.module.css"; +@value main-yellow, main-gray, gray-dark, gray-light, border-gray from "common/variables.module.css"; .container { - display: table; - width: 100%; - border-collapse: collapse; - - aside, .content { - display: table-cell; - vertical-align: top; - } + display: flex; +} - aside { - width: 190px; - padding: 64px 0; +.aside { + flex: 0 0 196px; - .frontButton { - border-radius: 5px 0 0 5px; - } - .rearButton { - border-radius: 0 5px 5px 0; - } - .frontButton, .rearButton { - display: inline-block; - text-align: center; - width: 80px; - height: 35px; - line-height: 35px; - border: 1px solid main-yellow; - &.toggle { - background-color: main-yellow; - } - } - .splitter { - margin-top: 30px; - border-bottom: 1px solid #ddd; - } + @media (max-width: 850px) { + display: none; } +} - .content { - padding: 64px 0 64px 64px; - - .searchbar { - .condition, .search { - display: table-cell; - vertical-align: top; - } - .condition { - padding-top: 7px; - } - input[type=text] { - border: 0; - border-bottom: 1px solid black; - background-color: transparent; - font-size: 1.2em; - padding: 5px; - } - - .keywordGroup { - margin: 10px 0 20px 0; - - .keyword { - font-size: 0.9em; - line-height: 2.5em; - border: 1px dashed #aaa; - border-radius: 5px; - padding: 7px 13px; - margin-left: 10px; +.content { + flex: 1 1 auto; + margin-left: 64px; - &:first-child { - margin-left: 0; - } - &:hover { - cursor: pointer; - background-color: #f5f5f5; - } - } - } + @media (max-width: 850px) { + margin-left: 0; + } +} - svg { - margin-left: 15px; - width: 1.5em; - height: 1.5em; +.searchResult { + background-color: gray-light; + border: 1px solid #ccc; + font-weight: 700; + padding: 20px; +} - &:hover { - cursor: pointer; - } - } +.frontButton, .rearButton { + display: inline-block; + text-align: center; + width: 80px; + height: 35px; + line-height: 35px; + border: 1px solid main-yellow; + &.toggle { + background-color: main-yellow; + } +} - } +.frontButton { + border-radius: 5px 0 0 5px; +} - .info { - background-color: gray-light; - border: 1px solid #ccc; - font-weight: 700; - padding: 20px; - } - } +.rearButton { + border-radius: 0 5px 5px 0; +} +.splitter { + margin-bottom: 32px; + margin-top: 32px; } diff --git a/src/components/ExperienceSearch/Searchbar.js b/src/components/ExperienceSearch/Searchbar.js new file mode 100644 index 000000000..6e87b81fb --- /dev/null +++ b/src/components/ExperienceSearch/Searchbar.js @@ -0,0 +1,80 @@ +import React, { PropTypes } from 'react'; +import cn from 'classnames'; + +import Radio from 'common/form/Radio'; +import Magnifiner from 'common/icons/Magnifiner'; +import styles from './Searchbar.module.css'; + +const SearchBar = ({ + data, + fetchKeywords, + setKeyword, + handleKeyPress, + handleKeywordClick, + fetchExperiencesAndWorkings, + className, +}) => ( +
+
+ { + [ + { label: '公司', value: 'company' }, + { label: '職稱', value: 'job_title' }, + ].map(o => ( + + )) + } +
+
+ + +
+ { + (data.keywords || []).map(o => ( + + {o} + + )) + } +
+
+
+); +SearchBar.propTypes = { + className: PropTypes.string, + data: PropTypes.object.isRequired, + fetchKeywords: PropTypes.func.isRequired, + handleKeyPress: PropTypes.func.isRequired, + handleKeywordClick: PropTypes.func.isRequired, + setKeyword: PropTypes.func.isRequired, + fetchExperiencesAndWorkings: PropTypes.func.isRequired, +}; + +export default SearchBar; diff --git a/src/components/ExperienceSearch/Searchbar.module.css b/src/components/ExperienceSearch/Searchbar.module.css new file mode 100644 index 000000000..5f836f7b4 --- /dev/null +++ b/src/components/ExperienceSearch/Searchbar.module.css @@ -0,0 +1,80 @@ +@value main-yellow, main-gray, gray-dark, gray-light, border-gray from "common/variables.module.css"; + +.searchbar { + display: flex; + align-items: center; + + input[type=text] { + border-bottom: 1px solid black; + background-color: transparent; + font-size: 1.2em; + padding: 5px; + letter-spacing: 1px; + width: 70%; + + @media (max-width: 850px) { + width: calc(100% - 30px - 16px); + } + } + + @media (max-width: 550px) { + flex-direction: column; + align-items: flex-start; + } +} + +.searchbarLarge { + color: red; +} + +.condition { + flex: 0 0 200px; + margin-bottom: 16px; + + @media (max-width: 550px) { + flex-basis: 100%; + } +} + +.search { + flex: 1 1 auto; + + @media (max-width: 550px) { + width: 100%; + } +} + +.keywordGroup { + margin: 10px 0 20px 0; +} + +.keyword { + font-size: 0.9em; + line-height: 2.5em; + border: 1px dashed #aaa; + border-radius: 5px; + padding: 7px 13px; + margin-left: 10px; + + &:first-child { + margin-left: 0; + } + + &:hover { + cursor: pointer; + background-color: #f5f5f5; + } +} + +.searchBtn svg { + margin-left: 16px; + width: 30px; + height: 30px; + cursor: pointer; + transition-property: fill; + transition-duration: .3s; + + &:hover { + fill: main-gray; + } +} diff --git a/src/components/ExperienceSearch/index.js b/src/components/ExperienceSearch/index.js index e2e7018f5..86d046955 100644 --- a/src/components/ExperienceSearch/index.js +++ b/src/components/ExperienceSearch/index.js @@ -3,12 +3,13 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import Helmet from 'react-helmet'; import InfiniteScroll from 'react-infinite-scroller'; -import Radio from 'common/form/Radio'; import Checkbox from 'common/form/Checkbox'; import Loader from 'common/Loader'; +import { Section, Wrapper } from 'common/base'; // import Alert from 'common/Alert'; + import styles from './ExperienceSearch.module.css'; -import Search from '../images/search.svg'; +import Searchbar from './Searchbar'; import ExperienceBlock from './ExperienceBlock'; import WorkingHourBlock from './WorkingHourBlock'; import { fetchExperiences } from '../../actions/experienceSearch'; @@ -39,6 +40,7 @@ class ExperienceSearch extends Component { this.handleKeyPress = this.handleKeyPress.bind(this); this.handleKeywordClick = this.handleKeywordClick.bind(this); this.fetchExperiencesWithSort = this.fetchExperiencesWithSort.bind(this); + this.fetchExperiencesAndWorkings = this.fetchExperiencesAndWorkings.bind(this); } componentDidMount() { @@ -76,164 +78,119 @@ class ExperienceSearch extends Component { const data = experienceSearch.toJS(); return ( -
+
- {/* - { cmpAlert = c; }}> -

test

-
- */} -
- - -
-
-
+ + {/* + { cmpAlert = c; }}> +

test

+
+ */} +
+ + +
+ + + {data.loadingStatus === status.FETCHING && } + + {data.searchQuery && +
+ 找到 {data.experienceCount} 筆與 "{data.searchQuery}" 相關的資料 +
+ } +
+ + { + if (data.hasMore) { + fetchMoreExperiences(nextPage); + } + }} + loader={} + > { - [ - { label: '公司', value: 'company' }, - { label: '職稱', value: 'job_title' }, - ].map(o => ( - + (data.experiences || []).map(o => ( + data[o.type] && ( + + ) )) } -
-
- - { - // cmpAlert.show(); - const val = data.keyword; - this.fetchExperiencesAndWorkings(val); - }} - /> -
- { - (data.keywords || []).map(o => ( - - {o} - - )) - } -
-
-
+ - {data.loadingStatus === status.FETCHING && } - - {data.searchQuery && -
- 找到 {data.experienceCount} 筆與 "{data.searchQuery}" 相關的資料 -
- } -
- - { /* - (data.experiences || []).map(o => ( - data[o.type] && ( - - ) - )) - */ } - - { - if (data.hasMore) { - fetchMoreExperiences(nextPage); - } - }} - loader={} - > { - (data.experiences || []).map(o => ( - data[o.type] && ( - - ) + data.salary && (data.workings || []).map((o, i) => ( + )) } - - - { - data.salary && (data.workings || []).map((o, i) => ( - - )) - } +
-
-
+ +
); } } diff --git a/src/components/LaborRightsMenu/About.js b/src/components/LaborRightsMenu/About.js new file mode 100644 index 000000000..db586bcbc --- /dev/null +++ b/src/components/LaborRightsMenu/About.js @@ -0,0 +1,25 @@ +import React from 'react'; +import { Section, P } from 'common/base'; +import styles from './About.module.css'; + +const About = () => ( +
+ 勞動知識小教室 +

+ Goodjob 團隊看見勞工們的需要,自 2016 年底推出【勞動知識小教室】系列懶人包,將複雜的法律資訊轉換成易懂的圖文,讓勞工認識自己的權益,學會保護自己。內容涵蓋勞基法、性別工作平等法、就服法以及工會相關法令等勞工必備的權益資訊。 +

+ 內容皆為創用 CC 授權,歡迎分享、散佈,但需標明出處。 + cc +

+
+); + +export default About; diff --git a/src/components/LaborRightsMenu/About.module.css b/src/components/LaborRightsMenu/About.module.css new file mode 100644 index 000000000..91e2c3d91 --- /dev/null +++ b/src/components/LaborRightsMenu/About.module.css @@ -0,0 +1,18 @@ +@value main-yellow from "common/variables.module.css"; + +.wrapper { + background-color: #fff; + border: 1px solid main-yellow; + padding: 32px; + border-radius: 5px; +} + +.image { + width: 240px; + margin: 0 auto; +} + +.cc { + width: 90px; + margin-top: 8px; +} diff --git a/src/components/LaborRightsMenu/index.js b/src/components/LaborRightsMenu/index.js index 7cfdbaa67..a7d47abe0 100644 --- a/src/components/LaborRightsMenu/index.js +++ b/src/components/LaborRightsMenu/index.js @@ -14,6 +14,7 @@ import { } from '../../actions/laborRightsMenu'; import status from '../../constants/status'; import LaborRightsEntry from './LaborRightsEntry'; +import About from './About'; class LaborRightsMenu extends React.Component { static fetchData({ store }) { @@ -26,10 +27,7 @@ class LaborRightsMenu extends React.Component { render() { const title = '勞動知識小教室'; - const description = ` - GoodJob 工時薪資透明化團隊,看見勞工們的需要,自 2016 年底推出【勞動知識小教室】系列懶人包 - 將複雜的法律資訊轉換成易懂的圖文,讓勞工認識自己的權益,學會保護自己。內容涵蓋勞基法、性別工作平等法、 - 就服法以及工會相關法令等勞工必備的權益資訊。`; + const description = `${siteName},看見勞工們的需要,自 2016 年底推出【勞動知識小教室】系列懶人包,將複雜的法律資訊轉換成易懂的圖文,讓勞工認識自己的權益,學會保護自己。內容涵蓋勞基法、性別工作平等法、就服法以及工會相關法令等勞工必備的權益資訊。`; return (
@@ -65,6 +63,9 @@ class LaborRightsMenu extends React.Component {
} + + + ); } diff --git a/src/components/LaborRightsSingle/Body.js b/src/components/LaborRightsSingle/Body.js index 46e99f682..2dbb88d06 100644 --- a/src/components/LaborRightsSingle/Body.js +++ b/src/components/LaborRightsSingle/Body.js @@ -1,21 +1,22 @@ import React, { PropTypes } from 'react'; import cn from 'classnames'; +import { Section, Wrapper, Heading } from 'common/base'; import MarkdownParser from './MarkdownParser'; import styles from './Body.module.css'; const Body = ({ title, seoText, description, content }) => ( -
-

- {title} -

-
- {description} -
- - {seoText &&
- {seoText} -
} -
+
+ + {title} +
+ {description} +
+ + {seoText &&
+ {seoText} +
} +
+
); Body.propTypes = { diff --git a/src/components/LaborRightsSingle/Body.module.css b/src/components/LaborRightsSingle/Body.module.css index c3d829fd7..0baf2975b 100644 --- a/src/components/LaborRightsSingle/Body.module.css +++ b/src/components/LaborRightsSingle/Body.module.css @@ -1,19 +1,6 @@ @value PAGE_TOP, PAGE_TOP_S from "common/variables.module.css"; - -.body { - padding-top: PAGE_TOP; - @media (max-width: 550px) { - padding-top: PAGE_TOP_S; - } -} - -.heading { - - margin-bottom: 30px; -} - .description { - margin-bottom: 20px; + margin-bottom: 40px; } .seoText { diff --git a/src/components/LaborRightsSingle/CallToAction.js b/src/components/LaborRightsSingle/CallToAction.js index 289388520..51447153e 100644 --- a/src/components/LaborRightsSingle/CallToAction.js +++ b/src/components/LaborRightsSingle/CallToAction.js @@ -1,21 +1,22 @@ import React from 'react'; import cn from 'classnames'; +import { Section, Wrapper, Heading } from 'common/base'; import styles from './CallToAction.module.css'; const CallToAction = () => ( -
-
+
+
- workers + 留下你的資訊
-
+ 覺得很有用嗎?也留下你的資訊吧! -
- 留下資料 + + 留下資料
-
-
+ + ); export default CallToAction; diff --git a/src/components/LaborRightsSingle/CallToAction.module.css b/src/components/LaborRightsSingle/CallToAction.module.css index 9bde066ae..b7bab8592 100644 --- a/src/components/LaborRightsSingle/CallToAction.module.css +++ b/src/components/LaborRightsSingle/CallToAction.module.css @@ -1,11 +1,8 @@ .callToAction { - background-color: #ffffff; - padding-top: 64px; - padding-bottom: 64px; margin-top: 80px; + @media (max-width: 550px) { - padding-top: 30px; - padding-bottom: 30px; + flex-direction: 40px; } } @@ -13,6 +10,7 @@ display: flex; align-items: center; justify-content: center; + @media (max-width: 550px) { flex-direction: column; } @@ -21,19 +19,28 @@ .image { margin-right: 40px; flex: 0 0 30%; + @media (max-width: 550px) { flex: 1 1 auto; margin-right: 0; - margin-top: 20px; - order: 2; + margin-bottom: 20px; + order: 1; + } + + img { + max-width: 200px; + @media (max-width: 550px) { + max-width: 150px; + } } } .content { flex: 1 1 auto; + @media (max-width: 550px) { text-align: center; - order: 1; + order: 2; } } diff --git a/src/components/LandingPage/HomeBanner.js b/src/components/LandingPage/HomeBanner.js index c2f1e8244..5f0557977 100644 --- a/src/components/LandingPage/HomeBanner.js +++ b/src/components/LandingPage/HomeBanner.js @@ -1,20 +1,23 @@ import React from 'react'; +import cn from 'classnames'; import { Link } from 'react-router'; -import homeBanner from '../images/home-banner.png'; +import { Wrapper, Heading } from 'common/base'; import styles from './HomeBanner.module.css'; const HomeBanner = () => ( -
-
-
- home-banner +
+ +
+ 求職市場透明化
-
-

工時薪資透明化運動

-

分享你的真實工時、薪資資訊,讓我們一起改善工作資訊不透明的現況

- 了解更多﹥﹥ +
+

求職市場透明化

+ + 分享你的真實工時、薪資資訊,讓我們一起改善工作資訊不透明的現況 + + 立即參與
-
+
); diff --git a/src/components/LandingPage/HomeBanner.module.css b/src/components/LandingPage/HomeBanner.module.css index 16f8ae78c..23d718972 100644 --- a/src/components/LandingPage/HomeBanner.module.css +++ b/src/components/LandingPage/HomeBanner.module.css @@ -1,62 +1,57 @@ @value main-yellow from '../common/variables.module.css'; -.home_banner { - height: 500px; - padding-top: 67px; - align-items: center; - background-color: main-yellow; - - @media (max-width: 1280px) { - height: 400px; - } +.banner { + background-color: #222; + background-image: url("https://s3-ap-northeast-1.amazonaws.com/goodjob.life/www/black-bg.jpg"); + background-repeat: repeat; > div { display: flex; - } -} -.home_banner_img { - > img { - width: 500px; - margin-left: 30px; - - @media (max-width: 1280px) { - width: 400px; - margin-top: 30px; - margin-left: 50; + @media (max-width: 850px) { + flex-direction: column; } } +} - @media (max-width: 1280px) { - flex: 1; +.image { + order: 2; + flex: 1 1 auto; + align-self: flex-end; + text-align: right; + + img { + display: inline-block; + max-width: 527px; + @media (max-width: 850px) { + max-width: 300px; + } } } -.home_banner_text { - display: flex; - flex-direction: column; - justify-content: center; +.content { + color: #fff; + flex: 0 0 50%; + padding-top: 64px; + padding-bottom: 64px; - > h1 { - margin-bottom: 30px; - font-size: 3em; - font-weight: 500; - letter-spacing: 0.02em; + @media (max-width: 850px) { + padding-top: 40px; + padding-bottom: 0; } +} - > h3 { - margin-bottom: 20px; - font-size: 1.2em; - line-height: 1.4em; - font-weight: 500; - } +.heading { + font-size: 2.75em; + letter-spacing: 2px; + margin-bottom: 20px; + font-weight: 300; - > a { - text-decoration: underline; + @media (max-width: 850px) { + font-size: 2.3em; } +} - @media (max-width: 1280px) { - height: 264px; - flex: 1; - } +.subheading { + margin-bottom: 24px; } diff --git a/src/components/LandingPage/LandingPage.module.css b/src/components/LandingPage/LandingPage.module.css index e69de29bb..9deecdfca 100644 --- a/src/components/LandingPage/LandingPage.module.css +++ b/src/components/LandingPage/LandingPage.module.css @@ -0,0 +1,38 @@ +.columns { + display: flex; + flex-wrap: wrap; + + @media (max-width: 550px) { + flex-direction: column; + } +} + +.columnItem { + flex: 0 0 calc((100% - gutter * 2) / 3); + margin-right: gutter; + margin-bottom: 64px; + + &:nth-child(3n) { + margin-right: 0; + } + + @media (max-width: 850px) { + flex: 0 0 calc((100% - gutter) / 2); + + &:nth-child(3n) { + margin-right: gutter; + } + + &:nth-child(2n) { + margin-right: 0; + } + } + + @media (max-width: 550px) { + flex: 1 1 auto; + margin-right: 0; + &:nth-child(3n) { + margin-right: 0; + } + } +} diff --git a/src/components/LandingPage/index.js b/src/components/LandingPage/index.js index 0620f8332..08759e819 100644 --- a/src/components/LandingPage/index.js +++ b/src/components/LandingPage/index.js @@ -1,22 +1,76 @@ -import React from 'react'; +import React, { Component, PropTypes } from 'react'; +import { Link } from 'react-router'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import cn from 'classnames'; import Helmet from 'react-helmet'; import { Section, Wrapper, Heading } from 'common/base'; import ShareExpSection from 'common/ShareExpSection'; +import columnStyle from 'common/Columns.module.css'; +import ExperienceBlock from '../ExperienceSearch/ExperienceBlock'; +import { fetchExperiences } from '../../actions/experienceSearch'; import HomeBanner from './HomeBanner'; -const LandingPage = () => ( -
- - -
- - 勞動知識小教室 - -
- -
-); +class LandingPage extends Component { + static fetchData({ store: { dispatch } }) { + return dispatch(fetchExperiences('sort', '')); + } + static propTypes = { + fetchExperiences: PropTypes.func.isRequired, + experienceSearch: ImmutablePropTypes.map.isRequired, + } + componentDidMount() { + this.props.fetchExperiences('sort', ''); + } + render() { + const expDatas = this.props.experienceSearch.toJS().experiences || []; + expDatas.sort((a, b) => { + if (a.like_count < b.like_count) { + return 1; + } + if (a.like_count > b.like_count) { + return -1; + } + return 0; + }); + return ( +
+ + +
+ + 熱門分享 +
+ { + expDatas.slice(0, 3).map(data => ( +
+ +
+ )) + } +
+
+ + 看更多 + +
+
+
+
+ + 勞動知識小教室 + +
+ + 看更多 + +
+
+ +
+ ); + } +} export default LandingPage; diff --git a/src/components/Layout/App.module.css b/src/components/Layout/App.module.css index 957b83195..0de91d667 100644 --- a/src/components/Layout/App.module.css +++ b/src/components/Layout/App.module.css @@ -1,7 +1,7 @@ @import "../common/reset.module.css"; @import "../common/global.module.css"; -@value primary-font, white-light, NAV_HEIGHT, NAV_MOBILE_HEIGHT from "../common/variables.module.css"; +@value primary-font, white-light, border-gray, NAV_HEIGHT, NAV_MOBILE_HEIGHT from "common/variables.module.css"; .App { @@ -19,8 +19,8 @@ /* gloabl style start */ body, html { font-family: primary-font; - font-weight: 300; - color: #111; + font-weight: 400; + color: #444; font-size: 16px; -webkit-tap-highlight-color: rgba(0,0,0,.2); overflow-x: hidden; @@ -41,13 +41,10 @@ svg { vertical-align: middle; } -p { - font-size: 1.13em; - line-height: 1.5em; - color: #333; - @media (max-width: 850px) { - font-size: 1em; - } +hr { + border : 0; + height : 1px; + background-color: border-gray; } /* global style end */ diff --git a/src/components/Layout/Footer/Footer.module.css b/src/components/Layout/Footer/Footer.module.css index 26fa13fd7..6a17371e7 100644 --- a/src/components/Layout/Footer/Footer.module.css +++ b/src/components/Layout/Footer/Footer.module.css @@ -13,8 +13,10 @@ } .col1 { - flex: 0 0 70%; + flex: 1 1 auto; display: flex; + justify-content: center; + align-items: space-between; @media (max-width: 850px) { flex: 1 1 auto; } @@ -24,7 +26,8 @@ } .col2 { - flex: 0 0 30%; + flex: 0 0 140px; + @media (max-width: 850px) { flex: 1 1 auto; } @@ -40,10 +43,28 @@ } } +.g0v { + flex: 0 0 120px; + display: flex; + justify-content: flex-start; + align-items: center; + + @media (max-width: 550px) { + flex: 1 1 auto; + margin-top: 10px; + margin-bottom: 10px; + } + + img { + width: 120px; + } +} + .content { flex: 1 1 auto; font-size: .85em; line-height: 1.4em; + @media (max-width: 550px) { flex: 1 1 auto; } diff --git a/src/components/Layout/Footer/index.js b/src/components/Layout/Footer/index.js index a7eefd998..ad2fadc4e 100644 --- a/src/components/Layout/Footer/index.js +++ b/src/components/Layout/Footer/index.js @@ -17,6 +17,11 @@ const Footer = () => ( 與隱私權政策

+
+ + g0v + +
diff --git a/src/components/Layout/Header/Header.module.css b/src/components/Layout/Header/Header.module.css index 1edc55acd..e1a7725d5 100644 --- a/src/components/Layout/Header/Header.module.css +++ b/src/components/Layout/Header/Header.module.css @@ -1,4 +1,4 @@ -@value main-black, NAV_HEIGHT, NAV_MOBILE_HEIGHT from "common/variables.module.css"; +@value main-yellow, main-black, NAV_HEIGHT, NAV_MOBILE_HEIGHT from "common/variables.module.css"; .header { position: fixed; @@ -9,6 +9,7 @@ background-color: main-black; height: NAV_HEIGHT; box-shadow: 0 0 8px rgba(0,0,0,.15); + font-weight: 300; @media (max-width: 850px) { height: NAV_MOBILE_HEIGHT; @@ -103,7 +104,7 @@ @media (min-width: 851px) { &:hover { - background-color: rgba(255,255,255, .1); + background-color: rgba(255,255,255, .2); } } @@ -112,17 +113,48 @@ } } +.loginBtn { + color: #fff; + height: 40px; + align-items: center; + justify-content: center; + display: flex; + margin-left: 40px; + transition-property: color; + transition-duration: .3s; + text-transform: lowercase; + + svg { + width: 20px; + height: 20px; + fill: #fff; + margin-right: 8px; + } + + @media (min-width: 851px) { + &:hover { + color: main-yellow; + } + } +} + +.disableBtn { + pointer-events: none; +} + .mHeaderButton { @media (min-width: 851px) { display: none; } + position: absolute; top: 0; right: 0; - z-index: 3; + z-index: 9; display: block; transform: translate(0, 0); padding: 9px 19px 0 19px; + &::before, &::after, span { background: #fff; border-radius: 3px; diff --git a/src/components/Layout/Header/index.js b/src/components/Layout/Header/index.js index 59ada242d..89999c82d 100644 --- a/src/components/Layout/Header/index.js +++ b/src/components/Layout/Header/index.js @@ -76,22 +76,21 @@ class Header extends React.Component { >
+ + 留下資料 + { this.props.auth.getIn(['user', 'name']) === null && -
-
登入
-
+ } { this.props.auth.getIn(['user', 'name']) !== null && -
-
{this.props.auth.getIn(['user', 'name'])}
+
+ {this.props.auth.getIn(['user', 'name'])}
} - - - 留下資料 -
diff --git a/src/components/common/base/Heading.js b/src/components/common/base/Heading.js index 51761e545..9250532f0 100644 --- a/src/components/common/base/Heading.js +++ b/src/components/common/base/Heading.js @@ -4,10 +4,11 @@ import styles from './Heading.module.css'; const sizeOptions = ['l', 'm', 'sl', 'sm']; -const Heading = ({ Tag, size, bold, center, marginBottom, children, style, className }) => ( +const Heading = ({ Tag, size, bold, light, center, marginBottom, children, style, className }) => ( ( +const Section = ({ Tag, pageTop, bg, padding, paddingTop, paddingBottom, center, children, className }) => ( @@ -18,6 +21,9 @@ Section.propTypes = { children: PropTypes.node, pageTop: PropTypes.bool, padding: PropTypes.bool, + paddingTop: PropTypes.bool, + paddingBottom: PropTypes.bool, + center: PropTypes.bool, bg: PropTypes.string, className: PropTypes.string, }; diff --git a/src/components/common/base/Section.module.css b/src/components/common/base/Section.module.css index fe18c83ce..9d3e5b243 100644 --- a/src/components/common/base/Section.module.css +++ b/src/components/common/base/Section.module.css @@ -16,3 +16,24 @@ padding-bottom: 48px; } } + +.paddingBottom { + padding-bottom: 64px; + + @media (max-width: 550px) { + padding-bottom: 48px; + } +} + +.paddingTop { + padding-top: 64px; + + @media (max-width: 550px) { + padding-top: 48px; + } +} + +.center { + display: flex; + justify-content: center; +} diff --git a/src/components/common/base/Wrapper.module.css b/src/components/common/base/Wrapper.module.css index e9a1912fc..24a4ef884 100644 --- a/src/components/common/base/Wrapper.module.css +++ b/src/components/common/base/Wrapper.module.css @@ -1,4 +1,4 @@ -@value PAGE_TOP, PAGE_TOP_S, inner-wrap-l, inner-wrap-m, inner-wrap-m-s, page-gutter, page-gutter-s from "common/variables.module.css"; +@value PAGE_TOP, PAGE_TOP_S, inner-wrap-l, inner-wrap-m, inner-wrap-s, inner-wrap-m-s, page-gutter, page-gutter-s from "common/variables.module.css"; .l { width: 100%; diff --git a/src/components/common/form/Checkbox.module.css b/src/components/common/form/Checkbox.module.css index c695c85df..6bd2c0635 100644 --- a/src/components/common/form/Checkbox.module.css +++ b/src/components/common/form/Checkbox.module.css @@ -1,4 +1,4 @@ -@value main-yellow, main-gray from "../variables.module.css"; +@value main-yellow, main-gray, border-gray, main-black from "common/variables.module.css"; .formGroup { position: relative; @@ -11,15 +11,18 @@ display: inline-block; align-items: center; transition: color .3s; + .checkboxInput { position: relative; display: inline-block; vertical-align: middle; width: 20px; height: 20px; - border: 1px solid #000; + border: 1px solid main-gray; + border-radius: 3px; margin-right: 10px; - transition: all .3s; + transition-property: color, background-color, border; + transition-duration: .3s; cursor: pointer; } .checkboxText { @@ -27,7 +30,7 @@ display: inline-block; vertical-align: middle; font-size: 1em; - font-weight: 400; + letter-spacing: 1px; cursor: pointer; } } @@ -50,21 +53,22 @@ .checkboxInput:before { content: '✓'; - //transform: rotate(15deg); transform-origin: 0% 100%; width: 6px; height: 12px; - //border-color: #fff; transform: translate3d(-.1em,-.4em,0) rotate(15deg); } } &.disabled { - pointer-events: none; + cursor: not-allowed; + input[type="checkbox"] + label { color: main-gray; + pointer-events: none; + .checkboxInput { - border: 1px solid main-gray; + border: 1px solid border-gray; } } } diff --git a/src/components/common/form/Radio.module.css b/src/components/common/form/Radio.module.css index cf8a360da..c00a05f7b 100644 --- a/src/components/common/form/Radio.module.css +++ b/src/components/common/form/Radio.module.css @@ -20,11 +20,7 @@ position: relative; z-index: 1; cursor: pointer; - /*@media (min-width: $above-desktop) { - &:hover { - color: $gray-dark; - } - }*/ + .radioInput { display: inline-block; vertical-align: middle; @@ -39,10 +35,10 @@ width: 8px; height: 8px; border-radius: 100%; - background-color: main-yellow; + background-color: #000; top: 4px; left: 4px; - /* transition: transform .3s; */ + transition: transform .3s; transform: scale(0); } } @@ -59,8 +55,9 @@ input[type="radio"]:checked + .radioCircle { .radioInput { - border: 1px solid main-yellow; - &:before { + border: 1px solid #000; + + &::before { transform: scale(1); } } diff --git a/src/components/common/form/TextInput.module.css b/src/components/common/form/TextInput.module.css index 758962f39..fa60f7876 100644 --- a/src/components/common/form/TextInput.module.css +++ b/src/components/common/form/TextInput.module.css @@ -1,6 +1,4 @@ -@value main-yellow from "../variables.module.css"; -@value border-gray from "../variables.module.css"; -@value warning-red from "../variables.module.css"; +@value main-yellow, border-gray, main-gray, warning-red from "../variables.module.css"; .input { width: 100%; @@ -10,10 +8,6 @@ &:focus{ border-color: main-yellow; } - - &::placeholder { - color: #C0C0C0; - } } .warning { @@ -36,3 +30,13 @@ .isWarning { display: inherit; } + +::-webkit-input-placeholder { + color: main-gray; +} +::-moz-placeholder { + color: main-gray; +} +:-ms-input-placeholder { + color: main-gray; +} diff --git a/src/components/common/global.module.css b/src/components/common/global.module.css index 167288938..cc2e85b8a 100644 --- a/src/components/common/global.module.css +++ b/src/components/common/global.module.css @@ -147,6 +147,19 @@ @media (min-width: 851px) { &:hover { background-color: main-yellow; + color: main-black; + } + } + } + + .buttonWhiteLine { + border: 1px solid #fff; + color: #fff; + @media (min-width: 851px) { + &:hover { + background-color: main-yellow; + color: main-black; + border-color: main-yellow; } } } diff --git a/src/components/common/icons/Magnifiner.js b/src/components/common/icons/Magnifiner.js new file mode 100644 index 000000000..caccbc356 --- /dev/null +++ b/src/components/common/icons/Magnifiner.js @@ -0,0 +1,11 @@ +import React from 'react'; + +/* eslint-disable */ +const Magnifiner = (props) => ( + + + +); +/* eslint-enable */ + +export default Magnifiner; diff --git a/src/components/common/reset.module.css b/src/components/common/reset.module.css index af0a474fe..cd08b8c30 100644 --- a/src/components/common/reset.module.css +++ b/src/components/common/reset.module.css @@ -18,11 +18,13 @@ textarea { text-align: left; font-size: inherit; font-family: inherit; + font-weight: inherit; color: inherit; box-sizing: border-box; outline: 0; box-shadow: none; background-clip: padding-box; + border: 0; border-radius: 0; } button { diff --git a/src/components/common/variables.module.css b/src/components/common/variables.module.css index 741c231fb..a553bb6bc 100644 --- a/src/components/common/variables.module.css +++ b/src/components/common/variables.module.css @@ -5,7 +5,7 @@ * ------------------------------------ */ @value inner-wrap-l: 1264px; @value inner-wrap-m: 964px; -@value inner-wrap-s: 630px; +@value inner-wrap-s: 764px; @value page-gutter: 40px; @value page-gutter-s: 15px; @@ -31,7 +31,7 @@ @value white-light: #f9f9f9; @value warning-red: #d50000; -@value border-gray: #cdcdcd; +@value border-gray: #ddd; @value link-blue: #325bbd; @@ -39,4 +39,4 @@ /* ------------------------------------ * Font * ------------------------------------ */ -@value primary-font: "Helvetica Neue", "Helvetica", "Arial", "PingFang TC", "微軟正黑體", "Microsoft JhengHei", sans-serif; +@value primary-font: "PingFang TC", "Helvetica Neue", Helvetica, Arial, "微軟正黑體", "Microsoft JhengHei", sans-serif; diff --git a/src/containers/LandingPage/index.js b/src/containers/LandingPage/index.js index eb1f74645..fda524aa2 100644 --- a/src/containers/LandingPage/index.js +++ b/src/containers/LandingPage/index.js @@ -1,9 +1,14 @@ +import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import LandingPage from '../../components/LandingPage'; +import * as ExperienceSearchActions from '../../actions/experienceSearch'; +const mapStateToProps = state => ({ + experienceSearch: state.experienceSearch, +}); -const mapStateToProps = () => ({}); +const mapDispatchToProps = dispatch => + bindActionCreators(ExperienceSearchActions, dispatch); - -export default connect(mapStateToProps)(LandingPage); +export default connect(mapStateToProps, mapDispatchToProps)(LandingPage);