Improve search layouts.

This commit is contained in:
Patrick Fic
2025-10-22 15:07:57 -07:00
parent 49d40aa038
commit c62d2ab05f
9 changed files with 546 additions and 328 deletions

View File

@@ -47,12 +47,10 @@ function AuthenticatedLayout() {
<Label>{t("settings.titles.settings")}</Label>
</NativeTabs.Trigger>
<NativeTabs.Trigger name="search" role="search">
{Platform.select({
{Platform.select({
//ios: <Icon sf="checklist" drawable="custom_android_drawable" />,
android: (
<Icon
src={<VectorIcon family={MaterialIcons} name="search" />}
/>
<Icon src={<VectorIcon family={MaterialIcons} name="search" />} />
),
})}
<Label>Search</Label>

View File

@@ -11,6 +11,8 @@ export default function SearchLayout() {
headerSearchBarOptions: {
placement: "automatic",
placeholder: "Search",
autoFocus: true,
shouldShowHintSearchIcon: true,
onChangeText: (event) => {
router.setParams({
globalSearch: event?.nativeEvent?.text,

View File

@@ -1,12 +1,4 @@
import { useLocalSearchParams } from "expo-router";
import { ScrollView } from "react-native";
import { Text } from "react-native-paper";
import GlobalSearch from "../../components/global-search/global-search";
export default function SearchIndex() {
const { globalSearch } = useLocalSearchParams();
return (
<ScrollView>
<Text>Some search results here for: {globalSearch}</Text>
</ScrollView>
);
return <GlobalSearch />;
}

View File

@@ -131,6 +131,27 @@
<folder_node>
<name>labels</name>
<children>
<concept_node>
<name>error</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>na</name>
<definition_loaded>false</definition_loaded>
@@ -152,6 +173,58 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>uploadprogress</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
</children>
</folder_node>
<folder_node>
<name>globalsearch</name>
<children>
<folder_node>
<name>labels</name>
<children>
<concept_node>
<name>entersearch</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
</children>
@@ -4932,6 +5005,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>wronginfo</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>wrongpassword</name>
<definition_loaded>false</definition_loaded>

View File

@@ -0,0 +1,109 @@
import axios from "axios";
import { useLocalSearchParams } from "expo-router";
import debounce from "lodash/debounce";
import { useCallback, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { FlatList, View } from "react-native";
import { ActivityIndicator, Text } from "react-native-paper";
import env from "../../env";
import ErrorDisplay from "../error/error-display";
import JobListItem from "../jobs-list/job-list-item";
// Debounce delay (ms) adjust as needed
const GLOBAL_SEARCH_DEBOUNCE_MS = 400;
/**
* Hook returning a debounced search trigger.
* It recreates the debounced function only when the underlying callback changes.
* Placeholder: Replace the body of `performSearch` with real API / GraphQL logic.
*/
function useDebouncedGlobalSearch(onSearch, delay = GLOBAL_SEARCH_DEBOUNCE_MS) {
const debouncedRef = useRef(() => {});
useEffect(() => {
// Create debounced wrapper
const debounced = debounce((query) => {
onSearch(query);
}, delay);
debouncedRef.current = debounced;
return () => debounced.cancel();
}, [onSearch, delay]);
return useCallback((query) => {
debouncedRef.current && debouncedRef.current(query);
}, []);
}
export default function GlobalSearch() {
const { globalSearch } = useLocalSearchParams();
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [results, setResults] = useState([]);
const { t } = useTranslation();
// Placeholder: Replace with actual API call (e.g., Apollo client query, REST fetch, Redux saga dispatch)
const performSearch = useCallback(async (query) => {
// Defensive trimr
const q = (query || "").trim();
if (!q) return;
setLoading(true);
setError(null);
// TODO: Integrate real search endpoint
console.log(`[GlobalSearch] (debounced placeholder) searching for: "${q}"`);
try {
const searchData = await axios.post(`${env.API_URL}/search`, {
search: q,
});
if (searchData.data) {
const jobResults = searchData.data?.hits?.hits
?.filter((hit) => hit._index === "jobs")
.map((hit) => hit._source);
setResults(jobResults);
} else {
setError("No results available. Try again.");
}
} catch (error) {
console.error("Search error:", error);
setError(error.message);
}
setLoading(false);
}, []);
const debouncedSearch = useDebouncedGlobalSearch(performSearch);
// Trigger debounced search when the route param changes
useEffect(() => {
if (typeof globalSearch === "string" && globalSearch.length > 0) {
debouncedSearch(globalSearch);
}
}, [globalSearch, debouncedSearch]);
if (globalSearch === undefined || globalSearch.trim() === "") {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text variant="bodyMedium" style={{ margin: 12, textAlign: "center" }}>
{t("globalsearch.labels.entersearch")}
</Text>
</View>
);
}
return (
<View style={{ flex: 1 }}>
{loading && <ActivityIndicator size="large" />}
{error && <ErrorDisplay errorMessage={error} />}
<Text variant="titleSmall" style={{ margin: 12, alignSelf: "center" }}>
{results.length} results found
</Text>
<FlatList
style={{ flex: 1 }}
data={results}
keyExtractor={(item) => item.id?.toString()}
renderItem={(object) => <JobListItem item={object.item} />}
/>
</View>
);
}

View File

@@ -3,7 +3,7 @@ import { useRouter } from "expo-router";
import React, { memo, useCallback } from "react";
import { useTranslation } from "react-i18next";
import { Pressable, StyleSheet, View } from "react-native";
import { IconButton, Text, useTheme } from "react-native-paper";
import { Chip, IconButton, Text, useTheme } from "react-native-paper";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { logImEXEvent } from "../../firebase/firebase.analytics";
@@ -86,6 +86,7 @@ function JobListItemComponent({ openImagePicker, item }) {
{vehicle}
</Text>
)}
<Chip style>{item.status}</Chip>
</View>
</View>
<IconButton
@@ -158,6 +159,7 @@ const styles = StyleSheet.create({
},
body: {
marginTop: 2,
flexDirection: "row", gap: 8, alignItems: "center",
},
ownerText: {
fontWeight: "600",

View File

@@ -1,313 +1,318 @@
{
"translation": {
"app": {
"nomobileaccess": "Your shop does not currently have access to ImEX Mobile. ",
"title": "ImEX Mobile"
},
"camera": {
"titles": {
"cameratab": "Camera"
}
},
"general": {
"actions": {
"signout": "Sign Out"
},
"labels": {
"na": "N/A",
"error": "Error",
"uploadprogress": "Upload Progress"
}
},
"jobdetail": {
"labels": {
"claiminformation": "Claim Information",
"dates": "Dates",
"documents": "Docs",
"employeeassignments": "Employee Assignments",
"job": "Job",
"jobinfo": "Job Information",
"lines": "Lines",
"lines_desc": "Desc.",
"lines_lb_hrs": "Hrs",
"lines_lbr_ty": "Lbr. Ty.",
"lines_part_type": "Part Ty.",
"lines_price": "$",
"lines_qty": "Qty.",
"nojobnotes": "There are no notes.",
"notes": "Notes"
},
"lbr_types": {
"LA1": "LA1",
"LA2": "LA2",
"LA3": "LA3",
"LA4": "LA4",
"LAA": "Aluminum",
"LAB": "Body",
"LAD": "Diagnostic",
"LAE": "Electrical",
"LAF": "Frame",
"LAG": "Glass",
"LAM": "Mechanical",
"LAR": "Refinish",
"LAS": "Structural",
"LAU": "User Defined"
},
"part_types": {
"CCC": "CC Cleaning",
"CCD": "CC Damage Waiver",
"CCDR": "CC Daily Rate",
"CCF": "CC Refuel",
"CCM": "CC Mileage",
"PAA": "Aftermarket",
"PAC": "Rechromed",
"PAE": "Existing",
"PAL": "LKQ",
"PAM": "Remanufactured",
"PAN": "New/OEM",
"PAO": "Other",
"PAP": "OEM Partial",
"PAR": "Recored",
"PAS": "Sublet",
"PASL": "Sublet"
}
},
"joblist": {
"actions": {
"refresh": "Refresh",
"swipecamera": "Add Pictures/Video"
},
"labels": {
"activejobs": "Jobs",
"detail": "Job Detail",
"nojobs": "There are no active jobs.",
"search": "Search..."
},
"titles": {
"jobtab": "Jobs"
}
},
"mediabrowser": {
"actions": {
"refresh": "Refresh",
"upload": "Upload"
},
"labels": {
"converting": "Converting",
"deleteafterupload": "Delete After Upload",
"localserver": "Local Server URL: {{url}}",
"nomedia": "Look's like there's no media on your device. Take some photos or videos and they will appear here.",
"selectjob": "--- Select a job ---",
"selectjobassetselector": "Please select a job to upload media. ",
"storageexceeded": "Unable to uploaded selected files because there is not sufficient space available on this job.",
"storageexceeded_title": "Unable to upload file(s)",
"storageused": "Storage Used: {{used}} / {{total}} ({{percent}}%)",
"temporarystorage": "* Temporary Storage *",
"uploading": "Uploading"
},
"titles": {
"mediabrowsertab": "Media Browser"
}
},
"mediacache": {
"actions": {
"deleteall": "Delete All",
"uploadall": "Upload All"
},
"titles": {
"mediacachetab": "Media"
}
},
"messaging": {
"titles": {
"messagingtab": "Messaging"
}
},
"more": {
"titles": {
"moretab": "More"
}
},
"objects": {
"jobs": {
"fields": {
"actual_completion": "Actual Completion",
"actual_delivery": "Actual Delivery",
"actual_in": "Actual In",
"adjustment_bottom_line": "Adjustments",
"ca_gst_registrant": "GST Registrant",
"category": "Category",
"ccc": "CC Cleaning",
"ccd": "CC Damage Waiver",
"ccdr": "CC Daily Rate",
"ccf": "CC Refuel",
"ccm": "CC Mileage",
"cieca_id": "CIECA ID",
"claim_total": "Claim Total",
"class": "Class",
"clm_no": "Claim #",
"clm_total": "Claim Total",
"csr": "Customer Service Rep.",
"customerowing": "Customer Owing",
"date_closed": "Closed",
"date_estimated": "Date Estimated",
"date_exported": "Exported",
"date_invoiced": "Invoiced",
"date_open": "Open",
"date_scheduled": "Scheduled",
"ded_amt": "Deductible",
"ded_status": "Deductible Status",
"depreciation_taxes": "Depreciation/Taxes",
"employee_body": "Body",
"employee_csr": "CSR",
"employee_prep": "Prep",
"employee_refinish": "Refinish",
"est_addr1": "Appraiser Address",
"est_co_nm": "Appraiser",
"est_ct_fn": "Appraiser First Name",
"est_ct_ln": "Appraiser Last Name",
"est_ea": "Appraiser Email",
"est_number": "Estimate #",
"est_ph1": "Appraiser Phone #",
"federal_tax_payable": "Federal Tax Payable",
"federal_tax_rate": "Federal Tax Rate",
"ins_addr1": "Insurance Co. Address",
"ins_city": "Insurance City",
"ins_co_id": "Insurance Co. ID",
"ins_co_nm": "Insurance Company Name",
"ins_ct_fn": "File Handler First Name",
"ins_ct_ln": "File Handler Last Name",
"ins_ea": "File Handler Email",
"ins_ph1": "File Handler Phone #",
"intake": {
"label": "Label",
"name": "Name",
"required": "Required?",
"type": "Type"
},
"kmin": "Mileage In",
"kmout": "Mileage Out",
"la1": "LA1",
"la2": "LA2",
"la3": "LA3",
"la4": "LA4",
"laa": "Aluminum ",
"lab": "Body",
"labor_rate_desc": "Labor Rate Name",
"lad": "Diagnostic",
"lae": "Electrical",
"laf": "Frame",
"lag": "Glass",
"lam": "Mechanical",
"lar": "Refinish",
"las": "Structural",
"lau": "LAU",
"local_tax_rate": "Local Tax Rate",
"loss_date": "Loss Date",
"loss_desc": "Loss Description",
"ma2s": "2 Stage Paint",
"ma3s": "3 Stage Pain",
"mabl": "MABL?",
"macs": "MACS?",
"mahw": "Hazardous Waste",
"mapa": "Paint Materials",
"mash": "Shop Materials",
"matd": "Tire Disposal",
"other_amount_payable": "Other Amount Payable",
"owner": "Owner",
"owner_owing": "Cust. Owes",
"ownr_ea": "Email",
"ownr_ph1": "Phone 1",
"paa": "Aftermarket",
"pae": "Existing",
"pal": "LKQ",
"pam": "Remanufactured",
"pan": "OEM/New",
"pao": "Other",
"pap": "EOM Partial",
"par": "Re-cored",
"pas": "Sublet",
"pay_date": "Pay Date",
"phoneshort": "PH",
"policy_no": "Policy #",
"ponumber": "PO Number",
"rate_la1": "LA1",
"rate_la2": "LA2",
"rate_la3": "LA3",
"rate_la4": "LA4",
"rate_laa": "Aluminum",
"rate_lab": "Body",
"rate_lad": "Diagnostic",
"rate_lae": "Electrical",
"rate_laf": "Frame",
"rate_lag": "Glass",
"rate_lam": "Mechanical",
"rate_lar": "Refinish",
"rate_las": "Sublet",
"rate_lau": "Aluminum",
"rate_ma2s": "2 Stage Paint",
"rate_ma3s": "3 Stage Paint",
"rate_mabl": "MABL??",
"rate_macs": "MACS??",
"rate_mahw": "Hazardous Waste",
"rate_mapa": "Paint Materials",
"rate_mash": "Shop Material",
"rate_matd": "Tire Disposal",
"referralsource": "Referral Source",
"regie_number": "Registration #",
"repairtotal": "Repair Total",
"ro_number": "RO #",
"scheduled_completion": "Scheduled Completion",
"scheduled_delivery": "Scheduled Delivery",
"scheduled_in": "Scheduled In",
"selling_dealer": "Selling Dealer",
"selling_dealer_contact": "Selling Dealer Contact",
"servicecar": "Service Car",
"servicing_dealer": "Servicing Dealer",
"servicing_dealer_contact": "Servicing Dealer Contact",
"specialcoveragepolicy": "Special Coverage Policy",
"state_tax_rate": "State Tax Rate",
"status": "Job Status",
"storage_payable": "Storage/PVRT",
"tax_registration_number": "Tax Registration Number",
"towing_payable": "Towing Payable",
"unitnumber": "Unit #",
"updated_at": "Updated At",
"uploaded_by": "Uploaded By",
"vehicle": "Vehicle"
},
"labels": {
"inproduction": "In Production"
}
}
},
"production": {
"titles": {
"production": "Production"
}
},
"settings": {
"labels": {
"version": "Version {{number}}"
},
"titles": {
"settings": "Settings"
}
},
"signin": {
"actions": {
"signin": "Sign In"
},
"errors": {
"emailformat": "The email you have entered is not formatted correctly. ",
"usernotfound": "No user found.",
"wronginfo": "The email or password you entered is not correct.",
"wrongpassword": "The password you entered is not correct."
},
"fields": {
"email": "Email",
"password": "Password"
}
}
}
"translation": {
"app": {
"nomobileaccess": "Your shop does not currently have access to ImEX Mobile. ",
"title": "ImEX Mobile"
},
"camera": {
"titles": {
"cameratab": "Camera"
}
},
"general": {
"actions": {
"signout": "Sign Out"
},
"labels": {
"error": "Error",
"na": "N/A",
"uploadprogress": "Upload Progress"
}
},
"globalsearch": {
"labels": {
"entersearch": "Recent items"
}
},
"jobdetail": {
"labels": {
"claiminformation": "Claim Information",
"dates": "Dates",
"documents": "Docs",
"employeeassignments": "Employee Assignments",
"job": "Job",
"jobinfo": "Job Information",
"lines": "Lines",
"lines_desc": "Desc.",
"lines_lb_hrs": "Hrs",
"lines_lbr_ty": "Lbr. Ty.",
"lines_part_type": "Part Ty.",
"lines_price": "$",
"lines_qty": "Qty.",
"nojobnotes": "There are no notes.",
"notes": "Notes"
},
"lbr_types": {
"LA1": "LA1",
"LA2": "LA2",
"LA3": "LA3",
"LA4": "LA4",
"LAA": "Aluminum",
"LAB": "Body",
"LAD": "Diagnostic",
"LAE": "Electrical",
"LAF": "Frame",
"LAG": "Glass",
"LAM": "Mechanical",
"LAR": "Refinish",
"LAS": "Structural",
"LAU": "User Defined"
},
"part_types": {
"CCC": "CC Cleaning",
"CCD": "CC Damage Waiver",
"CCDR": "CC Daily Rate",
"CCF": "CC Refuel",
"CCM": "CC Mileage",
"PAA": "Aftermarket",
"PAC": "Rechromed",
"PAE": "Existing",
"PAL": "LKQ",
"PAM": "Remanufactured",
"PAN": "New/OEM",
"PAO": "Other",
"PAP": "OEM Partial",
"PAR": "Recored",
"PAS": "Sublet",
"PASL": "Sublet"
}
},
"joblist": {
"actions": {
"refresh": "Refresh",
"swipecamera": "Add Pictures/Video"
},
"labels": {
"activejobs": "Jobs",
"detail": "Job Detail",
"nojobs": "There are no active jobs.",
"search": "Search..."
},
"titles": {
"jobtab": "Jobs"
}
},
"mediabrowser": {
"actions": {
"refresh": "Refresh",
"upload": "Upload"
},
"labels": {
"converting": "Converting",
"deleteafterupload": "Delete After Upload",
"localserver": "Local Server URL: {{url}}",
"nomedia": "Look's like there's no media on your device. Take some photos or videos and they will appear here.",
"selectjob": "--- Select a job ---",
"selectjobassetselector": "Please select a job to upload media. ",
"storageexceeded": "Unable to uploaded selected files because there is not sufficient space available on this job.",
"storageexceeded_title": "Unable to upload file(s)",
"storageused": "Storage Used: {{used}} / {{total}} ({{percent}}%)",
"temporarystorage": "* Temporary Storage *",
"uploading": "Uploading"
},
"titles": {
"mediabrowsertab": "Media Browser"
}
},
"mediacache": {
"actions": {
"deleteall": "Delete All",
"uploadall": "Upload All"
},
"titles": {
"mediacachetab": "Media"
}
},
"messaging": {
"titles": {
"messagingtab": "Messaging"
}
},
"more": {
"titles": {
"moretab": "More"
}
},
"objects": {
"jobs": {
"fields": {
"actual_completion": "Actual Completion",
"actual_delivery": "Actual Delivery",
"actual_in": "Actual In",
"adjustment_bottom_line": "Adjustments",
"ca_gst_registrant": "GST Registrant",
"category": "Category",
"ccc": "CC Cleaning",
"ccd": "CC Damage Waiver",
"ccdr": "CC Daily Rate",
"ccf": "CC Refuel",
"ccm": "CC Mileage",
"cieca_id": "CIECA ID",
"claim_total": "Claim Total",
"class": "Class",
"clm_no": "Claim #",
"clm_total": "Claim Total",
"csr": "Customer Service Rep.",
"customerowing": "Customer Owing",
"date_closed": "Closed",
"date_estimated": "Date Estimated",
"date_exported": "Exported",
"date_invoiced": "Invoiced",
"date_open": "Open",
"date_scheduled": "Scheduled",
"ded_amt": "Deductible",
"ded_status": "Deductible Status",
"depreciation_taxes": "Depreciation/Taxes",
"employee_body": "Body",
"employee_csr": "CSR",
"employee_prep": "Prep",
"employee_refinish": "Refinish",
"est_addr1": "Appraiser Address",
"est_co_nm": "Appraiser",
"est_ct_fn": "Appraiser First Name",
"est_ct_ln": "Appraiser Last Name",
"est_ea": "Appraiser Email",
"est_number": "Estimate #",
"est_ph1": "Appraiser Phone #",
"federal_tax_payable": "Federal Tax Payable",
"federal_tax_rate": "Federal Tax Rate",
"ins_addr1": "Insurance Co. Address",
"ins_city": "Insurance City",
"ins_co_id": "Insurance Co. ID",
"ins_co_nm": "Insurance Company Name",
"ins_ct_fn": "File Handler First Name",
"ins_ct_ln": "File Handler Last Name",
"ins_ea": "File Handler Email",
"ins_ph1": "File Handler Phone #",
"intake": {
"label": "Label",
"name": "Name",
"required": "Required?",
"type": "Type"
},
"kmin": "Mileage In",
"kmout": "Mileage Out",
"la1": "LA1",
"la2": "LA2",
"la3": "LA3",
"la4": "LA4",
"laa": "Aluminum ",
"lab": "Body",
"labor_rate_desc": "Labor Rate Name",
"lad": "Diagnostic",
"lae": "Electrical",
"laf": "Frame",
"lag": "Glass",
"lam": "Mechanical",
"lar": "Refinish",
"las": "Structural",
"lau": "LAU",
"local_tax_rate": "Local Tax Rate",
"loss_date": "Loss Date",
"loss_desc": "Loss Description",
"ma2s": "2 Stage Paint",
"ma3s": "3 Stage Pain",
"mabl": "MABL?",
"macs": "MACS?",
"mahw": "Hazardous Waste",
"mapa": "Paint Materials",
"mash": "Shop Materials",
"matd": "Tire Disposal",
"other_amount_payable": "Other Amount Payable",
"owner": "Owner",
"owner_owing": "Cust. Owes",
"ownr_ea": "Email",
"ownr_ph1": "Phone 1",
"paa": "Aftermarket",
"pae": "Existing",
"pal": "LKQ",
"pam": "Remanufactured",
"pan": "OEM/New",
"pao": "Other",
"pap": "EOM Partial",
"par": "Re-cored",
"pas": "Sublet",
"pay_date": "Pay Date",
"phoneshort": "PH",
"policy_no": "Policy #",
"ponumber": "PO Number",
"rate_la1": "LA1",
"rate_la2": "LA2",
"rate_la3": "LA3",
"rate_la4": "LA4",
"rate_laa": "Aluminum",
"rate_lab": "Body",
"rate_lad": "Diagnostic",
"rate_lae": "Electrical",
"rate_laf": "Frame",
"rate_lag": "Glass",
"rate_lam": "Mechanical",
"rate_lar": "Refinish",
"rate_las": "Sublet",
"rate_lau": "Aluminum",
"rate_ma2s": "2 Stage Paint",
"rate_ma3s": "3 Stage Paint",
"rate_mabl": "MABL??",
"rate_macs": "MACS??",
"rate_mahw": "Hazardous Waste",
"rate_mapa": "Paint Materials",
"rate_mash": "Shop Material",
"rate_matd": "Tire Disposal",
"referralsource": "Referral Source",
"regie_number": "Registration #",
"repairtotal": "Repair Total",
"ro_number": "RO #",
"scheduled_completion": "Scheduled Completion",
"scheduled_delivery": "Scheduled Delivery",
"scheduled_in": "Scheduled In",
"selling_dealer": "Selling Dealer",
"selling_dealer_contact": "Selling Dealer Contact",
"servicecar": "Service Car",
"servicing_dealer": "Servicing Dealer",
"servicing_dealer_contact": "Servicing Dealer Contact",
"specialcoveragepolicy": "Special Coverage Policy",
"state_tax_rate": "State Tax Rate",
"status": "Job Status",
"storage_payable": "Storage/PVRT",
"tax_registration_number": "Tax Registration Number",
"towing_payable": "Towing Payable",
"unitnumber": "Unit #",
"updated_at": "Updated At",
"uploaded_by": "Uploaded By",
"vehicle": "Vehicle"
},
"labels": {
"inproduction": "In Production"
}
}
},
"production": {
"titles": {
"production": "Production"
}
},
"settings": {
"labels": {
"version": "Version {{number}}"
},
"titles": {
"settings": "Settings"
}
},
"signin": {
"actions": {
"signin": "Sign In"
},
"errors": {
"emailformat": "The email you have entered is not formatted correctly. ",
"usernotfound": "No user found.",
"wronginfo": "The email or password you entered is not correct.",
"wrongpassword": "The password you entered is not correct."
},
"fields": {
"email": "Email",
"password": "Password"
}
}
}
}

View File

@@ -14,7 +14,14 @@
"signout": ""
},
"labels": {
"na": ""
"error": "",
"na": "",
"uploadprogress": ""
}
},
"globalsearch": {
"labels": {
"entersearch": ""
}
},
"jobdetail": {
@@ -299,6 +306,7 @@
"errors": {
"emailformat": "",
"usernotfound": "",
"wronginfo": "",
"wrongpassword": ""
},
"fields": {

View File

@@ -14,7 +14,14 @@
"signout": ""
},
"labels": {
"na": ""
"error": "",
"na": "",
"uploadprogress": ""
}
},
"globalsearch": {
"labels": {
"entersearch": ""
}
},
"jobdetail": {
@@ -299,6 +306,7 @@
"errors": {
"emailformat": "",
"usernotfound": "",
"wronginfo": "",
"wrongpassword": ""
},
"fields": {