Complete the home, profile and battery screens
parent
f85f43f968
commit
d1fbd92b2e
|
|
@ -2,16 +2,18 @@ import React, { useEffect } from "react";
|
||||||
import { Tabs } from "expo-router";
|
import { Tabs } from "expo-router";
|
||||||
import { useTabConfig } from "@/constants/config";
|
import { useTabConfig } from "@/constants/config";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { RootState } from "@/store";
|
import { AppDispatch, RootState } from "@/store";
|
||||||
import { initSocket } from "@/services/socket";
|
import { initSocket } from "@/services/socket";
|
||||||
import { useSnackbar } from "@/contexts/Snackbar";
|
import { useSnackbar } from "@/contexts/Snackbar";
|
||||||
import NetInfo from "@react-native-community/netinfo";
|
import NetInfo from "@react-native-community/netinfo";
|
||||||
|
import { getUserDetails } from "@/store/userSlice";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
|
||||||
export default function TabLayout() {
|
export default function TabLayout() {
|
||||||
const { isLoggedIn } = useSelector((state: RootState) => state.auth);
|
const { isLoggedIn } = useSelector((state: RootState) => state.auth);
|
||||||
if (!isLoggedIn) return null;
|
if (!isLoggedIn) return null;
|
||||||
const TAB_CONFIG = useTabConfig();
|
const TAB_CONFIG = useTabConfig();
|
||||||
|
const dispatch = useDispatch<AppDispatch>();
|
||||||
const { showSnackbar } = useSnackbar();
|
const { showSnackbar } = useSnackbar();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribe = NetInfo.addEventListener((state) => {
|
const unsubscribe = NetInfo.addEventListener((state) => {
|
||||||
|
|
@ -29,7 +31,20 @@ export default function TabLayout() {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initSocket();
|
const fetchAndInit = async () => {
|
||||||
|
try {
|
||||||
|
const result = await dispatch(getUserDetails()).unwrap();
|
||||||
|
console.log("User details fetched", result);
|
||||||
|
initSocket();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to fetch user details", error);
|
||||||
|
showSnackbar("Failed to fetch user details", "error");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isLoggedIn) {
|
||||||
|
fetchAndInit();
|
||||||
|
}
|
||||||
}, [isLoggedIn]);
|
}, [isLoggedIn]);
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,13 @@ import MapView, { Marker, PROVIDER_GOOGLE } from "react-native-maps";
|
||||||
import BatteryWarrantyCard from "@/components/home/BatteryWarrantyCars";
|
import BatteryWarrantyCard from "@/components/home/BatteryWarrantyCars";
|
||||||
import CustomerSupportModal from "@/components/home/CustomerSupportModal";
|
import CustomerSupportModal from "@/components/home/CustomerSupportModal";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { RootState } from "@/store";
|
import { AppDispatch, RootState } from "@/store";
|
||||||
import LocationOff from "@/assets/icons/location_off.svg";
|
import LocationOff from "@/assets/icons/location_off.svg";
|
||||||
import { Linking } from "react-native";
|
import { Linking } from "react-native";
|
||||||
import { useRouter } from "expo-router";
|
import { useRouter } from "expo-router";
|
||||||
import ProfileImage from "@/components/home/Profile";
|
import ProfileImage from "@/components/home/Profile";
|
||||||
import { calculateBearing, calculateDistance } from "@/utils/Map";
|
import { calculateBearing, calculateDistance } from "@/utils/Map";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
|
||||||
export default function HomeScreen() {
|
export default function HomeScreen() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
@ -31,11 +32,26 @@ export default function HomeScreen() {
|
||||||
const [isSupportModalVisible, setIsSupportModalVisible] = useState(false);
|
const [isSupportModalVisible, setIsSupportModalVisible] = useState(false);
|
||||||
const { SoC, SoH, chargingState, lat, lon, loading, error, totalDistance } =
|
const { SoC, SoH, chargingState, lat, lon, loading, error, totalDistance } =
|
||||||
useSelector((state: RootState) => state.telemetry);
|
useSelector((state: RootState) => state.telemetry);
|
||||||
|
const { data } = useSelector((state: RootState) => state.user);
|
||||||
const [prevPosition, setPrevPosition] = useState<{
|
const [prevPosition, setPrevPosition] = useState<{
|
||||||
lat: number;
|
lat: number;
|
||||||
lon: number;
|
lon: number;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
const [bearing, setBearing] = useState<number>(0);
|
const [bearing, setBearing] = useState<number>(0);
|
||||||
|
const dispatch = useDispatch<AppDispatch>();
|
||||||
|
const vehicle =
|
||||||
|
Array.isArray(data?.vehicles) && data.vehicles.length > 0
|
||||||
|
? data.vehicles[0]
|
||||||
|
: null;
|
||||||
|
const battery =
|
||||||
|
Array.isArray(data?.batteries) && data.batteries.length > 0
|
||||||
|
? data.batteries[0]
|
||||||
|
: null;
|
||||||
|
|
||||||
|
const model = vehicle?.model ?? "---";
|
||||||
|
const chasisNumber = vehicle?.chasis_number ?? "---";
|
||||||
|
const warrantyStartDate = data?.batteries[0]?.warranty_start_date || null;
|
||||||
|
const warrantyEndDate = data?.batteries[0]?.warranty_end_date || null;
|
||||||
|
|
||||||
const step = 0.001;
|
const step = 0.001;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -83,8 +99,8 @@ export default function HomeScreen() {
|
||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
headerTitle: () => (
|
headerTitle: () => (
|
||||||
<View style={styles.headerTitleContainer}>
|
<View style={styles.headerTitleContainer}>
|
||||||
<Text style={styles.title}>Yatri - NBX 600</Text>
|
<Text style={styles.title}>{model}</Text>
|
||||||
<Text style={styles.subtitle}>DL253C3602</Text>
|
<Text style={styles.subtitle}>{chasisNumber}</Text>
|
||||||
</View>
|
</View>
|
||||||
),
|
),
|
||||||
headerRight: () => (
|
headerRight: () => (
|
||||||
|
|
@ -104,7 +120,7 @@ export default function HomeScreen() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ProfileImage
|
<ProfileImage
|
||||||
username="Vivek"
|
username={data?.name || "User"}
|
||||||
onClick={() => router.push("/user/profile")}
|
onClick={() => router.push("/user/profile")}
|
||||||
textSize={20}
|
textSize={20}
|
||||||
boxSize={40}
|
boxSize={40}
|
||||||
|
|
@ -113,7 +129,7 @@ export default function HomeScreen() {
|
||||||
</View>
|
</View>
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}, [navigation]);
|
}, [navigation, data, model, chasisNumber]);
|
||||||
|
|
||||||
const openInGoogleMaps = () => {
|
const openInGoogleMaps = () => {
|
||||||
const url = `https://www.google.com/maps/search/?api=1&query=${lat},${lon}`;
|
const url = `https://www.google.com/maps/search/?api=1&query=${lat},${lon}`;
|
||||||
|
|
@ -199,13 +215,12 @@ export default function HomeScreen() {
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
{warrantyEndDate && warrantyStartDate && (
|
||||||
<BatteryWarrantyCard
|
<BatteryWarrantyCard
|
||||||
totalWarrantyYears={8}
|
warrantyStartDate={warrantyStartDate}
|
||||||
batteryPurchaseEpoch={Math.floor(
|
warrantyEndDate={warrantyEndDate}
|
||||||
new Date("2023-06-30").getTime() / 1000
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<CustomerSupportModal
|
<CustomerSupportModal
|
||||||
visible={isSupportModalVisible}
|
visible={isSupportModalVisible}
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,172 @@
|
||||||
import { StyleSheet } from "react-native";
|
import { RootState } from "@/store";
|
||||||
|
import React from "react";
|
||||||
|
import { View, Text, StyleSheet, ScrollView } from "react-native";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
const BatteryDetails = () => {
|
||||||
|
const { data } = useSelector((state: RootState) => state.user);
|
||||||
|
|
||||||
import { Text, View } from "react-native";
|
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 start = new Date(warrantyStartDate);
|
||||||
|
const end = new Date(warrantyEndDate);
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
export default function MyBatteryTabScreen() {
|
const totalDuration = end.getTime() - start.getTime();
|
||||||
return (
|
const elapsed = now.getTime() - start.getTime();
|
||||||
<View style={styles.container}>
|
const remaining = Math.max(end.getTime() - now.getTime(), 0);
|
||||||
<Text style={styles.title}>Coming Soon</Text>
|
|
||||||
</View>
|
const 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)
|
||||||
|
);
|
||||||
|
|
||||||
|
const formatDate = (date: Date): string =>
|
||||||
|
date.toLocaleDateString("en-GB", {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "short",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ScrollView contentContainerStyle={styles.container}>
|
||||||
|
{/* Battery Card */}
|
||||||
|
<View style={styles.card}>
|
||||||
|
<View style={styles.cardHeader}>
|
||||||
|
<Text style={styles.cardTitle}>Battery</Text>
|
||||||
|
<View style={styles.badge}>
|
||||||
|
<Text style={styles.badgeText}>In Warranty</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={styles.divider} />
|
||||||
|
<InfoRow label="Model" value={model} />
|
||||||
|
<InfoRow label="Battery ID" value={batteryId} />
|
||||||
|
<InfoRow label="BMS ID" value={bmsId} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Warranty Details */}
|
||||||
|
<View style={styles.card}>
|
||||||
|
<Text style={styles.cardTitle}>Battery Warranty Details</Text>
|
||||||
|
<View style={styles.divider} />
|
||||||
|
<InfoRow label="Start Date" value={formatDate(start)} />
|
||||||
|
<InfoRow label="End Date" value={formatDate(end)} />
|
||||||
|
<InfoRow
|
||||||
|
label="Duration Left"
|
||||||
|
value={`${yearsLeft} years, ${monthsLeft} months, ${daysLeft} days`}
|
||||||
|
/>
|
||||||
|
<View style={styles.progressBarBackground}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.progressBarFill,
|
||||||
|
{ width: `${(1 - progress) * 100}%` },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* VIM Details */}
|
||||||
|
<View style={styles.card}>
|
||||||
|
<Text style={styles.cardTitle}>VIM Details</Text>
|
||||||
|
<View style={styles.divider} />
|
||||||
|
<InfoRow label="VIM ID" value={vimId} />
|
||||||
|
<InfoRow label="Serial Number" value={serialNumber} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Charger Details */}
|
||||||
|
<View style={styles.card}>
|
||||||
|
<Text style={styles.cardTitle}>Charger Details</Text>
|
||||||
|
<View style={styles.divider} />
|
||||||
|
<InfoRow label="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({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
backgroundColor: "#F3F5F8",
|
||||||
|
padding: 16,
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
backgroundColor: "#FCFCFC",
|
||||||
|
borderRadius: 8,
|
||||||
|
padding: 12,
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
cardHeader: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
|
||||||
},
|
},
|
||||||
title: {
|
cardTitle: {
|
||||||
fontSize: 20,
|
fontSize: 14,
|
||||||
fontWeight: "bold",
|
fontWeight: "600",
|
||||||
|
color: "#252A34",
|
||||||
},
|
},
|
||||||
separator: {
|
badge: {
|
||||||
marginVertical: 30,
|
backgroundColor: "#DAF5ED",
|
||||||
|
paddingVertical: 2,
|
||||||
|
paddingHorizontal: 8,
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
badgeText: {
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: "500",
|
||||||
|
color: "#006C4D",
|
||||||
|
},
|
||||||
|
divider: {
|
||||||
height: 1,
|
height: 1,
|
||||||
width: "80%",
|
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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ export default function AuthLayout() {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="login"
|
name="profile"
|
||||||
options={{
|
options={{
|
||||||
headerShown: true,
|
headerShown: true,
|
||||||
title: "My Account",
|
title: "My Account",
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
"expo": "^53.0.13",
|
"expo": "^53.0.13",
|
||||||
"expo-constants": "~17.1.6",
|
"expo-constants": "~17.1.6",
|
||||||
"expo-font": "~13.3.1",
|
"expo-font": "~13.3.1",
|
||||||
|
"expo-image-picker": "~16.1.4",
|
||||||
"expo-linking": "~7.1.5",
|
"expo-linking": "~7.1.5",
|
||||||
"expo-router": "~5.1.1",
|
"expo-router": "~5.1.1",
|
||||||
"expo-secure-store": "^14.2.3",
|
"expo-secure-store": "^14.2.3",
|
||||||
|
|
@ -31,6 +32,7 @@
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "19.0.0",
|
||||||
"react-i18next": "^15.5.3",
|
"react-i18next": "^15.5.3",
|
||||||
"react-native": "0.79.4",
|
"react-native": "0.79.4",
|
||||||
|
"react-native-element-dropdown": "^2.12.4",
|
||||||
"react-native-maps": "^1.24.3",
|
"react-native-maps": "^1.24.3",
|
||||||
"react-native-otp-entry": "^1.8.5",
|
"react-native-otp-entry": "^1.8.5",
|
||||||
"react-native-paper": "^5.14.5",
|
"react-native-paper": "^5.14.5",
|
||||||
|
|
@ -7038,6 +7040,27 @@
|
||||||
"react": "*"
|
"react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-image-loader": {
|
||||||
|
"version": "5.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-5.1.0.tgz",
|
||||||
|
"integrity": "sha512-sEBx3zDQIODWbB5JwzE7ZL5FJD+DK3LVLWBVJy6VzsqIA6nDEnSFnsnWyCfCTSvbGigMATs1lgkC2nz3Jpve1Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/expo-image-picker": {
|
||||||
|
"version": "16.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-16.1.4.tgz",
|
||||||
|
"integrity": "sha512-bTmmxtw1AohUT+HxEBn2vYwdeOrj1CLpMXKjvi9FKSoSbpcarT4xxI0z7YyGwDGHbrJqyyic3I9TTdP2J2b4YA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"expo-image-loader": "~5.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-keep-awake": {
|
"node_modules/expo-keep-awake": {
|
||||||
"version": "14.1.4",
|
"version": "14.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-14.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-14.1.4.tgz",
|
||||||
|
|
@ -11858,6 +11881,22 @@
|
||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-element-dropdown": {
|
||||||
|
"version": "2.12.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-element-dropdown/-/react-native-element-dropdown-2.12.4.tgz",
|
||||||
|
"integrity": "sha512-abZc5SVji9FIt7fjojRYrbuvp03CoeZJrgvezQoDoSOrpiTqkX69ix5m+j06W2AVncA0VWvbT+vCMam8SoVadw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"lodash": "^4.17.21"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native-gesture-handler": {
|
"node_modules/react-native-gesture-handler": {
|
||||||
"version": "2.26.0",
|
"version": "2.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.26.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
"expo": "^53.0.13",
|
"expo": "^53.0.13",
|
||||||
"expo-constants": "~17.1.6",
|
"expo-constants": "~17.1.6",
|
||||||
"expo-font": "~13.3.1",
|
"expo-font": "~13.3.1",
|
||||||
|
"expo-image-picker": "~16.1.4",
|
||||||
"expo-linking": "~7.1.5",
|
"expo-linking": "~7.1.5",
|
||||||
"expo-router": "~5.1.1",
|
"expo-router": "~5.1.1",
|
||||||
"expo-secure-store": "^14.2.3",
|
"expo-secure-store": "^14.2.3",
|
||||||
|
|
@ -36,6 +37,7 @@
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "19.0.0",
|
||||||
"react-i18next": "^15.5.3",
|
"react-i18next": "^15.5.3",
|
||||||
"react-native": "0.79.4",
|
"react-native": "0.79.4",
|
||||||
|
"react-native-element-dropdown": "^2.12.4",
|
||||||
"react-native-maps": "^1.24.3",
|
"react-native-maps": "^1.24.3",
|
||||||
"react-native-otp-entry": "^1.8.5",
|
"react-native-otp-entry": "^1.8.5",
|
||||||
"react-native-paper": "^5.14.5",
|
"react-native-paper": "^5.14.5",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue