240 lines
6.5 KiB
TypeScript
240 lines
6.5 KiB
TypeScript
import { RootState } from "@/store";
|
|
import React from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { View, Text, StyleSheet, ScrollView } from "react-native";
|
|
import { useSelector } from "react-redux";
|
|
const BatteryDetails = () => {
|
|
const { data } = useSelector((state: RootState) => state.user);
|
|
const { t } = useTranslation();
|
|
const model = data?.batteries[0]?.battery_model ?? "---";
|
|
const batteryId = data?.batteries[0]?.battery_id ?? "---";
|
|
const bmsId = data?.batteries[0]?.bms_id ?? "---";
|
|
const warrantyStartDate = data?.batteries[0]?.warranty_start_date ?? "---";
|
|
const warrantyEndDate = data?.batteries[0]?.warranty_end_date ?? "---";
|
|
const vimId = data?.batteries[0]?.vim_id ?? "---";
|
|
const serialNumber = data?.batteries[0]?.serial_no ?? "---";
|
|
const chargerUid = data?.batteries[0]?.charger_uid ?? "---";
|
|
const battery = data?.batteries?.[0];
|
|
|
|
const start = battery?.warranty_start_date
|
|
? new Date(battery.warranty_start_date)
|
|
: null;
|
|
const end = battery?.warranty_end_date
|
|
? new Date(battery.warranty_end_date)
|
|
: null;
|
|
const now = new Date();
|
|
|
|
let progress = 0;
|
|
let durationText = "---";
|
|
|
|
if (
|
|
start &&
|
|
end &&
|
|
!isNaN(start.getTime()) &&
|
|
!isNaN(end.getTime()) &&
|
|
now < end
|
|
) {
|
|
const totalDuration = end.getTime() - start.getTime();
|
|
const elapsed = now.getTime() - start.getTime();
|
|
const remaining = Math.max(end.getTime() - now.getTime(), 0);
|
|
|
|
progress = Math.min(elapsed / totalDuration, 1);
|
|
|
|
const yearsLeft = Math.floor(remaining / (365.25 * 24 * 60 * 60 * 1000));
|
|
const monthsLeft = Math.floor(
|
|
(remaining % (365.25 * 24 * 60 * 60 * 1000)) /
|
|
(30.44 * 24 * 60 * 60 * 1000)
|
|
);
|
|
const daysLeft = Math.floor(
|
|
(remaining % (30.44 * 24 * 60 * 60 * 1000)) / (24 * 60 * 60 * 1000)
|
|
);
|
|
|
|
durationText = (() => {
|
|
const parts: string[] = [];
|
|
|
|
if (yearsLeft > 0) {
|
|
parts.push(`${yearsLeft} ${t("home.year")}`);
|
|
}
|
|
|
|
if (monthsLeft > 0) {
|
|
parts.push(`${monthsLeft} ${t("home.month")}`);
|
|
}
|
|
|
|
if (daysLeft > 0 || parts.length === 0) {
|
|
parts.push(`${daysLeft} ${t("home.day")}`);
|
|
}
|
|
|
|
return parts.join(", ");
|
|
})();
|
|
}
|
|
|
|
const formatDate = (date?: Date | null): string =>
|
|
date && !isNaN(date.getTime())
|
|
? date.toLocaleDateString("en-GB", {
|
|
day: "2-digit",
|
|
month: "short",
|
|
year: "numeric",
|
|
})
|
|
: "---";
|
|
|
|
const isInWarranty =
|
|
start &&
|
|
end &&
|
|
now >= start &&
|
|
now <= end &&
|
|
!isNaN(start.getTime()) &&
|
|
!isNaN(end.getTime());
|
|
|
|
return (
|
|
<ScrollView contentContainerStyle={styles.container}>
|
|
{/* Battery Section */}
|
|
<View style={styles.card}>
|
|
<View style={styles.cardHeader}>
|
|
<Text style={styles.cardTitle}>{t("battery.battery")}</Text>
|
|
{isInWarranty ? (
|
|
<View style={styles.badge}>
|
|
<Text style={styles.badgeText}>{t("battery.in-warranty")}</Text>
|
|
</View>
|
|
) : (
|
|
<View style={styles.expiredBadge}>
|
|
<Text style={styles.expiredBadgeText}>
|
|
{t("battery.warranty-expired")}
|
|
</Text>
|
|
</View>
|
|
)}
|
|
</View>
|
|
<View style={styles.divider} />
|
|
<InfoRow label={t("battery.model")} value={model} />
|
|
<InfoRow label={t("battery.battery-id")} value={batteryId} />
|
|
<InfoRow label={t("battery.bms-id")} value={bmsId} />
|
|
</View>
|
|
|
|
{/* Battery Warranty Details Section */}
|
|
<View style={styles.card}>
|
|
<Text style={styles.cardTitle}>
|
|
{t("battery.battery-warranty-details")}
|
|
</Text>
|
|
<View style={styles.divider} />
|
|
<InfoRow label={t("battery.start-date")} value={formatDate(start)} />
|
|
<InfoRow label={t("battery.end-date")} value={formatDate(end)} />
|
|
<InfoRow label={t("battery.duration-left")} value={durationText} />
|
|
{start && end && !isNaN(start.getTime()) && !isNaN(end.getTime()) && (
|
|
<View style={styles.progressBarBackground}>
|
|
<View
|
|
style={[
|
|
styles.progressBarFill,
|
|
{ width: `${(1 - progress) * 100}%` },
|
|
]}
|
|
/>
|
|
</View>
|
|
)}
|
|
</View>
|
|
|
|
{/* VIM Details Section */}
|
|
<View style={styles.card}>
|
|
<Text style={styles.cardTitle}>{t("battery.vim-details")}</Text>
|
|
<View style={styles.divider} />
|
|
<InfoRow label={t("battery.vim-id")} value={vimId} />
|
|
<InfoRow label={t("battery.serial-number")} value={serialNumber} />
|
|
</View>
|
|
|
|
{/* Charger Details Section */}
|
|
<View style={styles.card}>
|
|
<Text style={styles.cardTitle}>{t("battery.charger-details")}</Text>
|
|
<View style={styles.divider} />
|
|
<InfoRow label={t("battery.uid")} value={chargerUid} />
|
|
</View>
|
|
</ScrollView>
|
|
);
|
|
};
|
|
|
|
type InfoRowProps = {
|
|
label: string;
|
|
value: string;
|
|
};
|
|
|
|
const InfoRow: React.FC<InfoRowProps> = ({ label, value }) => (
|
|
<View style={styles.infoRow}>
|
|
<Text style={styles.label}>{label}</Text>
|
|
<Text style={styles.value}>{value}</Text>
|
|
</View>
|
|
);
|
|
|
|
export default BatteryDetails;
|
|
|
|
const styles = StyleSheet.create({
|
|
expiredBadgeText: {
|
|
fontSize: 12,
|
|
fontWeight: "500",
|
|
color: "#D51D10",
|
|
},
|
|
container: {
|
|
backgroundColor: "#F3F5F8",
|
|
paddingHorizontal: 16,
|
|
},
|
|
card: {
|
|
backgroundColor: "#FCFCFC",
|
|
borderRadius: 8,
|
|
padding: 12,
|
|
marginBottom: 16,
|
|
},
|
|
cardHeader: {
|
|
flexDirection: "row",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
},
|
|
cardTitle: {
|
|
fontSize: 14,
|
|
fontWeight: "600",
|
|
color: "#252A34",
|
|
},
|
|
expiredBadge: {
|
|
backgroundColor: "#FDE9E7",
|
|
paddingVertical: 2,
|
|
paddingHorizontal: 8,
|
|
borderRadius: 4,
|
|
},
|
|
badge: {
|
|
backgroundColor: "#DAF5ED",
|
|
paddingVertical: 2,
|
|
paddingHorizontal: 8,
|
|
borderRadius: 4,
|
|
},
|
|
badgeText: {
|
|
fontSize: 12,
|
|
fontWeight: "500",
|
|
color: "#006C4D",
|
|
},
|
|
divider: {
|
|
height: 1,
|
|
backgroundColor: "#e5e9f0",
|
|
marginVertical: 12,
|
|
},
|
|
infoRow: {
|
|
flexDirection: "row",
|
|
justifyContent: "space-between",
|
|
paddingVertical: 4,
|
|
},
|
|
label: {
|
|
fontSize: 14,
|
|
color: "#252A34",
|
|
},
|
|
value: {
|
|
fontSize: 14,
|
|
fontWeight: "600",
|
|
color: "#252A34",
|
|
},
|
|
progressBarBackground: {
|
|
height: 8,
|
|
backgroundColor: "#E5E9F0",
|
|
borderRadius: 10,
|
|
overflow: "hidden",
|
|
marginTop: 16,
|
|
},
|
|
progressBarFill: {
|
|
height: 8,
|
|
backgroundColor: "#00825B",
|
|
borderRadius: 10,
|
|
},
|
|
});
|