Skip to content

Commit

Permalink
Merge pull request PapillonApp#379 from raphckrman/fix/canteen-bugs
Browse files Browse the repository at this point in the history
Détection de prix pour ARD + Divers fixs
  • Loading branch information
tryon-dev authored Nov 27, 2024
2 parents 51ad31a + a134e37 commit 7335eab
Show file tree
Hide file tree
Showing 14 changed files with 231 additions and 238 deletions.
81 changes: 9 additions & 72 deletions src/components/Restaurant/AccountButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,66 +22,8 @@ interface AccountButtonProps {
}

const AccountButton: React.FC<AccountButtonProps> = ({ account, isSelected, onPress, colors }) => {
const COLLAPSED_WIDTH = 47;
const [textMeasurement, setTextMeasurement] = React.useState(0);
const EXPANDED_WIDTH = React.useMemo(() => COLLAPSED_WIDTH + textMeasurement + 16, [textMeasurement]); // 16 pour le gap

const width = useSharedValue(isSelected ? EXPANDED_WIDTH : COLLAPSED_WIDTH);
const textOpacity = useSharedValue(isSelected ? 1 : 0);
const textScale = useSharedValue(isSelected ? 1 : 0.7);
const textWidth = useSharedValue(isSelected ? textMeasurement : 0);

const springConfig = {
damping: 15,
mass: 0.5,
stiffness: 120,
};

const animatedContainerStyle = useAnimatedStyle(() => ({
width: withSpring(width.value, springConfig),
}));

const animatedTextContainerStyle = useAnimatedStyle(() => ({
width: withTiming(textWidth.value, {
duration: 150,
easing: Easing.bezier(0.4, 0.0, 0.2, 1),
}),
}));

const animatedTextStyle = useAnimatedStyle(() => ({
opacity: withTiming(textOpacity.value, {
duration: 150,
easing: Easing.ease,
}),
transform: [{ scale: withTiming(textScale.value, { duration: 150 }) }],
}));

React.useEffect(() => {
if (textMeasurement > 0) {
width.value = isSelected ? EXPANDED_WIDTH : COLLAPSED_WIDTH;
textOpacity.value = isSelected ? 1 : 0;
textScale.value = isSelected ? 1 : 0.7;
textWidth.value = isSelected ? textMeasurement : 0;
}
}, [isSelected, textMeasurement]);

return (
<>
{/* Composant de mesure invisible */}
<Text
style={{
position: "absolute",
opacity: 0,
fontSize: 13,
fontFamily: "semibold",
}}
onLayout={({ nativeEvent: { layout: { width } } }) => {
setTextMeasurement(width);
}}
>
{account.label}
</Text>

<AnimatedTouchableOpacity
onPress={onPress}
style={[
Expand All @@ -90,15 +32,12 @@ const AccountButton: React.FC<AccountButtonProps> = ({ account, isSelected, onPr
alignItems: "center",
justifyContent: "center",
backgroundColor: isSelected ? colors.primary + "20" : colors.card,
borderColor: colors.border,
borderWidth: isSelected ? 0 : 1,
paddingVertical: 12,
borderRadius: 15,
paddingHorizontal: 12,
paddingVertical: 8,
borderRadius: 10,
paddingHorizontal: 10,
gap: 8,
overflow: "hidden",
},
animatedContainerStyle,
}
]}
>
<View style={{
Expand All @@ -114,24 +53,22 @@ const AccountButton: React.FC<AccountButtonProps> = ({ account, isSelected, onPr
<Utensils color={isSelected ? colors.primary : colors.text} size={20} />
)}
</Reanimated.View>
{isSelected && (
{(
<AnimatedView
style={[
{
overflow: "hidden",
},
animatedTextContainerStyle
}
]}
>
<Reanimated.Text
numberOfLines={1}
style={[
{
fontFamily: "semibold",
fontSize: 13,
color: colors.primary,
},
animatedTextStyle,
fontSize: 15.5,
color: isSelected ? colors.primary : colors.text,
}
]}
>
{account.label}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Restaurant/RestaurantCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const RestaurantCard: React.FC<RestaurantCardProps> = ({ solde, repas }) => {
style={{
textAlign: "left",
fontFamily: "semibold",
color: solde < 0 ? "D10000" : "#5CB21F",
color: solde < 0 ? "#D10000" : "#5CB21F",
fontSize: 30,
}}
>
Expand Down
3 changes: 2 additions & 1 deletion src/router/helpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type React from "react";
import type { School as SkolengoSchool} from "scolengo-api/types/models/School";
import {Information} from "@/services/shared/Information";
import { ImageSourcePropType } from "react-native";
import {Client} from "pawrd";

export type RouteParameters = {
// welcome.index
Expand Down Expand Up @@ -137,7 +138,7 @@ export type RouteParameters = {
ExternalArdLogin: undefined;
ExternalIzlyLogin: undefined;
IzlyActivation: { username: string, password: string };
QrcodeAnswer: { accountID: string };
PriceError: { account: Client, accountId: string };
QrcodeScanner: { accountID: string };
PriceDetectionOnboarding: { accountID: string };
PriceBeforeScan: { accountID: string };
Expand Down
4 changes: 2 additions & 2 deletions src/router/screens/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import ExternalTurboselfLogin from "@/views/settings/ExternalAccount/Turboself";
import ExternalArdLogin from "@/views/settings/ExternalAccount/ARD";
import SettingsDonorsList from "@/views/settings/SettingsDonorsList";
import ExternalAccountSelector from "@/views/settings/ExternalAccount/ServiceSelector";
import QrcodeAnswer from "@/views/settings/ExternalAccount/QrcodeAnswer";
import PriceError from "@/views/settings/ExternalAccount/PriceError";
import QrcodeScanner from "@/views/settings/ExternalAccount/QrcodeScanner";
import PriceDetectionOnboarding from "@/views/settings/ExternalAccount/PriceDetectionOnboarding";
import PriceBeforeScan from "@/views/settings/ExternalAccount/PriceBeforeScan";
Expand Down Expand Up @@ -76,7 +76,7 @@ const settingsScreens = [
headerTitle: "Configuration de la cantine",
}),

createScreen("QrcodeAnswer", QrcodeAnswer, {
createScreen("PriceError", PriceError, {
headerTitle: "Configuration de la cantine",
}),

Expand Down
5 changes: 3 additions & 2 deletions src/services/ard/balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import { ErrorServiceUnauthenticated } from "../shared/errors";
export const balance = async (account: ARDAccount): Promise<Balance[]> => {
if (!account.instance) throw new ErrorServiceUnauthenticated("ARD");
const payments = await account.instance!.getOnlinePayments();
const mealPrice = account.authentication.mealPrice;

return payments.walletData.map(wallet => ({
amount: wallet.walletAmount / 100,
currency: "€",
remaining: null,
label: wallet.walletName
remaining: Math.floor((wallet.walletAmount / mealPrice!)),
label: wallet.walletName[0].toUpperCase() + wallet.walletName.slice(1).toLowerCase()
}));

};
2 changes: 1 addition & 1 deletion src/services/ard/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const history = async (account: ARDAccount): Promise<ReservationHistory[]
label: "Transaction n°" + item.orderReference.toString()
})),
...(consumptionsHistory ?? []).map((item) => ({
amount: item.amount / 100,
amount: -item.amount / 100,
timestamp: item.consumptionDate * 1000,
currency: "€",
label: item.consumptionDescription
Expand Down
3 changes: 2 additions & 1 deletion src/stores/account/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ export interface ARDAccount extends BaseExternalAccount {
pid: string
username: string
password: string
schoolID: string
schoolID: string,
mealPrice: number
}
}

Expand Down
8 changes: 6 additions & 2 deletions src/views/account/Restaurant/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ const Menu: Screen<"Menu"> = ({ route, navigation }) => {
) : (
<>
<View style={styles.accountButtonContainer}>
{allBalances?.map((account, index) => (
{allBalances!.length > 1 && allBalances?.map((account, index) => (
<AccountButton
key={index}
account={account}
Expand All @@ -214,7 +214,11 @@ const Menu: Screen<"Menu"> = ({ route, navigation }) => {
>
<RestaurantCard
solde={allBalances[selectedIndex].amount}
repas={allBalances[selectedIndex].remaining || null }
repas={
allBalances?.[selectedIndex]?.remaining != null
? Math.max(0, allBalances[selectedIndex].remaining)
: null
}
/>
</Reanimated.View>
)}
Expand Down
14 changes: 9 additions & 5 deletions src/views/account/Restaurant/Modals/History.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,31 @@ const RestaurantHistory = ({ route }: { route: NavigationProps }) => {
return date.toLocaleDateString("fr-FR", {
weekday: "long",
month: "long",
day: "numeric",
day: "numeric"
}).toUpperCase();
};

const groupedHistories = useMemo(() => {
const historyMap = new Map();
const historyMap = new Map<string, ReservationHistory[]>();

histories.sort((a, b) => b.timestamp - a.timestamp);

histories.forEach((history: ReservationHistory) => {
const formattedDate = formatDate(history.timestamp);
if (!historyMap.has(formattedDate)) {
historyMap.set(formattedDate, []);
}
historyMap.get(formattedDate).push(history);
historyMap.get(formattedDate)?.push(history);
});

historyMap.forEach((value) => {
value.sort((a: { timestamp: number; }, b: { timestamp: number; }) => b.timestamp - a.timestamp);
value.sort((a, b) => b.timestamp - a.timestamp);
});

return Array.from(historyMap.entries()).sort(([a], [b]) => a - b);;
return Array.from(historyMap);
}, [histories]);


return (
<ScrollView contentContainerStyle={styles.scrollViewContent}>
{histories === null ? (
Expand Down
34 changes: 30 additions & 4 deletions src/views/settings/ExternalAccount/ARD.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,33 @@
import { useState } from "react";
import { Authenticator } from "pawrd";
import {Authenticator, Client, getOnlinePayments} from "pawrd";
import { AccountService, type ARDAccount } from "@/stores/account/types";
import uuid from "@/utils/uuid-v4";
import { useAccounts, useCurrentAccount } from "@/stores/account";
import LoginView from "@/components/Templates/LoginView";
import { Screen } from "@/router/helpers/types";

export async function detectMealPrice (account: Client): Promise<number | null> {
const uid = await account.getOnlinePayments().then((payment) => payment.user.uid);
const consumptionsHistory = await account.getConsumptionsHistory(uid);

let mostFrequentAmount: number | null = null;
let maxCount = 0;
const amountCount: Record<number, number> = {};

for (const consumption of consumptionsHistory) {
const amount = consumption.amount;

amountCount[amount] = (amountCount[amount] || 0) + 1;

if (amountCount[amount] > maxCount) {
maxCount = amountCount[amount];
mostFrequentAmount = amount;
}
}

return mostFrequentAmount || null;
}

const ExternalArdLogin: Screen<"ExternalArdLogin"> = ({ navigation }) => {
const linkExistingExternalAccount = useCurrentAccount(store => store.linkExistingExternalAccount);
const create = useAccounts(store => store.create);
Expand All @@ -19,6 +41,7 @@ const ExternalArdLogin: Screen<"ExternalArdLogin"> = ({ navigation }) => {
const schoolID = customFields["schoolID"];

const client = await authenticator.fromCredentials(schoolID, username, password);
const mealPrice = await detectMealPrice(client);

const new_account: ARDAccount = {
instance: client,
Expand All @@ -28,7 +51,8 @@ const ExternalArdLogin: Screen<"ExternalArdLogin"> = ({ navigation }) => {
schoolID,
username,
password,
pid: client.pid
pid: client.pid,
mealPrice: mealPrice ?? 100
},
isExternal: true,
localID: uuid(),
Expand All @@ -37,8 +61,10 @@ const ExternalArdLogin: Screen<"ExternalArdLogin"> = ({ navigation }) => {

create(new_account);
linkExistingExternalAccount(new_account);

navigation.navigate("QrcodeAnswer", { accountID: new_account.localID });
if (!mealPrice) return navigation.navigate("PriceError", { account: client, accountId: new_account.localID });
navigation.pop();
navigation.pop();
navigation.pop();
} catch (error) {
if (error instanceof Error) {
setError(error.message);
Expand Down
Loading

0 comments on commit 7335eab

Please sign in to comment.