解鎖範圍:全站 {formatCommaSeparatedNumber(dataCount || 0)}{' '}
- 筆面試經驗、工作心得、薪資工時資料,及期間內新增的資料
+ 筆面試經驗、評價、薪資工時資料,及期間內新增的資料
使用期間:現在 ~ {format(endDateTime || new Date(), 'yyyy-MM-dd hh:mm a')}
diff --git a/src/components/CompanyAndJobTitle/InterviewExperiences/InterviewExperiences.module.css b/src/components/CompanyAndJobTitle/InterviewExperiences/InterviewExperiences.module.css
index 9f71bbad9..e009f03cd 100644
--- a/src/components/CompanyAndJobTitle/InterviewExperiences/InterviewExperiences.module.css
+++ b/src/components/CompanyAndJobTitle/InterviewExperiences/InterviewExperiences.module.css
@@ -37,7 +37,8 @@
> .salaryRatingWrapper {
display: flex;
- justify-content: space-between;
+ flex-wrap: wrap;
+ gap: 1rem;
margin: 12px 0;
@media (min-width: above-small) {
diff --git a/src/components/CompanyAndJobTitle/Overview/Helmet.js b/src/components/CompanyAndJobTitle/Overview/Helmet.js
index 9e3820594..82c8e4906 100644
--- a/src/components/CompanyAndJobTitle/Overview/Helmet.js
+++ b/src/components/CompanyAndJobTitle/Overview/Helmet.js
@@ -17,7 +17,7 @@ const formatDataCount = (dataCount, unit, defaultStr) => {
};
const formatKeyword = name =>
- `${name}薪水, ${name}加班情況, ${name}工時, ${name}工作心得, ${name}面試心得`;
+ `${name}薪水, ${name}加班情況, ${name}工時, ${name}評價, ${name}面試心得`;
const CompanyOverviewHelmet = ({
companyName,
@@ -36,7 +36,7 @@ const CompanyOverviewHelmet = ({
'',
);
const workExperiencesStr = formatDataCount(workExperiencesCount, '篇', '');
- const description = `查看由${companyName}內部員工分享的${salaryWorkTimesStr}薪水及加班數據、${workExperiencesStr}工作心得,以及由面試者分享的${interviewExperiencesStr}面試經驗。`;
+ const description = `查看由${companyName}內部員工分享的${salaryWorkTimesStr}薪水及加班數據、${workExperiencesStr}評價,以及由面試者分享的${interviewExperiencesStr}面試經驗。`;
const path = generatePath('/companies/:companyName', { companyName });
const url = formatCanonicalPath(path);
@@ -80,7 +80,7 @@ const JobTitleOverviewHelmet = ({
'',
);
const workExperiencesStr = formatDataCount(workExperiencesCount, '篇', '');
- const description = `查看由${jobTitle}分享的${salaryWorkTimesStr}薪水及加班數據、${workExperiencesStr}工作心得,以及由面試者分享的${interviewExperiencesStr}面試經驗。`;
+ const description = `查看由${jobTitle}分享的${salaryWorkTimesStr}薪水及加班數據、${workExperiencesStr}評價,以及由面試者分享的${interviewExperiencesStr}面試經驗。`;
const path = generatePath('/job-titles/:jobTitle', { jobTitle });
const url = formatCanonicalPath(path);
diff --git a/src/components/CompanyAndJobTitle/Overview/Overview.js b/src/components/CompanyAndJobTitle/Overview/Overview.js
index 217d0695e..cdf9bbbd2 100644
--- a/src/components/CompanyAndJobTitle/Overview/Overview.js
+++ b/src/components/CompanyAndJobTitle/Overview/Overview.js
@@ -53,8 +53,8 @@ const Overview = ({
/>
>`}
+ title="評價"
+ linkText={`查看 ${workExperiencesCount} 篇完整的評價 >>`}
linkTo={generateTabURL({
pageType,
pageName,
diff --git a/src/components/CompanyAndJobTitle/WorkExperiences/ExperienceEntry.js b/src/components/CompanyAndJobTitle/WorkExperiences/ExperienceEntry.js
index 01013a440..ee9acf36d 100644
--- a/src/components/CompanyAndJobTitle/WorkExperiences/ExperienceEntry.js
+++ b/src/components/CompanyAndJobTitle/WorkExperiences/ExperienceEntry.js
@@ -12,6 +12,7 @@ import Bad from 'common/icons/Bad';
import styles from './WorkExperiences.module.css';
import { formatSalary, formatSalaryRange } from 'common/formatter';
import { formatCreatedAt, formatWeekWorkTime } from './helper';
+import OverallRating from 'common/OverallRating';
const createLinkTo = ({ pageType, id }) => ({
pathname: `/experiences/${id}`,
@@ -31,6 +32,7 @@ const ExperienceEntry = ({
week_work_time: weekWorkTime,
salary,
recommend_to_others: recommendToOthers,
+ averageSectionRating,
},
size,
canView,
@@ -40,37 +42,49 @@ const ExperienceEntry = ({
- 工作經驗 · {formatCreatedAt(createdAt)}
+ 評價 · {formatCreatedAt(createdAt)}
- {weekWorkTime && canView && (
-
-
- {formatWeekWorkTime(weekWorkTime)}
-
- )}
- {salary && (
-
- {canView ? (
-
-
- {formatSalary(salary)}
-
- ) : (
-
-
- {formatSalaryRange(salary)}
-
- )}
-
- )}
-
- {recommendToOthers === 'yes' ?
:
}
- {recommendToOthers === 'yes' ? '推' : '不推'}
+
+ {weekWorkTime && canView && (
+
+
+ {formatWeekWorkTime(weekWorkTime)}
+
+ )}
+ {salary && (
+
+ {canView ? (
+
+
+ {formatSalary(salary)}
+
+ ) : (
+
+
+ {formatSalaryRange(salary)}
+
+ )}
+
+ )}
+
+ {averageSectionRating ? (
+
+
+
+ ) : (
+
+ {recommendToOthers === 'yes' ? : }
+ {recommendToOthers === 'yes' ? '推' : '不推'}
+
+ )}
@@ -103,6 +117,7 @@ const ExperienceEntry = ({
ExperienceEntry.propTypes = {
canView: PropTypes.bool.isRequired,
data: PropTypes.shape({
+ averageSectionRating: PropTypes.number,
created_at: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
job_title: PropTypes.shape({ name: PropTypes.string.isRequired })
diff --git a/src/components/CompanyAndJobTitle/WorkExperiences/Helmet.js b/src/components/CompanyAndJobTitle/WorkExperiences/Helmet.js
index ed7b9ba72..2311a25e3 100644
--- a/src/components/CompanyAndJobTitle/WorkExperiences/Helmet.js
+++ b/src/components/CompanyAndJobTitle/WorkExperiences/Helmet.js
@@ -9,12 +9,12 @@ import { pageType as PAGE_TYPE } from 'constants/companyJobTitle';
const CompanyWorkExperienceHelmet = ({ companyName, page, totalCount }) => {
// title
- const title = `${companyName} 工作心得列表 - 第${page}頁`;
+ const title = `${companyName} 評價列表 - 第${page}頁`;
// description
- let description = `目前還沒有${companyName}的工作心得。分享你的工作心得,一起讓職場更透明!`;
+ let description = `目前還沒有${companyName}的評價。分享你的評價,一起讓職場更透明!`;
if (totalCount > 0) {
- description = `查看${totalCount}篇${companyName}工作心得`;
+ description = `查看${totalCount}篇${companyName}評價`;
}
// canonical url
@@ -35,7 +35,7 @@ const CompanyWorkExperienceHelmet = ({ companyName, page, totalCount }) => {
@@ -51,12 +51,12 @@ CompanyWorkExperienceHelmet.propTypes = {
const JobTitleWorkExperienceHelmet = ({ jobTitle, page, totalCount }) => {
// title
- const title = `${jobTitle} 工作心得列表 - 第${page}頁`;
+ const title = `${jobTitle} 評價列表 - 第${page}頁`;
// description
- let description = `目前還沒有${jobTitle}的工作心得。分享你的工作心得,一起讓職場更透明!`;
+ let description = `目前還沒有${jobTitle}的評價。分享你的評價,一起讓職場更透明!`;
if (totalCount > 0) {
- description = `查看${totalCount}篇${jobTitle}工作心得`;
+ description = `查看${totalCount}篇${jobTitle}評價`;
}
// canonical url
@@ -77,7 +77,7 @@ const JobTitleWorkExperienceHelmet = ({ jobTitle, page, totalCount }) => {
diff --git a/src/components/CompanyAndJobTitle/WorkExperiences/WorkExperiences.module.css b/src/components/CompanyAndJobTitle/WorkExperiences/WorkExperiences.module.css
index 9c1249823..5079f4813 100644
--- a/src/components/CompanyAndJobTitle/WorkExperiences/WorkExperiences.module.css
+++ b/src/components/CompanyAndJobTitle/WorkExperiences/WorkExperiences.module.css
@@ -42,13 +42,8 @@
> .salaryRecommendWrapper {
display: flex;
- justify-content: space-between;
margin: 12px 0;
-
- @media (min-width: above-small) {
- margin: 0;
- justify-content: flex-start;
- }
+ flex-direction: column;
.weekWorkTime,
.salary,
@@ -57,12 +52,6 @@
align-items: center;
font-size: 15px;
color: #424242;
- }
-
- .salary,
- .weekWorkTime,
- .recommendToOthers {
- margin-left: 35px;
svg {
margin-right: 7px;
@@ -77,6 +66,22 @@
color: #ed0d5e;
}
}
+
+ .rowWrapper {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1rem;
+ justify-content: flex-start;
+ }
+
+ @media (min-width: above-small) {
+ margin: 0;
+ justify-content: flex-start;
+
+ .rowWrapper {
+ gap: 2.5rem;
+ }
+ }
}
}
@@ -152,3 +157,7 @@
}
}
}
+
+.overallRatingWrapper {
+ margin: 0;
+}
diff --git a/src/components/ExperienceDetail/Article/ArticleInfo.js b/src/components/ExperienceDetail/Article/ArticleInfo.js
index 33a03dbe0..01d10939e 100644
--- a/src/components/ExperienceDetail/Article/ArticleInfo.js
+++ b/src/components/ExperienceDetail/Article/ArticleInfo.js
@@ -3,8 +3,6 @@ import PropTypes from 'prop-types';
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
import faLock from '@fortawesome/fontawesome-free-solid/faLock';
import { formatSalary, formatSalaryRange } from 'common/formatter';
-import Good from 'common/icons/Good';
-import Bad from 'common/icons/Bad';
import styles from './Article.module.css';
import InfoBlock from './InfoBlock';
import RateButtons from './RateButtons';
@@ -13,6 +11,7 @@ import {
generatePageURL,
} from 'constants/companyJobTitle';
import { originalCompanyNameSelector } from '../experienceSelector';
+import RatingInfo from './RatingInfo';
const formatDate = date => `${date.getFullYear()} 年 ${date.getMonth() + 1} 月`;
const formatExperienceInYear = year => {
@@ -51,7 +50,7 @@ const InterviewInfoBlocks = ({ experience, hideContent }) => {
{experience.job_title.name}
{expInYearText !== null ? (
-
{expInYearText}
+
{expInYearText}
) : null}
{experience.education ? (
{experience.education}
@@ -153,7 +152,7 @@ const WorkInfoBlocks = ({ experience, hideContent }) => {
) : null}
{expInYearText ? (
-
{expInYearText}
+
{expInYearText}
) : null}
{experience.education ? (
{experience.education}
@@ -173,25 +172,17 @@ const WorkInfoBlocks = ({ experience, hideContent }) => {
)}
) : null}
- {experience.recommend_to_others ? (
-
- {experience.recommend_to_others === 'yes' ? (
-
- 推
-
- ) : (
-
- 不推
-
- )}
-
- ) : null}
+
);
};
WorkInfoBlocks.propTypes = {
experience: PropTypes.shape({
+ averageSectionRating: PropTypes.number,
company: PropTypes.shape({
name: PropTypes.string,
}),
diff --git a/src/components/ExperienceDetail/Article/InfoBlock.js b/src/components/ExperienceDetail/Article/InfoBlock.js
index 95ea3520d..325d317dd 100644
--- a/src/components/ExperienceDetail/Article/InfoBlock.js
+++ b/src/components/ExperienceDetail/Article/InfoBlock.js
@@ -1,15 +1,16 @@
import React from 'react';
import { Link } from 'react-router-dom';
+import cn from 'classnames';
import PropTypes from 'prop-types';
import { P } from 'common/base';
import styles from './InfoBlock.module.css';
-const InfoBlock = ({ label, to, children }) => (
-
+const InfoBlock = ({ label, to, children, noMargin }) => (
+
{label}:
-
+
{to ? {children} : children}
@@ -18,6 +19,7 @@ const InfoBlock = ({ label, to, children }) => (
InfoBlock.propTypes = {
children: PropTypes.node,
label: PropTypes.string.isRequired,
+ noMargin: PropTypes.bool,
to: PropTypes.string,
};
diff --git a/src/components/ExperienceDetail/Article/InfoBlock.module.css b/src/components/ExperienceDetail/Article/InfoBlock.module.css
index de129e55b..388a57bc8 100644
--- a/src/components/ExperienceDetail/Article/InfoBlock.module.css
+++ b/src/components/ExperienceDetail/Article/InfoBlock.module.css
@@ -1,8 +1,9 @@
-@value gray-dark from "../../common/variables.module.css";
+@value above-mobile, gray-dark from "../../common/variables.module.css";
.block {
display: flex;
flex-wrap: wrap;
+ align-items: center;
&:not(:last-child) {
margin-bottom: 20px;
}
@@ -29,3 +30,9 @@
}
}
}
+
+.content.noMargin {
+ @media (max-width: above-mobile) {
+ margin-left: 0px;
+ }
+}
diff --git a/src/components/ExperienceDetail/Article/RatingInfo.js b/src/components/ExperienceDetail/Article/RatingInfo.js
new file mode 100644
index 000000000..ef6dbc1ff
--- /dev/null
+++ b/src/components/ExperienceDetail/Article/RatingInfo.js
@@ -0,0 +1,52 @@
+import React from 'react';
+import Good from 'common/icons/Good';
+import Bad from 'common/icons/Bad';
+import styles from './Article.module.css';
+import InfoBlock from './InfoBlock';
+import OverallRating from 'common/OverallRating';
+import PropTypes from 'prop-types';
+
+const RecommendationIcon = ({ recommend }) => (
+
+ {recommend === 'yes' ? (
+ <>
+ 推
+ >
+ ) : (
+ <>
+ 不推
+ >
+ )}
+
+);
+
+RecommendationIcon.propTypes = {
+ recommend: PropTypes.string.isRequired,
+};
+
+const RatingInfo = ({ rating, recommend }) => {
+ if (rating > 0) {
+ return (
+
+
+
+ );
+ }
+
+ if (recommend) {
+ return (
+
+
+
+ );
+ }
+
+ return null;
+};
+
+RatingInfo.propTypes = {
+ rating: PropTypes.number,
+ recommend: PropTypes.string,
+};
+
+export default RatingInfo;
diff --git a/src/components/ExperienceDetail/Article/SectionBlock.js b/src/components/ExperienceDetail/Article/SectionBlock.js
index ccd1a82aa..caaadcd0b 100644
--- a/src/components/ExperienceDetail/Article/SectionBlock.js
+++ b/src/components/ExperienceDetail/Article/SectionBlock.js
@@ -2,12 +2,14 @@ import React from 'react';
import PropTypes from 'prop-types';
import { P } from 'common/base';
import styles from './SectionBlock.module.css';
+import OverallRating from 'common/OverallRating';
-const SectionBlock = ({ subtitle, content }) => (
+const SectionBlock = ({ subtitle, content, rating }) => (
{subtitle && (
- {subtitle}
+
{subtitle}
+ {rating ? : null}
)}
@@ -18,6 +20,7 @@ const SectionBlock = ({ subtitle, content }) => (
SectionBlock.propTypes = {
content: PropTypes.string.isRequired,
+ rating: PropTypes.number,
subtitle: PropTypes.string,
};
diff --git a/src/components/ExperienceDetail/Article/SectionBlock.module.css b/src/components/ExperienceDetail/Article/SectionBlock.module.css
index eb073c740..d5743ce85 100644
--- a/src/components/ExperienceDetail/Article/SectionBlock.module.css
+++ b/src/components/ExperienceDetail/Article/SectionBlock.module.css
@@ -1,5 +1,9 @@
+@value below-mobile from "../../common/variables.module.css";
+
.heading {
margin-bottom: 8px;
+ display: flex;
+ gap: 1rem;
}
.content {
@@ -7,3 +11,9 @@
white-space: pre-line;
word-break: break-word;
}
+
+@media (max-width: below-mobile) {
+ .heading {
+ flex-direction: column;
+ }
+}
diff --git a/src/components/ExperienceDetail/Article/index.js b/src/components/ExperienceDetail/Article/index.js
index 41f866ee0..d025c2b81 100644
--- a/src/components/ExperienceDetail/Article/index.js
+++ b/src/components/ExperienceDetail/Article/index.js
@@ -27,12 +27,7 @@ const countSectionWords = sections =>
sections,
);
-const Article = ({
- experience,
- hideContent,
-
- onClickMsgButton,
-}) => {
+const Article = ({ experience, hideContent, onClickMsgButton }) => {
// Get share link object according to Google Optimize parameters
const shareLink = useShareLink();
@@ -76,8 +71,13 @@ const Article = ({
return (
{experience.sections &&
- experience.sections.map(({ subtitle, content }, idx) => (
-
+ experience.sections.map(({ subtitle, content, rating }, idx) => (
+
))}
);
diff --git a/src/components/ExperienceDetail/Heading/index.js b/src/components/ExperienceDetail/Heading/index.js
index d42d92882..2b5f66c22 100644
--- a/src/components/ExperienceDetail/Heading/index.js
+++ b/src/components/ExperienceDetail/Heading/index.js
@@ -12,13 +12,13 @@ import {
const formatType = type => {
switch (type) {
case 'work':
- return '工作心得';
+ return '評價';
case 'interview':
return '面試經驗';
case 'intern':
return '實習心得';
default:
- return '工作心得';
+ return '評價';
}
};
diff --git a/src/components/ExperienceDetail/MoreExperiencesBlock/index.js b/src/components/ExperienceDetail/MoreExperiencesBlock/index.js
index c00011562..2f0d14e86 100644
--- a/src/components/ExperienceDetail/MoreExperiencesBlock/index.js
+++ b/src/components/ExperienceDetail/MoreExperiencesBlock/index.js
@@ -76,7 +76,7 @@ const MoreExperiencesBlock = ({ experience }) => {
更多{experience.originalCompanyName}、{experience.job_title.name}
- 的面試及工作心得...
+ 的面試及評價...
{experiences.map(e => (
{
content += `面試地區:${region}。`;
}
if (experience.experience_in_year) {
- content += `相關職務工作經驗:${experience_in_year} 年。`;
+ content += `相關職務評價:${experience_in_year} 年。`;
}
if (interviewYear && interviewMonth) {
content += `面試時間:${interviewYear} 年 ${interviewMonth} 月。`;
@@ -113,7 +113,7 @@ const workMetaDescriptionSelector = experience => {
content += `工作地區:${region}。`;
}
if (experience.experience_in_year) {
- content += `相關職務工作經驗:${experience_in_year} 年。`;
+ content += `相關職務評價:${experience_in_year} 年。`;
}
if (experience.education) {
content += `最高學歷:${experience.education}。`;
diff --git a/src/components/Guidelines/index.js b/src/components/Guidelines/index.js
index 43210a0e7..891b6f3a6 100644
--- a/src/components/Guidelines/index.js
+++ b/src/components/Guidelines/index.js
@@ -12,7 +12,7 @@ const GuideLines = () => (
GoodJob 的使用者您好!一旦您在 GoodJob
- 平台上發表內容(包含但不限於薪資及工時資訊、面試經驗分享、工作經驗分享、實習經驗分享、留言回覆以及檢舉的內容),即代表您同意遵守以下發文留言規則。我們未來有可能修訂本規則,您將會於本頁面或公告指定的頁面找到此規則的最新版本。
+ 平台上發表內容(包含但不限於薪資及工時資訊、面試經驗分享、評價分享、實習經驗分享、留言回覆以及檢舉的內容),即代表您同意遵守以下發文留言規則。我們未來有可能修訂本規則,您將會於本頁面或公告指定的頁面找到此規則的最新版本。
diff --git a/src/components/LaborRightsMenu/index.js b/src/components/LaborRightsMenu/index.js
index d48aab9d8..57968c167 100644
--- a/src/components/LaborRightsMenu/index.js
+++ b/src/components/LaborRightsMenu/index.js
@@ -38,7 +38,7 @@ const LaborRightsMenu = () => {
R.insert(4, {
link: shareLink,
coverUrl: AdvImage,
- title: '留下你的面試經驗、工作經驗',
+ title: '留下你的面試經驗、評價',
}),
R.map(entryToProps),
);
diff --git a/src/components/LandingPage/ExperienceBlock/helper.js b/src/components/LandingPage/ExperienceBlock/helper.js
index ab2d7c724..484f1d9b7 100644
--- a/src/components/LandingPage/ExperienceBlock/helper.js
+++ b/src/components/LandingPage/ExperienceBlock/helper.js
@@ -3,13 +3,13 @@ import { formatSalaryAmount, formatSalaryType } from 'common/formatter';
export const formatType = type => {
switch (type) {
case 'work':
- return '工作心得';
+ return '評價';
case 'interview':
return '面試心得';
case 'intern':
return '實習心得';
default:
- return '工作心得';
+ return '評價';
}
};
diff --git a/src/components/LandingPage/index.js b/src/components/LandingPage/index.js
index 9d5cf72db..5db4748e1 100644
--- a/src/components/LandingPage/index.js
+++ b/src/components/LandingPage/index.js
@@ -86,7 +86,7 @@ const LandingPage = () => {
- 最新面試、工作心得
+ 最新面試、評價