Update time ticket areas added to use translations

This commit is contained in:
jfrye122
2023-06-05 16:50:12 -04:00
parent 43151aaa2d
commit 0889453998
11 changed files with 235 additions and 84 deletions

View File

@@ -10,12 +10,6 @@ import { QUERY_EMPLOYEE_BY_ID } from "../../graphql/employees.queries";
import { useEffect } from "react"; import { useEffect } from "react";
import { t } from "i18next"; import { t } from "i18next";
const data = [
{ label: "Item 1", value: "1" },
{ label: "Item 2", value: "3" },
{ label: "Item 3", value: "3" },
];
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop
// timeTicketJobId: selectCurrentTimeTicketJobId, // timeTicketJobId: selectCurrentTimeTicketJobId,
@@ -62,8 +56,8 @@ export function CostCenterSelect(props) {
maxHeight={300} maxHeight={300}
labelField="label" labelField="label"
valueField="value" valueField="value"
placeholder={!isFocus ? "Select Cost Center" : "..."} placeholder={!isFocus ? t("selectcostcenter.labels.placeholder") : t("selectcostcenter.labels.selectedplaceholder")}
searchPlaceholder="Search..." searchPlaceholder={t("selectcostcenter.labels.searchplaceholder")}
onFocus={() => setIsFocus(true)} onFocus={() => setIsFocus(true)}
onBlur={() => setIsFocus(false)} onBlur={() => setIsFocus(false)}
data={costCenters} data={costCenters}

View File

@@ -96,7 +96,7 @@ export function JobIdSearchSelect(
useEffect(() => { useEffect(() => {
// console.log("useEfectDependentOn: [theOptions]"); // console.log("useEfectDependentOn: [theOptions]");
var count = Object.keys(theOptions).length; var count = Object.keys(theOptions).length;
console.log("useEfectDependentOn: [theOptions] count:", count); // console.log("useEfectDependentOn: [theOptions] count:", count);
let selectDataArray = []; let selectDataArray = [];
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
selectDataArray.push({ selectDataArray.push({
@@ -131,8 +131,8 @@ export function JobIdSearchSelect(
maxHeight={300} maxHeight={300}
labelField="label" labelField="label"
valueField="value" valueField="value"
placeholder={!isFocus ? "RO #" : "..."} placeholder={!isFocus ? t("selectjobid.labels.placeholder") : t("selectjobid.labels.selectedplaceholder")}
searchPlaceholder="Search..." searchPlaceholder={t("selectjobid.labels.searchplaceholder")}
onFocus={() => setIsFocus(true)} onFocus={() => setIsFocus(true)}
onBlur={() => setIsFocus(false)} onBlur={() => setIsFocus(false)}
data={selectorData} data={selectorData}

View File

@@ -186,7 +186,7 @@ const TimeTicketBrowserStackNavigator = connect(
<TimeTicketBrowserStack.Screen <TimeTicketBrowserStack.Screen
name="TimeTicketClockOff" name="TimeTicketClockOff"
options={() => ({ options={() => ({
title: "Clock Off", title: i18n.t("timeticketclockoff.titles.clockoff"),
})} })}
component={ScreenTimeTicketClockoffComponent} component={ScreenTimeTicketClockoffComponent}
/> />
@@ -217,7 +217,6 @@ const BottomTabsNavigator = () => (
} else if (route.name === "MediaBrowserTab") { } else if (route.name === "MediaBrowserTab") {
iconName = "ios-camera"; iconName = "ios-camera";
} else if (route.name === "TimeTicketBrowserTab") { } else if (route.name === "TimeTicketBrowserTab") {
//ADDED JF check for route.name for TimeTicketBrowserTab. Also icon ios-stopwatch-outline
iconName = "ios-stopwatch-outline"; iconName = "ios-stopwatch-outline";
} else { } else {
//iconName = "customerservice"; //iconName = "customerservice";

View File

@@ -25,6 +25,7 @@ import { QUERY_ACTIVE_TIME_TICKETS } from "../../graphql/timetickets.queries";
import EmployeeClockedInList from "../time-ticket-lists/employee-clockedin-list.component"; import EmployeeClockedInList from "../time-ticket-lists/employee-clockedin-list.component";
import { logImEXEvent } from "../../firebase/firebase.analytics"; import { logImEXEvent } from "../../firebase/firebase.analytics";
import StyleRepeater from "../style-repeater/style-repeater"; import StyleRepeater from "../style-repeater/style-repeater";
import { useTranslation } from "react-i18next";
// import SignOutButton from "../Buttons/employee-sign-out-button.component"; // import SignOutButton from "../Buttons/employee-sign-out-button.component";
// import AddTimeTicketButton from "../Buttons/create-time-ticket-button.component"; // import AddTimeTicketButton from "../Buttons/create-time-ticket-button.component";
@@ -55,6 +56,7 @@ export function ScreenTimeTicketBrowser({
currentSelectedTimeTicketJobId, currentSelectedTimeTicketJobId,
currentEmployeeFullName, currentEmployeeFullName,
}) { }) {
const { t } = useTranslation();
const [currentSCC, setCurrentSCC] = useState(null); const [currentSCC, setCurrentSCC] = useState(null);
const [currentSJobId, setCurrentSJobId] = useState(null); const [currentSJobId, setCurrentSJobId] = useState(null);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@@ -65,7 +67,7 @@ export function ScreenTimeTicketBrowser({
}); });
const handleFinish = async (values) => { const handleFinish = async (values) => {
console.log("handleFinish called in ScreenTimeTicketBrowser"); // console.log("handleFinish called in ScreenTimeTicketBrowser");
setLoading(true); setLoading(true);
setError(null); setError(null);
@@ -77,7 +79,7 @@ export function ScreenTimeTicketBrowser({
} else { } else {
// console.log("missing values!"); // console.log("missing values!");
setLoading(false); setLoading(false);
setError({ message: "Please make sure all fields have a value." }); setError({ message: t("timeticketbrowser.errors.missingvalues") });
return; return;
} }
@@ -137,7 +139,7 @@ export function ScreenTimeTicketBrowser({
> >
<StyleRepeater childStyle={{ margin: 4 }}> <StyleRepeater childStyle={{ margin: 4 }}>
<Card> <Card>
<Card.Title title={"Logged in Employee"} <Card.Title title={t("timeticketbrowser.labels.loggedinemployee")}
// right={(props) => <SignOutButton />} // right={(props) => <SignOutButton />}
/> />
<Card.Content> <Card.Content>
@@ -147,7 +149,7 @@ export function ScreenTimeTicketBrowser({
</Card.Content> </Card.Content>
</Card> </Card>
<Card> <Card>
<Card.Title title={"Clock Into Job"} <Card.Title title={t("timeticketbrowser.labels.clockintojob")}
// right={(props) => // right={(props) =>
// <View style={{ flexDirection:"row" }} ><AddTimeTicketButton /> // <View style={{ flexDirection:"row" }} ><AddTimeTicketButton />
// <Button mode="outlined" // <Button mode="outlined"
@@ -175,7 +177,7 @@ export function ScreenTimeTicketBrowser({
<ErrorDisplay errorMessage={error.message} /> <ErrorDisplay errorMessage={error.message} />
) : null} ) : null}
<Button mode="outlined" loading={loading} onPress={handleFinish}> <Button mode="outlined" loading={loading} onPress={handleFinish}>
<Text>Clock In</Text> <Text>{t("timeticketbrowser.actions.clockin")}</Text>
</Button> </Button>
</Card.Content> </Card.Content>
</Card> </Card>

View File

@@ -36,16 +36,16 @@ export function ClockedinListItem({ setTmTicketJobIdRedux, ticket }) {
/> />
<Card.Content> <Card.Content>
<Text> <Text>
Vehicle : {t("clockedinlistitem.labels.vehicle")}
{`${ticket.job.v_model_yr || ""} ${ticket.job.v_make_desc || ""} ${ {`${ticket.job.v_model_yr || ""} ${ticket.job.v_make_desc || ""} ${
ticket.job.v_model_desc || "" ticket.job.v_model_desc || ""
}`} }`}
</Text> </Text>
<Text> <Text>
Clocked In : <DateTimeFormatter>{ticket.clockon}</DateTimeFormatter> {t("clockedinlistitem.labels.clockedin")}<DateTimeFormatter>{ticket.clockon}</DateTimeFormatter>
</Text> </Text>
<Text> <Text>
Cost Center :{" "} {t("clockedinlistitem.labels.costcenter")}
{ticket.cost_center === "timetickets.labels.shift" {ticket.cost_center === "timetickets.labels.shift"
? t(ticket.cost_center) ? t(ticket.cost_center)
: ticket.cost_center} : ticket.cost_center}
@@ -53,7 +53,7 @@ export function ClockedinListItem({ setTmTicketJobIdRedux, ticket }) {
</Card.Content> </Card.Content>
<Card.Actions> <Card.Actions>
<Button mode="outlined" onPress={makeNavToTimeTicketClockOff} > <Button mode="outlined" onPress={makeNavToTimeTicketClockOff} >
Clock Out {t("clockedinlistitem.actions.clockout")}
</Button> </Button>
</Card.Actions> </Card.Actions>
</Card> </Card>

View File

@@ -42,7 +42,7 @@ export function EmployeeClockedInList({ currentEmployee, isRefresh }) {
if(isRefresh){ if(isRefresh){
refetch(); refetch();
} }
console.log("useEffect: ", isRefresh); // console.log("useEffect: ", isRefresh);
// setRefreshKey(isRefresh); // setRefreshKey(isRefresh);
}, [isRefresh]); }, [isRefresh]);
@@ -62,19 +62,16 @@ export function EmployeeClockedInList({ currentEmployee, isRefresh }) {
if (error) return <ErrorDisplay errorMessage={error.message} />; if (error) return <ErrorDisplay errorMessage={error.message} />;
const onRefresh = async () => { const onRefresh = async () => {
console.info("EmployeeClockedInList, onRefresh."); // console.info("EmployeeClockedInList, onRefresh.");
return refetch(); return refetch();
}; };
return ( return (
<View style={{ flex: 1, flexGrow: 1 }}> <View style={{ flex: 1, flexGrow: 1 }}>
{jobData ? ( {jobData ? (
<View style={{ flex: 1 }}> <View style={{ flex: 1 }}>
<Text style={{ paddingLeft: 12, paddingTop: 14 }}> <Text style={{ paddingLeft: 12, paddingTop: 14 }}>
You are already clocked in to the following job(s): {t("employeeclockedinlist.labels.alreadyclockedon")}
</Text> </Text>
<FlatList <FlatList
data={jobData?.timetickets} data={jobData?.timetickets}

View File

@@ -62,17 +62,16 @@ export function TimeTicketClockOff({
!!currentSCC?.value !!currentSCC?.value
) { ) {
if (isNaN(values.actualhours)|isNaN(values.productivehours)) { if (isNaN(values.actualhours)|isNaN(values.productivehours)) {
console.log("actual hours is NAN!"); // console.log("actual hours is NAN!");
setLoading(false); setLoading(false);
setError({ message: "Please make sure all fields have valid values." }); setError({ message: t("timeticketclockoff.errors.nan") });
return; return;
} }
setError(null); setError(null);
console.log("all have values:"); // console.log("all have values:");
} else { } else {
console.log("missing values!"); // console.log("missing values!");
setError({ message: "Please make sure all fields have a value." }); setError({ message: t("timeticketclockoff.errors.missingvalues") });
return; return;
} }
const tempcallobj = { const tempcallobj = {
@@ -119,9 +118,9 @@ export function TimeTicketClockOff({
setLoading(false); setLoading(false);
if (!!result.errors) { if (!!result.errors) {
// console.log("updateTimeticket, result.error :", result.errors); // console.log("updateTimeticket, result.error :", result.errors);
setError(SON.stringify(result.errors)); setError(JSON.stringify(result.errors));
} else { } else {
console.log("updateTimeticket, result. :", result.data); // console.log("updateTimeticket, result :", result.data);
navigation.goBack(); navigation.goBack();
} }
//if (completedCallback) completedCallback(); //if (completedCallback) completedCallback();
@@ -146,7 +145,7 @@ export function TimeTicketClockOff({
onChangeText={handleChange("actualhours")} onChangeText={handleChange("actualhours")}
onBlur={handleBlur("actualhours")} onBlur={handleBlur("actualhours")}
value={values.actualhours} value={values.actualhours}
label={"Actual Hours"} label={t("timeticketclockoff.labels.actualhoursplaceholder")}
keyboardType="numeric" keyboardType="numeric"
/> />
<TextInput <TextInput
@@ -155,7 +154,7 @@ export function TimeTicketClockOff({
onChangeText={handleChange("productivehours")} onChangeText={handleChange("productivehours")}
onBlur={handleBlur("productivehours")} onBlur={handleBlur("productivehours")}
value={values.productivehours} value={values.productivehours}
label={"Productive Hours"} label={t("timeticketclockoff.labels.productivehoursplaceholder")}
keyboardType="numeric" keyboardType="numeric"
/> />
<CostCenterSelect <CostCenterSelect
@@ -167,9 +166,9 @@ export function TimeTicketClockOff({
<Button <Button
style={localStyles.input} style={localStyles.input}
onPress={handleSubmit} onPress={handleSubmit}
title="Submit" title={t("timeticketclockoff.actions.clockoff")}
> >
<Text style={{ fontSize: 12 }}>Clock Off</Text> <Text style={{ fontSize: 12 }}>{t("timeticketclockoff.actions.clockoff")}</Text>
</Button> </Button>
</View> </View>
)} )}

View File

@@ -52,13 +52,6 @@ export function TimeTicketCreate({
// const [currentSJob, setCurrentSJob] = useState(null); // const [currentSJob, setCurrentSJob] = useState(null);
const [currentSJobId, setCurrentSJobId] = useState(null); const [currentSJobId, setCurrentSJobId] = useState(null);
// const wrapperSetCurrentSJobState = useCallback(
// (val) => {
// setCurrentSJob(val);
// },
// [setCurrentSJob]
// );
const showDatePicker = () => { const showDatePicker = () => {
setDatePickerVisibility(true); setDatePickerVisibility(true);
}; };
@@ -67,7 +60,6 @@ export function TimeTicketCreate({
}; };
const handleConfirm = (date) => { const handleConfirm = (date) => {
setDate2(date); setDate2(date);
//console.war1n("A date has been picked: ", date);
hideDatePicker(); hideDatePicker();
}; };
@@ -75,7 +67,7 @@ export function TimeTicketCreate({
const handleFinish = async (values) => { const handleFinish = async (values) => {
logImEXEvent("handleFinish_called_in_TimeTicketCreate"); logImEXEvent("handleFinish_called_in_TimeTicketCreate");
console.log("handleFinish called in TimeTicketCreate"); // console.log("handleFinish called in TimeTicketCreate");
setError(null); setError(null);
setLoading(true); setLoading(true);
@@ -93,17 +85,17 @@ export function TimeTicketCreate({
!!values.actualhours !!values.actualhours
) { ) {
if (isNaN(values.actualhours) | isNaN(values.productivehours)) { if (isNaN(values.actualhours) | isNaN(values.productivehours)) {
console.log("actual hours is NAN!"); // console.log("actual hours is NAN!");
setLoading(false); setLoading(false);
setError({ message: "Please make sure all fields have valid values." }); setError({ message: t("createtimeticket.errors.nan") });
return; return;
} }
setError(null); setError(null);
console.log("have all values"); // console.log("have all values");
} else { } else {
console.log("missing values!"); // console.log("missing values!");
setLoading(false); setLoading(false);
setError({ message: "Please make sure all fields have a value." }); setError({ message: t("createtimeticket.errors.missingvalues")});
return; return;
} }
@@ -211,7 +203,7 @@ export function TimeTicketCreate({
style={localStyles.dateButton} style={localStyles.dateButton}
> >
<Text style={localStyles.textForButton}> <Text style={localStyles.textForButton}>
Ticket Date: {date2.toLocaleDateString('en-US', { day: '2-digit', month: '2-digit', year: 'numeric' })} {t("createtimeticket.actions.ticketdate")}{date2.toLocaleDateString('en-US', { day: '2-digit', month: '2-digit', year: 'numeric' })}
</Text> </Text>
</Button> </Button>
<DateTimePickerModal <DateTimePickerModal
@@ -221,28 +213,25 @@ export function TimeTicketCreate({
onConfirm={handleConfirm} onConfirm={handleConfirm}
onCancel={hideDatePicker} onCancel={hideDatePicker}
/> />
{/* Below will set to auto fill with current employee */}
<TextInput <TextInput
style={localStyles.inputStyle} style={localStyles.inputStyle}
mode="outlined" mode="outlined"
disabled={true} disabled={true}
value={currentEmployeeFullName} value={currentEmployeeFullName}
label={"Employee"} label={t("createtimeticket.labels.employeeplaceholder")}
/> />
<CostCenterSelect <CostCenterSelect
currentRatesNCostCenters={currentRatesNCostCenters} currentRatesNCostCenters={currentRatesNCostCenters}
currentValue={currentSCC} currentValue={currentSCC}
onValueSelected={setCurrentSCC} onValueSelected={setCurrentSCC}
/> />
<TextInput <TextInput
style={localStyles.inputStyle} style={localStyles.inputStyle}
mode="outlined" mode="outlined"
onChangeText={handleChange("productivehours")} onChangeText={handleChange("productivehours")}
onBlur={handleBlur("productivehours")} onBlur={handleBlur("productivehours")}
value={values.productivehours} value={values.productivehours}
label={"Productive Hours"} label={t("createtimeticket.labels.productivehoursplaceholder")}
keyboardType="numeric" keyboardType="numeric"
/> />
<TextInput <TextInput
@@ -251,7 +240,7 @@ export function TimeTicketCreate({
onChangeText={handleChange("actualhours")} onChangeText={handleChange("actualhours")}
onBlur={handleBlur("actualhours")} onBlur={handleBlur("actualhours")}
value={values.actualhours} value={values.actualhours}
label={"Actual Hours"} label={t("createtimeticket.labels.actualhoursplaceholder")}
keyboardType="numeric" keyboardType="numeric"
/> />
{error ? <ErrorDisplay errorMessage={error.message} /> : null} {error ? <ErrorDisplay errorMessage={error.message} /> : null}
@@ -261,7 +250,7 @@ export function TimeTicketCreate({
loading={loading} loading={loading}
title="Submit" title="Submit"
> >
<Text style={{ fontSize: 12 }}>Create Ticket</Text> <Text style={{ fontSize: 12 }}>{t("createtimeticket.actions.createticket")}</Text>
</Button> </Button>
</View> </View>
)} )}

View File

@@ -330,13 +330,15 @@
"ticket":"Ticket", "ticket":"Ticket",
"timetickets": "Time Tickets", "timetickets": "Time Tickets",
"detail": "Time Ticket Details", "detail": "Time Ticket Details",
"notickets": "There are no active tickets." "notickets": "There are no active tickets.",
"clockin": "Clock In"
}, },
"labels": { "labels": {
"converting": "Converting", "loggedinemployee": "Logged in Employee",
"selectjob": "--- Select a ticket ---", "clockintojob": "Clock Into Job"
"selectticketassetselector": "Please select a ticket to update. ", },
"uploading": "Uploading" "errors": {
"missingvalues": "Please make sure all fields have a value."
}, },
"titles": { "titles": {
"timeticketbrowsertab": "Time Tickets" "timeticketbrowsertab": "Time Tickets"
@@ -349,13 +351,22 @@
"ticket":"Ticket", "ticket":"Ticket",
"timetickets": "Time Tickets", "timetickets": "Time Tickets",
"detail": "Time Ticket Details", "detail": "Time Ticket Details",
"notickets": "There are no active tickets." "notickets": "There are no active tickets.",
"ticketdate": "Ticket Date: ",
"createticket": "Create Ticket"
}, },
"labels": { "labels": {
"converting": "Converting", "converting": "Converting",
"selectjob": "--- Select a ticket ---", "selectjob": "--- Select a ticket ---",
"selectticketassetselector": "Please select a ticket to update. ", "selectticketassetselector": "Please select a ticket to update. ",
"uploading": "Uploading" "uploading": "Uploading",
"employeeplaceholder": "Employee",
"actualhoursplaceholder": "Actual Hours",
"productivehoursplaceholder": "Productive Hours"
},
"errors": {
"nan": "Please make sure all fields have valid values.",
"missingvalues": "Please make sure all fields have a value."
}, },
"titles": { "titles": {
"createtimeticket": "Create a Time Ticket" "createtimeticket": "Create a Time Ticket"
@@ -450,6 +461,52 @@
"requiredifparttype": "Required if a part type has been specified.", "requiredifparttype": "Required if a part type has been specified.",
"zeropriceexistingpart": "This line cannot have any price since it uses an existing part." "zeropriceexistingpart": "This line cannot have any price since it uses an existing part."
} }
},
"timeticketclockoff":{
"actions": {
"clockoff": "Clock Off",
"noinfo": "There is no info to display."
},
"labels": {
"actualhoursplaceholder": "Actual Hours",
"productivehoursplaceholder": "Productive Hours"
},
"errors": {
"nan": "Please make sure all fields have valid values.",
"missingvalues": "Please make sure all fields have a value."
},
"titles": {
"clockoff": "Clock Off"
}
},
"selectjobid":{
"labels": {
"placeholder": "RO #",
"selectedplaceholder": "...",
"searchplaceholder": "Search..."
}
},
"selectcostcenter":{
"labels": {
"placeholder": "Select Cost Center",
"selectedplaceholder": "...",
"searchplaceholder": "Search..."
}
},
"employeeclockedinlist": {
"labels": {
"alreadyclockedon": "You are already clocked in to the following job(s):"
}
},
"clockedinlistitem": {
"labels": {
"vehicle": "Vehicle : ",
"clockedin": "Clocked In : ",
"costcenter": "Cost Center : "
},
"actions": {
"clockout": "Clock Out"
}
} }
} }
} }

View File

@@ -330,13 +330,15 @@
"ticket": "", "ticket": "",
"timetickets": "", "timetickets": "",
"detail": "", "detail": "",
"notickets": "" "notickets": "",
"clockin": ""
}, },
"labels": { "labels": {
"converting": "", "loggedinemployee": "",
"selectjob": "", "clockintojob": ""
"selectticketassetselector": "", },
"uploading": "" "errors": {
"missingvalues": ""
}, },
"titles": { "titles": {
"timeticketbrowsertab": "" "timeticketbrowsertab": ""
@@ -349,13 +351,22 @@
"ticket":" ", "ticket":" ",
"timetickets": "", "timetickets": "",
"detail": "", "detail": "",
"notickets": "" "notickets": "",
"ticketdate": "",
"createticket": ""
}, },
"labels": { "labels": {
"converting": "", "converting": "",
"selectjob": "", "selectjob": "",
"selectticketassetselector": "", "selectticketassetselector": "",
"uploading": "" "uploading": "",
"employeeplaceholder": "",
"actualhoursplaceholder": "",
"productivehoursplaceholder": ""
},
"errors": {
"nan": "",
"missingvalues": ""
}, },
"titles": { "titles": {
"createtimeticket": "" "createtimeticket": ""
@@ -450,6 +461,52 @@
"requiredifparttype": "", "requiredifparttype": "",
"zeropriceexistingpart": "" "zeropriceexistingpart": ""
} }
},
"timeticketclockoff":{
"actions": {
"clockoff": "",
"noinfo": ""
},
"labels": {
"actualhoursplaceholder": "",
"productivehoursplaceholder": ""
},
"errors": {
"nan": "",
"missingvalues": ""
},
"titles": {
"clockoff": ""
}
},
"selectjobid":{
"labels": {
"placeholder": "",
"selectedplaceholder": "...",
"searchplaceholder": ""
}
},
"selectcostcenter":{
"labels": {
"placeholder": "",
"selectedplaceholder": "...",
"searchplaceholder": ""
}
},
"employeeclockedinlist": {
"labels": {
"alreadyclockedon": ""
}
},
"clockedinlistitem": {
"labels": {
"vehicle": "",
"clockedin": "",
"costcenter": ""
},
"actions": {
"clockout": ""
}
} }
} }
} }

View File

@@ -330,13 +330,15 @@
"ticket": "", "ticket": "",
"timetickets": "", "timetickets": "",
"detail": "", "detail": "",
"notickets": "" "notickets": "",
"clockin": ""
}, },
"labels": { "labels": {
"converting": "", "loggedinemployee": "",
"selectjob": "", "clockintojob": ""
"selectticketassetselector": "", },
"uploading": "" "errors": {
"missingvalues": ""
}, },
"titles": { "titles": {
"timeticketbrowsertab": "" "timeticketbrowsertab": ""
@@ -349,13 +351,22 @@
"ticket":" ", "ticket":" ",
"timetickets": "", "timetickets": "",
"detail": "", "detail": "",
"notickets": "" "notickets": "",
"ticketdate": "",
"createticket": ""
}, },
"labels": { "labels": {
"converting": "", "converting": "",
"selectjob": "", "selectjob": "",
"selectticketassetselector": "", "selectticketassetselector": "",
"uploading": "" "uploading": "",
"employeeplaceholder": "",
"actualhoursplaceholder": "",
"productivehoursplaceholder": ""
},
"errors": {
"nan": "",
"missingvalues": ""
}, },
"titles": { "titles": {
"createtimeticket": "" "createtimeticket": ""
@@ -450,6 +461,52 @@
"requiredifparttype": "", "requiredifparttype": "",
"zeropriceexistingpart": "" "zeropriceexistingpart": ""
} }
},
"timeticketclockoff":{
"actions": {
"clockoff": "",
"noinfo": ""
},
"labels": {
"actualhoursplaceholder": "",
"productivehoursplaceholder": ""
},
"errors": {
"nan": "",
"missingvalues": ""
},
"titles": {
"clockoff": ""
}
},
"selectjobid":{
"labels": {
"placeholder": "",
"selectedplaceholder": "...",
"searchplaceholder": ""
}
},
"selectcostcenter":{
"labels": {
"placeholder": "",
"selectedplaceholder": "...",
"searchplaceholder": ""
}
},
"employeeclockedinlist": {
"labels": {
"alreadyclockedon": ""
}
},
"clockedinlistitem": {
"labels": {
"vehicle": "",
"clockedin": "",
"costcenter": ""
},
"actions": {
"clockout": ""
}
} }
} }
} }