diff --git a/app/components/december-challenge/card.tsx b/app/components/december-challenge/card.tsx new file mode 100644 index 0000000000..8fdbbc7ffb --- /dev/null +++ b/app/components/december-challenge/card.tsx @@ -0,0 +1,106 @@ +import { View } from "react-native" +import { Text, makeStyles, useTheme } from "@rneui/themed" +import { useI18nContext } from "@app/i18n/i18n-react" +import { GaloyIcon } from "../atomic/galoy-icon" +import { useEffect, useState } from "react" +import { DecemberChallengeModal } from "./modal" +import { PressableCard } from "../pressable-card" + +import { JAN_1_2024_12_AM_UTC_MINUS_6, DEC_1_12_AM_UTC_MINUS_6 } from "./dates" + +function secondsToDDMMSS(totalSeconds: number) { + if (totalSeconds < 0) return "" + + const days = Math.floor(totalSeconds / 86400) // There are 86400 seconds in a day + const hours = Math.floor((totalSeconds - days * 86400) / 3600) // 3600 seconds in an hour + const minutes = Math.floor((totalSeconds - days * 86400 - hours * 3600) / 60) + const seconds = Math.floor(totalSeconds - days * 86400 - hours * 3600 - minutes * 60) + + const formattedDays = days.toString().padStart(2, "0") + const formattedHours = hours.toString().padStart(2, "0") + const formattedMinutes = minutes.toString().padStart(2, "0") + const formattedSeconds = seconds.toString().padStart(2, "0") + + return `${formattedDays}:${formattedHours}:${formattedMinutes}:${formattedSeconds}` +} + +const getTimeLeft = () => { + const dateNow = Date.now() + if (dateNow > JAN_1_2024_12_AM_UTC_MINUS_6 || dateNow < DEC_1_12_AM_UTC_MINUS_6) + return "" + + const sLeft = (JAN_1_2024_12_AM_UTC_MINUS_6 - dateNow) / 1000 + return secondsToDDMMSS(sLeft) +} + +export const DecemberChallengeCard: React.FC = () => { + const [modalIsOpen, setModalIsOpen] = useState(false) + const openModal = () => setModalIsOpen(true) + + const { + theme: { colors }, + } = useTheme() + const styles = useStyles() + const { LL } = useI18nContext() + + const [countDown, setCountDown] = useState(getTimeLeft()) + + useEffect(() => { + const dateNow = Date.now() + if (dateNow > JAN_1_2024_12_AM_UTC_MINUS_6) return + + const t = setInterval(() => { + setCountDown(getTimeLeft()) + }, 1000) + + return () => clearInterval(t) + }, [setCountDown]) + + const currentTime = Date.now() + if (currentTime > JAN_1_2024_12_AM_UTC_MINUS_6 || currentTime < DEC_1_12_AM_UTC_MINUS_6) + return <> + + return ( + + + + + + + {LL.Circles.decemberChallenge.title()} + + {countDown} + + {LL.Circles.decemberChallenge.description()} + + + + + + + ) +} + +const useStyles = makeStyles(({ colors }) => ({ + card: { + display: "flex", + flexDirection: "row", + justifyContent: "space-between", + padding: 16, + borderRadius: 10, + backgroundColor: colors.grey5, + }, + textContainer: { + flex: 1, + display: "flex", + flexDirection: "column", + justifyContent: "center", + rowGap: 6, + }, + beside: { + display: "flex", + flexDirection: "row", + alignItems: "center", + columnGap: 10, + }, +})) diff --git a/app/components/december-challenge/dates.ts b/app/components/december-challenge/dates.ts new file mode 100644 index 0000000000..d9ec41255f --- /dev/null +++ b/app/components/december-challenge/dates.ts @@ -0,0 +1,5 @@ +export const DEC_1_12_AM_UTC_MINUS_6 = new Date(Date.UTC(2023, 11, 1, 6, 0, 0)).getTime() + +export const JAN_1_2024_12_AM_UTC_MINUS_6 = new Date( + Date.UTC(2024, 0, 1, 6, 0, 0), +).getTime() diff --git a/app/components/december-challenge/index.tsx b/app/components/december-challenge/index.tsx new file mode 100644 index 0000000000..cfa5107fa6 --- /dev/null +++ b/app/components/december-challenge/index.tsx @@ -0,0 +1,2 @@ +export * from "./modal" +export * from "./card" diff --git a/app/components/december-challenge/modal.tsx b/app/components/december-challenge/modal.tsx new file mode 100644 index 0000000000..57bbdc9edb --- /dev/null +++ b/app/components/december-challenge/modal.tsx @@ -0,0 +1,131 @@ +import * as React from "react" +import { Linking, View } from "react-native" +import Modal from "react-native-modal" + +import { useI18nContext } from "@app/i18n/i18n-react" +import { makeStyles, useTheme, Text } from "@rneui/themed" + +import { GaloyIconButton } from "../atomic/galoy-icon-button" +import { GaloyToast } from "../galoy-toast" +import { GaloyIcon } from "../atomic/galoy-icon" +import { useCirclesCard } from "@app/screens/people-screen/circles/use-circles-card" +import { GaloyPrimaryButton } from "../atomic/galoy-primary-button" + +const CHALLENGE_PAGE = "blink.sv/circles" +const CHALLENGE_PAGE_URL = "https://www.blink.sv/circles" +const SOCIAL_LINK_TREE = "https://linktr.ee/blinkbtc" + +type Props = { + isVisible: boolean + setIsVisible: (isVisible: boolean) => void +} + +export const DecemberChallengeModal: React.FC = ({ isVisible, setIsVisible }) => { + const { LL } = useI18nContext() + + const { + theme: { colors }, + } = useTheme() + const styles = useStyles() + + const acknowledgeModal = () => { + setIsVisible(false) + } + + const { ShareImg, share } = useCirclesCard() + + return ( + + + + + + + {LL.Circles.decemberChallenge.title()} + + + {LL.Circles.decemberChallenge.details()} + + {ShareImg} + + + {LL.Circles.octoberChallenge.connectOnSocial()} + Linking.openURL(SOCIAL_LINK_TREE)} + > + {SOCIAL_LINK_TREE} + + + + {LL.Circles.octoberChallenge.fullDetails()} + Linking.openURL(CHALLENGE_PAGE_URL)} + > + {CHALLENGE_PAGE} + + + + + + + ) +} + +const useStyles = makeStyles(({ colors }) => ({ + container: { + paddingHorizontal: 12, + display: "flex", + flexDirection: "column", + rowGap: 20, + justifyContent: "center", + alignItems: "center", + }, + cross: { + position: "absolute", + right: 20, + top: -10, + }, + top: { marginTop: 40 }, + modalCard: { + backgroundColor: colors.grey5, + borderRadius: 16, + display: "flex", + justifyContent: "center", + alignItems: "center", + paddingVertical: 30, + }, + details: { + textAlign: "center", + paddingHorizontal: 20, + }, + reminder: { + textAlign: "center", + paddingHorizontal: 20, + color: colors.grey2, + }, + underline: { + textDecorationLine: "underline", + }, + containerData: { + display: "flex", + flexDirection: "column", + rowGap: 2, + justifyContent: "center", + alignItems: "center", + }, +})) diff --git a/app/i18n/en/index.ts b/app/i18n/en/index.ts index 5b19b9ec36..065b2bf1dc 100644 --- a/app/i18n/en/index.ts +++ b/app/i18n/en/index.ts @@ -2796,6 +2796,11 @@ const en: BaseTranslation = { description: "Earn 2,100 sats for every person you welcome to Blink in November!", details: "Earn 2,100 sats for every person you welcome to Blink in November!\n\nTo claim your sats, simply share your Circles on social any time during November with the tag `#blinkcircles`.\n\nYour sats will be paid out on December 1, 2023." }, + decemberChallenge: { + title: "December Challenge!", + description: "+10 inner circle for a chance at $100!", + details: "Grow your inner circle by 10 people in December for a chance at $100!\n\nTo participate, share your circles on social once you've reached 10 for the month and tag #blinkcircles.\n\nOn January 1, three people will be chosen at random to receive $100!" + }, }, FullOnboarding: { title: "Full onboarding", diff --git a/app/i18n/i18n-types.ts b/app/i18n/i18n-types.ts index 33a4fa1f66..d2e7ce7b60 100644 --- a/app/i18n/i18n-types.ts +++ b/app/i18n/i18n-types.ts @@ -8725,6 +8725,24 @@ type RootTranslation = { */ details: string } + decemberChallenge: { + /** + * D​e​c​e​m​b​e​r​ ​C​h​a​l​l​e​n​g​e​! + */ + title: string + /** + * +​1​0​ ​i​n​n​e​r​ ​c​i​r​c​l​e​ ​f​o​r​ ​a​ ​c​h​a​n​c​e​ ​a​t​ ​$​1​0​0​! + */ + description: string + /** + * G​r​o​w​ ​y​o​u​r​ ​i​n​n​e​r​ ​c​i​r​c​l​e​ ​b​y​ ​1​0​ ​p​e​o​p​l​e​ ​i​n​ ​D​e​c​e​m​b​e​r​ ​f​o​r​ ​a​ ​c​h​a​n​c​e​ ​a​t​ ​$​1​0​0​!​ + ​ + ​T​o​ ​p​a​r​t​i​c​i​p​a​t​e​,​ ​s​h​a​r​e​ ​y​o​u​r​ ​c​i​r​c​l​e​s​ ​o​n​ ​s​o​c​i​a​l​ ​o​n​c​e​ ​y​o​u​'​v​e​ ​r​e​a​c​h​e​d​ ​1​0​ ​f​o​r​ ​t​h​e​ ​m​o​n​t​h​ ​a​n​d​ ​t​a​g​ ​#​b​l​i​n​k​c​i​r​c​l​e​s​.​ + ​ + ​O​n​ ​J​a​n​u​a​r​y​ ​1​,​ ​t​h​r​e​e​ ​p​e​o​p​l​e​ ​w​i​l​l​ ​b​e​ ​c​h​o​s​e​n​ ​a​t​ ​r​a​n​d​o​m​ ​t​o​ ​r​e​c​e​i​v​e​ ​$​1​0​0​! + */ + details: string + } } FullOnboarding: { /** @@ -17408,6 +17426,24 @@ export type TranslationFunctions = { */ details: () => LocalizedString } + decemberChallenge: { + /** + * December Challenge! + */ + title: () => LocalizedString + /** + * +10 inner circle for a chance at $100! + */ + description: () => LocalizedString + /** + * Grow your inner circle by 10 people in December for a chance at $100! + + To participate, share your circles on social once you've reached 10 for the month and tag #blinkcircles. + + On January 1, three people will be chosen at random to receive $100! + */ + details: () => LocalizedString + } } FullOnboarding: { /** diff --git a/app/i18n/raw-i18n/source/en.json b/app/i18n/raw-i18n/source/en.json index 9e6bf635d4..980e27b5fb 100644 --- a/app/i18n/raw-i18n/source/en.json +++ b/app/i18n/raw-i18n/source/en.json @@ -2671,6 +2671,11 @@ "title": "November Challenge!", "description": "Earn 2,100 sats for every person you welcome to Blink in November!", "details": "Earn 2,100 sats for every person you welcome to Blink in November!\n\nTo claim your sats, simply share your Circles on social any time during November with the tag `#blinkcircles`.\n\nYour sats will be paid out on December 1, 2023." + }, + "decemberChallenge": { + "title": "December Challenge!", + "description": "+10 inner circle for a chance at $100!", + "details": "Grow your inner circle by 10 people in December for a chance at $100!\n\nTo participate, share your circles on social once you've reached 10 for the month and tag #blinkcircles.\n\nOn January 1, three people will be chosen at random to receive $100!" } }, "FullOnboarding": { diff --git a/app/screens/people-screen/circles/circles-dashboard-screen.tsx b/app/screens/people-screen/circles/circles-dashboard-screen.tsx index 28da626488..d174da47c2 100644 --- a/app/screens/people-screen/circles/circles-dashboard-screen.tsx +++ b/app/screens/people-screen/circles/circles-dashboard-screen.tsx @@ -17,6 +17,7 @@ import { Screen } from "../../../components/screen" import { IntroducingCirclesModal } from "@app/components/introducing-circles-modal" import { NovemberChallengeCard } from "@app/components/november-challenge" import { ScrollView } from "react-native-gesture-handler" +import { DecemberChallengeCard } from "@app/components/december-challenge" gql` query Circles { @@ -154,6 +155,7 @@ export const CirclesDashboardScreen: React.FC = () => { )} + {isLonely ? : }