merge
@@ -5,8 +5,10 @@ const admin = require("firebase-admin");
|
|||||||
admin.initializeApp();
|
admin.initializeApp();
|
||||||
|
|
||||||
const db = admin.firestore();
|
const db = admin.firestore();
|
||||||
|
const REGION = process.env.FIREBASE_REGION || "europe-west1";
|
||||||
|
|
||||||
exports.db = db;
|
exports.db = db;
|
||||||
|
exports.REGION = REGION;
|
||||||
|
|
||||||
exports.refList = {
|
exports.refList = {
|
||||||
projects: db.collection("projects"),
|
projects: db.collection("projects"),
|
||||||
@@ -21,6 +23,7 @@ exports.refList = {
|
|||||||
monthlyPayoutEntries: db.collection("monthlyPayoutEntries"),
|
monthlyPayoutEntries: db.collection("monthlyPayoutEntries"),
|
||||||
monthlyPayouts: db.collection("monthlyPayouts"),
|
monthlyPayouts: db.collection("monthlyPayouts"),
|
||||||
};
|
};
|
||||||
|
exports.refsList = exports.refList;
|
||||||
|
|
||||||
exports.ALERT_TYPE = {
|
exports.ALERT_TYPE = {
|
||||||
NEW_LIKE: "NEW_LIKE",
|
NEW_LIKE: "NEW_LIKE",
|
||||||
@@ -45,4 +48,5 @@ exports.algolia = require("./src/algolia");
|
|||||||
exports.notifications = require("./src/notifications");
|
exports.notifications = require("./src/notifications");
|
||||||
exports.rankings = require("./src/rankings");
|
exports.rankings = require("./src/rankings");
|
||||||
exports.payouts = require("./src/payouts");
|
exports.payouts = require("./src/payouts");
|
||||||
|
exports.subscription = require("./src/subscription");
|
||||||
exports.youtube = require("./src/youtube");
|
exports.youtube = require("./src/youtube");
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 446 KiB |
|
Before Width: | Height: | Size: 905 KiB |
|
Before Width: | Height: | Size: 418 KiB |
|
Before Width: | Height: | Size: 301 KiB |
|
Before Width: | Height: | Size: 438 KiB |
@@ -11,7 +11,7 @@ import {
|
|||||||
// import CountryPicker, { DARK_THEME } from "react-native-country-picker-modal";
|
// import CountryPicker, { DARK_THEME } from "react-native-country-picker-modal";
|
||||||
import usePlaceApi from "react-native-minuit/src/hooks/usePlacesApi";
|
import usePlaceApi from "react-native-minuit/src/hooks/usePlacesApi";
|
||||||
|
|
||||||
import { art, icons } from "../assets";
|
import { icons } from "../assets";
|
||||||
import { Fonts, Palette, Style, gutters } from "../styles";
|
import { Fonts, Palette, Style, gutters } from "../styles";
|
||||||
import { FONT_FAMILY } from "../styles/Fonts";
|
import { FONT_FAMILY } from "../styles/Fonts";
|
||||||
|
|
||||||
@@ -69,11 +69,7 @@ const Input = ({
|
|||||||
const ContainerView = isBlur ? BlurView : View;
|
const ContainerView = isBlur ? BlurView : View;
|
||||||
const resolvedKeyboardType =
|
const resolvedKeyboardType =
|
||||||
textInputProps?.keyboardType ??
|
textInputProps?.keyboardType ??
|
||||||
(isNumeric
|
(isNumeric ? "numeric" : type === "email" ? "email-address" : "default");
|
||||||
? "numeric"
|
|
||||||
: type === "email"
|
|
||||||
? "email-address"
|
|
||||||
: "default");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -198,12 +194,6 @@ const Input = ({
|
|||||||
<Pressable onPress={() => setShowPassword(!showPassword)}>
|
<Pressable onPress={() => setShowPassword(!showPassword)}>
|
||||||
{showPassword ? <EyeSVG /> : <EyeSlashSVG />}
|
{showPassword ? <EyeSVG /> : <EyeSlashSVG />}
|
||||||
</Pressable>
|
</Pressable>
|
||||||
) : type === "coinAmount" ? (
|
|
||||||
<Image
|
|
||||||
source={art.coin}
|
|
||||||
style={[Style.iconDefault]}
|
|
||||||
resizeMode="contain"
|
|
||||||
/>
|
|
||||||
) : null}
|
) : null}
|
||||||
</ContainerView>
|
</ContainerView>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable react/display-name */
|
/* eslint-disable react/display-name */
|
||||||
import { Image, View } from "react-native";
|
import { Image, Pressable, Text, View } from "react-native";
|
||||||
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
|
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
|
||||||
import { SafeAreaView } from "react-native-safe-area-context";
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
import React from "reactn";
|
import React from "reactn";
|
||||||
@@ -10,6 +10,11 @@ import NavigateHeader from "../components/NavigateHeader";
|
|||||||
import ShareBtn from "../components/ShareBtn/ShareBtn";
|
import ShareBtn from "../components/ShareBtn/ShareBtn";
|
||||||
import { isWeb } from "../hooks/useLayoutType.js";
|
import { isWeb } from "../hooks/useLayoutType.js";
|
||||||
import { gutters } from "../styles";
|
import { gutters } from "../styles";
|
||||||
|
import { icons } from "../assets";
|
||||||
|
import { FONT_FAMILY } from "../styles/Fonts";
|
||||||
|
import { useUserData } from "../providers/UserDataProvider";
|
||||||
|
import { push } from "../navigation/NavigationService";
|
||||||
|
import { Routes } from "../navigation";
|
||||||
|
|
||||||
export default ({
|
export default ({
|
||||||
children,
|
children,
|
||||||
@@ -40,6 +45,53 @@ export default ({
|
|||||||
blurIntensity = 0,
|
blurIntensity = 0,
|
||||||
backgroundColor = "#000",
|
backgroundColor = "#000",
|
||||||
}) => {
|
}) => {
|
||||||
|
const {
|
||||||
|
currentUID = null,
|
||||||
|
currentUserData = null,
|
||||||
|
} = useUserData?.() || {};
|
||||||
|
|
||||||
|
const coinBalance = React.useMemo(() => {
|
||||||
|
const data = currentUserData || {};
|
||||||
|
const candidates = [
|
||||||
|
data?.coins,
|
||||||
|
data?.coinBalance,
|
||||||
|
data?.coin,
|
||||||
|
data?.wallet?.coins,
|
||||||
|
data?.wallet?.coinBalance,
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const value of candidates) {
|
||||||
|
if (typeof value === "number" && Number.isFinite(value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
if (typeof value === "string") {
|
||||||
|
const parsed = Number(value);
|
||||||
|
if (Number.isFinite(parsed)) {
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}, [currentUserData]);
|
||||||
|
|
||||||
|
const formattedCoins = React.useMemo(() => {
|
||||||
|
try {
|
||||||
|
return new Intl.NumberFormat("fr-FR", {
|
||||||
|
maximumFractionDigits: 0,
|
||||||
|
}).format(coinBalance);
|
||||||
|
} catch (_error) {
|
||||||
|
return `${coinBalance}`;
|
||||||
|
}
|
||||||
|
}, [coinBalance]);
|
||||||
|
|
||||||
|
const showCoinBadge = isWeb && !!currentUID;
|
||||||
|
|
||||||
|
const handleCoinPress = React.useCallback(() => {
|
||||||
|
if (!showCoinBadge) return;
|
||||||
|
push?.(Routes?.Payments || "Payments", { pack: "packs" });
|
||||||
|
}, [showCoinBadge]);
|
||||||
|
|
||||||
const PageContainer =
|
const PageContainer =
|
||||||
containerType === "SAFE_AREA_VIEW" ? SafeAreaView : View;
|
containerType === "SAFE_AREA_VIEW" ? SafeAreaView : View;
|
||||||
|
|
||||||
@@ -88,6 +140,41 @@ export default ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
{showCoinBadge ? (
|
||||||
|
<Pressable
|
||||||
|
onPress={handleCoinPress}
|
||||||
|
accessibilityRole="button"
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: gutters,
|
||||||
|
left: gutters,
|
||||||
|
paddingHorizontal: 14,
|
||||||
|
paddingVertical: 8,
|
||||||
|
borderRadius: 20,
|
||||||
|
backgroundColor: "rgba(12, 14, 18, 0.72)",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "rgba(255, 255, 255, 0.1)",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 10,
|
||||||
|
zIndex: 20,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
source={icons.coin}
|
||||||
|
style={{ width: 22, height: 22, resizeMode: "contain" }}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: "#ffffff",
|
||||||
|
fontFamily: FONT_FAMILY.InterSemiBold,
|
||||||
|
fontSize: 14,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{formattedCoins}
|
||||||
|
</Text>
|
||||||
|
</Pressable>
|
||||||
|
) : null}
|
||||||
<PageContainer
|
<PageContainer
|
||||||
{...(containerType === "SAFE_AREA_VIEW" ? { edges: ["top"] } : {})}
|
{...(containerType === "SAFE_AREA_VIEW" ? { edges: ["top"] } : {})}
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import React, {
|
|||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { Platform, StyleSheet, View } from "react-native";
|
import { Platform, StyleSheet, View } from "react-native";
|
||||||
|
import { useIsFocused } from "@react-navigation/native";
|
||||||
import useMinuit from "react-native-minuit/src/hooks/useMinuit.js";
|
import useMinuit from "react-native-minuit/src/hooks/useMinuit.js";
|
||||||
import { background, videos } from "../../assets";
|
import { background, videos } from "../../assets";
|
||||||
import Alert from "../../components/Alert";
|
import Alert from "../../components/Alert";
|
||||||
@@ -31,6 +32,7 @@ import {
|
|||||||
} from "../../utils/projectStages";
|
} from "../../utils/projectStages";
|
||||||
|
|
||||||
const Home = ({ navigation, route }) => {
|
const Home = ({ navigation, route }) => {
|
||||||
|
const isFocused = useIsFocused();
|
||||||
const {
|
const {
|
||||||
userProjects = [],
|
userProjects = [],
|
||||||
resetSelectedProject,
|
resetSelectedProject,
|
||||||
@@ -425,6 +427,7 @@ const Home = ({ navigation, route }) => {
|
|||||||
activeIndex={activeStageIndex}
|
activeIndex={activeStageIndex}
|
||||||
onActiveIndexChange={setActiveStageIndex}
|
onActiveIndexChange={setActiveStageIndex}
|
||||||
backgroundImage={homeBackgroundImage}
|
backgroundImage={homeBackgroundImage}
|
||||||
|
isFocused={isFocused}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ const SETTINGS = [
|
|||||||
navigate(Routes.Language);
|
navigate(Routes.Language);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Découvrir les packs",
|
||||||
|
action: () => {
|
||||||
|
navigate(Routes.Payments, { pack: "premium" });
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "Gérer mon abonnement",
|
title: "Gérer mon abonnement",
|
||||||
action: () => {},
|
action: () => {},
|
||||||
|
|||||||