| @@ -66,8 +66,8 @@ const Profile: React.FC<Props> = ({ avatarImageSrc, profileName }) => { | |||
| </Typography> | |||
| <Divider /> | |||
| <MenuItem onClick={() => { router.replace("/changepassword") }}>{t("Change Password")}</MenuItem> | |||
| {/* {language === "zh" && <MenuItem onClick={() => { onLangClick("en") }}>{t("Change To English Version")}</MenuItem>} | |||
| {language === "en" && <MenuItem onClick={() => { onLangClick("zh") }}>{t("Change To Chinese Version")}</MenuItem>} */} | |||
| {language === "zh" && <MenuItem onClick={() => { onLangClick("en") }}>{t("Change To English Version")}</MenuItem>} | |||
| {language === "en" && <MenuItem onClick={() => { onLangClick("zh") }}>{t("Change To Chinese Version")}</MenuItem>} | |||
| <MenuItem onClick={() => signOut()}>{t("Sign out")}</MenuItem> | |||
| </Menu> | |||
| </> | |||
| @@ -27,6 +27,7 @@ import LeaveEditModal from "../LeaveTable/LeaveEditModal"; | |||
| import dayjs from "dayjs"; | |||
| import { checkTotalHours } from "@/app/api/timesheets/utils"; | |||
| import unionBy from "lodash/unionBy"; | |||
| import { ConnectingAirportsOutlined } from "@mui/icons-material"; | |||
| export interface Props { | |||
| leaveTypes: LeaveType[]; | |||
| @@ -56,8 +57,8 @@ const LeaveCalendar: React.FC<Props> = ({ | |||
| leaveRecords, | |||
| isFullTime, | |||
| }) => { | |||
| const { t } = useTranslation(["home", "common"]); | |||
| const { t ,i18n: { language }} = useTranslation(["home", "common"]); | |||
| const locale = language === "zh" ? "zh-tw" : "en"; | |||
| const theme = useTheme(); | |||
| const projectMap = useMemo(() => { | |||
| @@ -143,7 +144,7 @@ const LeaveCalendar: React.FC<Props> = ({ | |||
| title: `${t("{{count}} hour", { | |||
| ns: "common", | |||
| count: entry.inputHours || 0, | |||
| })} (${leaveMap[entry.leaveTypeId]})`, | |||
| })} (${t(leaveMap[entry.leaveTypeId])})`, | |||
| backgroundColor: theme.palette.warning.light, | |||
| borderColor: theme.palette.warning.light, | |||
| textColor: theme.palette.text.primary, | |||
| @@ -269,6 +270,7 @@ const LeaveCalendar: React.FC<Props> = ({ | |||
| events={[...holidays, ...timeEntries, ...leaveEntries]} | |||
| eventClick={handleEventClick} | |||
| dateClick={handleDateClick} | |||
| locale={locale} | |||
| /> | |||
| <LeaveEditModal | |||
| modalSx={{ maxWidth: 400 }} | |||
| @@ -108,16 +108,16 @@ const LeaveEditModal: React.FC<Props> = ({ | |||
| </Typography> | |||
| )} | |||
| <FormControl fullWidth> | |||
| <InputLabel>{t("Leave Type")}</InputLabel> | |||
| <InputLabel>{t("Leave Types")}</InputLabel> | |||
| <Controller | |||
| defaultValue={leaveTypes[0].id} | |||
| control={control} | |||
| name="leaveTypeId" | |||
| render={({ field }) => ( | |||
| <Select label={t("Leave Type")} {...field}> | |||
| <Select label={t("Leave Types")} {...field}> | |||
| {leaveTypes.map((type, index) => ( | |||
| <MenuItem key={`${type.id}-${index}`} value={type.id}> | |||
| {type.name} | |||
| {t(type.name)} | |||
| </MenuItem> | |||
| ))} | |||
| </Select> | |||
| @@ -148,7 +148,7 @@ const LeaveEditModal: React.FC<Props> = ({ | |||
| helperText={formState.errors.inputHours?.message} | |||
| /> | |||
| <TextField | |||
| label={t("Remark")} | |||
| label={t("Remarks")} | |||
| fullWidth | |||
| multiline | |||
| rows={2} | |||
| @@ -35,7 +35,7 @@ const LeaveEntryCard: React.FC<Props> = ({ entry, onEdit, leaveTypeMap }) => { | |||
| > | |||
| <Box> | |||
| <Typography variant="body2" component="div" fontWeight="bold"> | |||
| {leaveTypeMap[entry.leaveTypeId].name} | |||
| {t(leaveTypeMap[entry.leaveTypeId].name)} | |||
| </Typography> | |||
| <Typography component="p"> | |||
| {manhourFormatter.format(entry.inputHours)} | |||
| @@ -50,7 +50,7 @@ const LeaveEntryCard: React.FC<Props> = ({ entry, onEdit, leaveTypeMap }) => { | |||
| {entry.remark && ( | |||
| <Box> | |||
| <Typography variant="body2" component="div" fontWeight="bold"> | |||
| {t("Remark")} | |||
| {t("Remarks")} | |||
| </Typography> | |||
| <Typography component="p">{entry.remark}</Typography> | |||
| </Box> | |||
| @@ -303,7 +303,7 @@ const NavigationContent: React.FC<Props> = ({ abilities, username }) => { | |||
| }, | |||
| { | |||
| icon: <Settings />, | |||
| label: "Setting", | |||
| label: "Settings", | |||
| path: "", | |||
| isHidden: ![ | |||
| VIEW_CLIENT, | |||
| @@ -560,7 +560,7 @@ const TimeLeaveInputTable: React.FC<Props> = ({ | |||
| }, | |||
| { | |||
| field: "remark", | |||
| headerName: t("Remark"), | |||
| headerName: t("Remarks"), | |||
| sortable: false, | |||
| flex: 1, | |||
| editable: true, | |||
| @@ -41,7 +41,7 @@ import LeaveEditModal from "../LeaveTable/LeaveEditModal"; | |||
| import dayjs from "dayjs"; | |||
| import { checkTotalHours } from "@/app/api/timesheets/utils"; | |||
| import unionBy from "lodash/unionBy"; | |||
| import { Luggage, MoreTime } from "@mui/icons-material"; | |||
| import { Language, Luggage, MoreTime } from "@mui/icons-material"; | |||
| import { Task } from "@/app/api/tasks"; | |||
| export interface Props { | |||
| @@ -80,8 +80,8 @@ const TimesheetAmendment: React.FC<Props> = ({ | |||
| leaveTypes, | |||
| miscTasks, | |||
| }) => { | |||
| const { t } = useTranslation(["home", "common"]); | |||
| const { t, i18n:{language}} = useTranslation(["home", "common"]); | |||
| const locale = language === "zh" ? "zh-tw" : "en"; | |||
| const theme = useTheme(); | |||
| const projectMap = useMemo(() => { | |||
| @@ -262,7 +262,7 @@ const TimesheetAmendment: React.FC<Props> = ({ | |||
| title: `${t("{{count}} hour", { | |||
| ns: "common", | |||
| count: entry.inputHours || 0, | |||
| })} (${leaveMap[entry.leaveTypeId]})`, | |||
| })} (${t(leaveMap[entry.leaveTypeId])})`, | |||
| backgroundColor: theme.palette.warning.light, | |||
| borderColor: theme.palette.warning.light, | |||
| textColor: theme.palette.text.primary, | |||
| @@ -454,6 +454,7 @@ const TimesheetAmendment: React.FC<Props> = ({ | |||
| events={[...holidays, ...timeEntries, ...leaveEntries]} | |||
| eventClick={handleEventClick} | |||
| dateClick={handleDateClick} | |||
| locale={locale} | |||
| /> | |||
| <TimesheetEditModal | |||
| modalSx={{ maxWidth: 400 }} | |||
| @@ -42,7 +42,7 @@ export const TimesheetAmendmentModal: React.FC<Props> = ({ | |||
| const { t } = useTranslation("home"); | |||
| const isMobile = useIsMobile(); | |||
| const title = t("Timesheet Amendment"); | |||
| const title = t("Timesheet Amendments"); | |||
| const content = ( | |||
| <TimesheetAmendment | |||
| leaveTypes={leaveTypes} | |||
| @@ -195,7 +195,7 @@ const FastTimeEntryModal: React.FC<Props> = ({ | |||
| <FormHelperText> | |||
| {formState.errors.projectIds?.message || | |||
| t( | |||
| 'The inputted time will be evenly distributed among the selected projects. Only projects with the "Management Timesheet Allocation" task can use the fast entry.', | |||
| 'The inputted time will be evenly distributed among the selected projects. Only projects with the Management Timesheet Allocation task can use the fast entry.', | |||
| )} | |||
| </FormHelperText> | |||
| </FormControl> | |||
| @@ -237,7 +237,7 @@ const FastTimeEntryModal: React.FC<Props> = ({ | |||
| error={Boolean(formState.errors.otHours)} | |||
| /> | |||
| <TextField | |||
| label={t("Remark")} | |||
| label={t("Remarks")} | |||
| fullWidth | |||
| multiline | |||
| rows={2} | |||
| @@ -97,7 +97,7 @@ const AutocompleteProjectSelect: React.FC<Props> = ({ | |||
| ...(includeLeaves && leaveTypes | |||
| ? leaveTypes.map((l) => ({ | |||
| value: `leave-${l.id}`, | |||
| label: l.name, | |||
| label: t(l.name), | |||
| group: "leaves", | |||
| })) | |||
| : []), | |||
| @@ -295,7 +295,7 @@ const TimesheetEditModal: React.FC<Props> = ({ | |||
| error={Boolean(formState.errors.otHours)} | |||
| /> | |||
| <TextField | |||
| label={t("Remark")} | |||
| label={t("Remarks")} | |||
| fullWidth | |||
| multiline | |||
| rows={2} | |||
| @@ -168,7 +168,7 @@ const UserWorkspacePage: React.FC<Props> = ({ | |||
| {showTimesheetAmendment && ( | |||
| <MenuItem onClick={handleAmendmentClick} sx={menuItemSx}> | |||
| <EditCalendar /> | |||
| {t("Timesheet Amendment")} | |||
| {t("Timesheet Amendments")} | |||
| </MenuItem> | |||
| )} | |||
| </Menu> | |||
| @@ -41,5 +41,36 @@ | |||
| "Project Status by Team": "Project Status by Team", | |||
| "Project Resource Consumption Ranking": "Project Resource Consumption Ranking", | |||
| "Staff Utilization": "Staff Utilization", | |||
| "Project Resource Summary": "Project Resource Summary" | |||
| "Project Resource Summary": "Project Resource Summary", | |||
| "User Workspace": "User Workspace", | |||
| "Project Management": "Project Management", | |||
| "Task Template": "Task Template", | |||
| "Invoice": "Invoice", | |||
| "Analysis Report": "Analysis Report", | |||
| "Late Start Report": "Late Start Report", | |||
| "Project Potential Delay Report": "Project Potential Delay Report", | |||
| "Resource Overconsumption Report": "Resource Overconsumption Report", | |||
| "Cost and Expense Report": "Cost and Expense Report", | |||
| "Project Completion Report": "Project Completion Report", | |||
| "Project P&L Report": "Project P&L Report", | |||
| "Financial Status Report": "Financial Status Report", | |||
| "Project Cash Flow Report": "Project Cash Flow Report", | |||
| "Staff Monthly Work Hours Analysis Report": "Staff Monthly Work Hours Analysis Report", | |||
| "Cross Team Charge Report": "Cross Team Charge Report", | |||
| "Settings": "Settings", | |||
| "Client": "Client", | |||
| "Subsidiary": "Subsidiary", | |||
| "Staff": "Staff", | |||
| "Company": "Company", | |||
| "Skill": "Skill", | |||
| "Department": "Department", | |||
| "Position": "Position", | |||
| "Salary": "Salary", | |||
| "Team": "Team", | |||
| "User Group": "User Group", | |||
| "Holiday": "Holiday", | |||
| "Mail": "Mail", | |||
| "Import Excel File": "Import Excel File", | |||
| "There are some errors": "There are some errors", | |||
| "{{count}} hour": "{{count}} hour" | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| { | |||
| "User Workspace": "User Workspace", | |||
| "Timesheet Actions": "Timesheet Actions", | |||
| "Enter Timesheet": "Enter Timesheet", | |||
| "Record Leave": "Record Leave", | |||
| "View Past Entries": "View Past Entries", | |||
| "Timesheet Amendments": "Timesheet Amendments", | |||
| "You have no assigned projects!": "You have no assigned projects!", | |||
| "Timesheet Input": "Timesheet Input", | |||
| "Date": "Date", | |||
| "Timesheet Hours": "Timesheet Hours", | |||
| "Leave Hours": "Leave Hours", | |||
| "Daily Total Hours": "Daily Total Hours", | |||
| "Actions": "Actions", | |||
| "Project or Leave": "Project Or Leave", | |||
| "Stage": "Stage", | |||
| "Task": "Task", | |||
| "Hours": "Hours", | |||
| "Other Hours": "Other Hours", | |||
| "Remarks": "Remarks", | |||
| "Add some time entries!": "Add some time entries!", | |||
| "Record time or leave": "Record time or leave", | |||
| "Fast time entry": "Fast time entry", | |||
| "Non-billable": "Non-billable", | |||
| "None": "None", | |||
| "Leave Types": "Leave Types", | |||
| "Annual Leave": "Annual Leave", | |||
| "Sick Leave": "Sick Leave", | |||
| "Special Leave": "Special Leave", | |||
| "All projects": "All projects", | |||
| "Required": "Required", | |||
| "Required for non-billable tasks": "Required for non-billable tasks", | |||
| "There are some errors": "There are some errors", | |||
| "There are some unsaved entries.": "There are some unsaved entries.", | |||
| "Project Code and Name": "Project Code and Name", | |||
| "Please choose at least 1 project.": "Please choose at least 1 project.", | |||
| "The inputted time will be evenly distributed among the selected projects. Only projects with the Management Timesheet Allocation task can use the fast entry.": "The inputted time will be evenly distributed among the selected projects. Only projects with the 'Management Timesheet Allocation' task can use the fast entry.", | |||
| "Cannot input normal hours on holidays": "Cannot input normal hours on holidays", | |||
| "Input hours should be between 0 and {{DAILY_NORMAL_MAX_HOURS}}": "Input hours should be between 0 and {{DAILY_NORMAL_MAX_HOURS}}", | |||
| "The remark will be added to all selected projects": "The remark will be added to all selected projects", | |||
| "Hour distribution preview": "Hour distribution preview", | |||
| "Please input the hours": "Please input the hours", | |||
| "Save": "Save", | |||
| "Non-billable Task": "Non-billable Task", | |||
| "Please select some projects.": "Please select some projects.", | |||
| "Cancel": "Cancel", | |||
| "Record leave": "Record leave", | |||
| "Today": "Today", | |||
| "Close": "Close", | |||
| "Past Entries": "Past Entries", | |||
| "Has timesheet entry": "Has timesheet entry", | |||
| "Has leave entry": "Has leave entry", | |||
| "Has both timesheet and leave entry": "Has both timesheet and leave entry", | |||
| "Monthly Summary": "Monthly Summary", | |||
| "Total Monthly Work Hours": "Total Monthly Work Hours", | |||
| "Total Monthly Leave Hours": "Total Monthly Leave Hours", | |||
| "Back to Monthly Summary": "Back to Monthly Summary", | |||
| "Total Work Hours": "Total Work Hours", | |||
| "Total Leave Hours": "Total Leave Hours", | |||
| "{{count}} hour": "{{count}} hour", | |||
| "Enter Time": "Enter Time" | |||
| } | |||
| @@ -39,5 +39,36 @@ | |||
| "Project Status by Team": "按團隊查看項目狀態", | |||
| "Project Resource Consumption Ranking": "項目資源消耗排名", | |||
| "Staff Utilization": "員工利用率", | |||
| "Project Resource Summary": "項目資源摘要" | |||
| "Project Resource Summary": "項目資源摘要", | |||
| "User Workspace": "用戶工作區", | |||
| "Project Management": "項目管理", | |||
| "Task Template": "任務模板", | |||
| "Invoice": "發票", | |||
| "Analysis Report": "分析報告", | |||
| "Late Start Report": "延遲開始報告", | |||
| "Project Potential Delay Report": "項目潛在延遲報告", | |||
| "Resource Overconsumption Report": "資源超量消耗報告", | |||
| "Cost and Expense Report": "成本與費用報告", | |||
| "Project Completion Report": "項目完成報告", | |||
| "Project P&L Report": "項目損益報告", | |||
| "Financial Status Report": "財務狀況報告", | |||
| "Project Cash Flow Report": "項目現金流報告", | |||
| "Staff Monthly Work Hours Analysis Report": "員工月度工時分析報告", | |||
| "Cross Team Charge Report": "跨團隊費用報告", | |||
| "Settings": "設置", | |||
| "Client": "客戶", | |||
| "Subsidiary": "子公司", | |||
| "Staff": "員工", | |||
| "Company": "公司", | |||
| "Skill": "技能", | |||
| "Department": "部門", | |||
| "Position": "職位", | |||
| "Salary": "薪資", | |||
| "Team": "團隊", | |||
| "User Group": "用戶組", | |||
| "Holiday": "假期", | |||
| "Mail": "郵件", | |||
| "Import Excel File": "導入 Excel 文件", | |||
| "There are some errors": "發生錯誤", | |||
| "{{count}} hour": "{{count}} 小時" | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| { | |||
| "User Workspace": "用戶工作區", | |||
| "Timesheet Actions": "時間表操作", | |||
| "Enter Timesheet": "填寫時間表", | |||
| "Record Leave": "記錄假期", | |||
| "View Past Entries": "查看過去記錄", | |||
| "Timesheet Amendments": "修訂時間表", | |||
| "You have no assigned projects!": "您沒有分配的項目!", | |||
| "Timesheet Input": "輸入時間表", | |||
| "Date": "日期", | |||
| "Timesheet Hours": "時間表工時", | |||
| "Leave Hours": "請假工時", | |||
| "Daily Total Hours": "每日總工時", | |||
| "Actions": "操作", | |||
| "Project or Leave": "項目或假期", | |||
| "Stage": "階段", | |||
| "Task": "任務", | |||
| "Hours": "工時", | |||
| "Other Hours": "其他工時", | |||
| "Remarks": "備註", | |||
| "Add some time entries!": "添加一些時間記錄!", | |||
| "Record time or leave": "記錄工時或假期", | |||
| "Fast time entry": "快速時間輸入", | |||
| "Non-billable": "不可計費", | |||
| "None": "無", | |||
| "Leave Types": "假期類型", | |||
| "Annual Leave": "年假", | |||
| "Sick Leave": "病假", | |||
| "Special Leave": "特別假", | |||
| "All projects": "所有項目", | |||
| "Required": "必填", | |||
| "Required for non-billable tasks": "非計費工作必填", | |||
| "There are some errors": "發生錯誤", | |||
| "There are some unsaved entries.": "有未保存的記錄", | |||
| "Project Code and Name": "項目代碼與名稱", | |||
| "Please choose at least 1 project.": "請至少選擇一個項目。", | |||
| "The inputted time will be evenly distributed among the selected projects. Only projects with the Management Timesheet Allocation task can use the fast entry.": "輸入的時間將平均分配到選定的項目中。只有具有「管理時間表分配」工作的項目才能使用快速輸入。", | |||
| "Cannot input normal hours on holidays": "無法在假期輸入正常工時", | |||
| "Input hours should be between 0 and {{DAILY_NORMAL_MAX_HOURS}}": "輸入的工時應介於 0 和 {{DAILY_NORMAL_MAX_HOURS}} 之間", | |||
| "The remark will be added to all selected projects": "備註將添加到所有選定的項目中", | |||
| "Hour distribution preview": "工時分配預覽", | |||
| "Please input the hours": "請輸入工時", | |||
| "Save": "保存", | |||
| "Non-billable Task": "不可計費工作", | |||
| "Please select some projects.": "請選擇一些項目。", | |||
| "Cancel": "取消", | |||
| "Record leave": "記錄假期", | |||
| "Today": "今天", | |||
| "Close": "關閉", | |||
| "Past Entries": "過去的記錄", | |||
| "Has timesheet entry": "有時間表記錄", | |||
| "Has leave entry": "有假期記錄", | |||
| "Has both timesheet and leave entry": "有時間表和假期記錄", | |||
| "Monthly Summary": "月度總結", | |||
| "Total Monthly Work Hours": "月度總工時", | |||
| "Total Monthly Leave Hours": "月度假期工時", | |||
| "Back to Monthly Summary": "返回月度總結", | |||
| "Total Work Hours": "總工時", | |||
| "Total Leave Hours": "總假期工時", | |||
| "{{count}} hour": "{{count}} 小時", | |||
| "Enter Time": "輸入工時" | |||
| } | |||