feat: cgu
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
export const REGISTRATION_TERMS_VERSION = 'musicland-2023-10-22'
|
||||||
@@ -11,6 +11,7 @@ import { useGlobal } from 'reactn'
|
|||||||
import { handleFirebaseError } from '../actions/signupActions'
|
import { handleFirebaseError } from '../actions/signupActions'
|
||||||
import firebase, { usersRef } from '../config/firebase'
|
import firebase, { usersRef } from '../config/firebase'
|
||||||
import { GOOGLE_ANDROID_CLIENT_ID, GOOGLE_IOS_CLIENT_ID, GOOGLE_WEB_CLIENT_ID } from '../data/keys'
|
import { GOOGLE_ANDROID_CLIENT_ID, GOOGLE_IOS_CLIENT_ID, GOOGLE_WEB_CLIENT_ID } from '../data/keys'
|
||||||
|
import { REGISTRATION_TERMS_VERSION } from '../data/legal'
|
||||||
|
|
||||||
WebBrowser.maybeCompleteAuthSession()
|
WebBrowser.maybeCompleteAuthSession()
|
||||||
|
|
||||||
@@ -131,6 +132,11 @@ const ensureUserDocument = async (user, overrides = {}, isNewUser = false) => {
|
|||||||
payload.preferredLanguage = overridePreferredLanguage
|
payload.preferredLanguage = overridePreferredLanguage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isNewUser && overrides?.termsAccepted === true) {
|
||||||
|
payload.termsAcceptedAt = firebase.firestore.FieldValue.serverTimestamp()
|
||||||
|
payload.termsVersion = REGISTRATION_TERMS_VERSION
|
||||||
|
}
|
||||||
|
|
||||||
await docRef.set(payload, { merge: true })
|
await docRef.set(payload, { merge: true })
|
||||||
return {
|
return {
|
||||||
isNewUser,
|
isNewUser,
|
||||||
@@ -145,7 +151,7 @@ const ensureUserDocument = async (user, overrides = {}, isNewUser = false) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const useSocialAuth = ({ onSuccess, preferredLanguage = null } = {}) => {
|
const useSocialAuth = ({ onSuccess, preferredLanguage = null, termsAccepted = false } = {}) => {
|
||||||
const [, setTooltip] = useGlobal('_tooltip')
|
const [, setTooltip] = useGlobal('_tooltip')
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const [isAppleSignInAvailable, setIsAppleSignInAvailable] = useState(false)
|
const [isAppleSignInAvailable, setIsAppleSignInAvailable] = useState(false)
|
||||||
@@ -242,7 +248,7 @@ const useSocialAuth = ({ onSuccess, preferredLanguage = null } = {}) => {
|
|||||||
const userCredential = await firebase.auth().signInWithCredential(credential)
|
const userCredential = await firebase.auth().signInWithCredential(credential)
|
||||||
const authResult = await ensureUserDocument(
|
const authResult = await ensureUserDocument(
|
||||||
userCredential?.user,
|
userCredential?.user,
|
||||||
{ preferredLanguage },
|
{ preferredLanguage, termsAccepted },
|
||||||
userCredential?.additionalUserInfo?.isNewUser === true
|
userCredential?.additionalUserInfo?.isNewUser === true
|
||||||
)
|
)
|
||||||
if (typeof onSuccess === 'function') {
|
if (typeof onSuccess === 'function') {
|
||||||
@@ -260,7 +266,7 @@ const useSocialAuth = ({ onSuccess, preferredLanguage = null } = {}) => {
|
|||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[onSuccess, preferredLanguage, redirectUri, request, setTooltip]
|
[onSuccess, preferredLanguage, redirectUri, request, setTooltip, termsAccepted]
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -323,7 +329,7 @@ const useSocialAuth = ({ onSuccess, preferredLanguage = null } = {}) => {
|
|||||||
const userCredential = await firebase.auth().signInWithPopup(provider)
|
const userCredential = await firebase.auth().signInWithPopup(provider)
|
||||||
const authResult = await ensureUserDocument(
|
const authResult = await ensureUserDocument(
|
||||||
userCredential?.user,
|
userCredential?.user,
|
||||||
{ preferredLanguage },
|
{ preferredLanguage, termsAccepted },
|
||||||
userCredential?.additionalUserInfo?.isNewUser === true
|
userCredential?.additionalUserInfo?.isNewUser === true
|
||||||
)
|
)
|
||||||
if (typeof onSuccess === 'function') {
|
if (typeof onSuccess === 'function') {
|
||||||
@@ -380,6 +386,7 @@ const useSocialAuth = ({ onSuccess, preferredLanguage = null } = {}) => {
|
|||||||
preferredLanguage,
|
preferredLanguage,
|
||||||
promptAsync,
|
promptAsync,
|
||||||
setTooltip,
|
setTooltip,
|
||||||
|
termsAccepted,
|
||||||
])
|
])
|
||||||
|
|
||||||
const signInWithApple = useCallback(async () => {
|
const signInWithApple = useCallback(async () => {
|
||||||
@@ -431,6 +438,7 @@ const useSocialAuth = ({ onSuccess, preferredLanguage = null } = {}) => {
|
|||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName,
|
||||||
preferredLanguage,
|
preferredLanguage,
|
||||||
|
termsAccepted,
|
||||||
displayName:
|
displayName:
|
||||||
userCredential?.user?.displayName ||
|
userCredential?.user?.displayName ||
|
||||||
[firstName, lastName].filter(Boolean).join(' ') ||
|
[firstName, lastName].filter(Boolean).join(' ') ||
|
||||||
@@ -456,7 +464,7 @@ const useSocialAuth = ({ onSuccess, preferredLanguage = null } = {}) => {
|
|||||||
setTooltip({ text: message, type: 'error' })
|
setTooltip({ text: message, type: 'error' })
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
}
|
}
|
||||||
}, [isAppleSignInAvailable, isLoading, onSuccess, preferredLanguage, setTooltip])
|
}, [isAppleSignInAvailable, isLoading, onSuccess, preferredLanguage, setTooltip, termsAccepted])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
signInWithGoogle,
|
signInWithGoogle,
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import Profile from '../screens/Profile/Profile'
|
|||||||
import Reels from '../screens/Profile/Reels'
|
import Reels from '../screens/Profile/Reels'
|
||||||
import Settings from '../screens/Profile/Settings'
|
import Settings from '../screens/Profile/Settings'
|
||||||
import Register from '../screens/Register'
|
import Register from '../screens/Register'
|
||||||
|
import RegistrationTerms from '../screens/RegistrationTerms'
|
||||||
import Splash from '../screens/Splash'
|
import Splash from '../screens/Splash'
|
||||||
import Compose from '../screens/Studio/Compose'
|
import Compose from '../screens/Studio/Compose'
|
||||||
import ComposeSong from '../screens/Studio/ComposeSong'
|
import ComposeSong from '../screens/Studio/ComposeSong'
|
||||||
@@ -342,6 +343,10 @@ const baseScreens = [
|
|||||||
name: Routes.Register,
|
name: Routes.Register,
|
||||||
component: Register,
|
component: Register,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: Routes.RegistrationTerms,
|
||||||
|
component: RegistrationTerms,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: Routes.CreatePassword,
|
name: Routes.CreatePassword,
|
||||||
component: CreatePassword,
|
component: CreatePassword,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export const Routes = {
|
|||||||
ForgotPassword: 'ForgotPassword',
|
ForgotPassword: 'ForgotPassword',
|
||||||
ResetPassword: 'ResetPassword',
|
ResetPassword: 'ResetPassword',
|
||||||
Register: 'Register',
|
Register: 'Register',
|
||||||
|
RegistrationTerms: 'RegistrationTerms',
|
||||||
CreatePassword: 'CreatePassword',
|
CreatePassword: 'CreatePassword',
|
||||||
CreatePseudo: 'CreatePseudo',
|
CreatePseudo: 'CreatePseudo',
|
||||||
RegistrationChoice: 'RegistrationChoice',
|
RegistrationChoice: 'RegistrationChoice',
|
||||||
|
|||||||
+29
-291
@@ -1,15 +1,15 @@
|
|||||||
import { useRoute } from '@react-navigation/native'
|
import { useRoute } from '@react-navigation/native'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { Modal, Pressable, ScrollView, Text, View } from 'react-native'
|
import { Pressable, Text, View } from 'react-native'
|
||||||
import { responsiveHeight } from 'react-native-responsive-dimensions'
|
import { responsiveHeight } from 'react-native-responsive-dimensions'
|
||||||
import { useGlobal } from 'reactn'
|
import { useGlobal } from 'reactn'
|
||||||
import { background } from '../assets'
|
import { background } from '../assets'
|
||||||
import BorderGradientButton from '../components/BorderGradientButton'
|
|
||||||
import GradientButton from '../components/GradientButton'
|
import GradientButton from '../components/GradientButton'
|
||||||
import { Input } from '../components/Input'
|
import { Input } from '../components/Input'
|
||||||
import ItemContainer from '../components/ItemContainer/ItemContainer'
|
import ItemContainer from '../components/ItemContainer/ItemContainer'
|
||||||
import { checkIfPasswordIsStrongEnough, handleFirebaseError } from '../actions/signupActions'
|
import { checkIfPasswordIsStrongEnough, handleFirebaseError } from '../actions/signupActions'
|
||||||
import firebase, { usersRef } from '../config/firebase'
|
import firebase, { usersRef } from '../config/firebase'
|
||||||
|
import { REGISTRATION_TERMS_VERSION } from '../data/legal'
|
||||||
import Page from '../layouts/Page'
|
import Page from '../layouts/Page'
|
||||||
import { isWeb } from '../hooks/useLayoutType'
|
import { isWeb } from '../hooks/useLayoutType'
|
||||||
import { Routes } from '../navigation'
|
import { Routes } from '../navigation'
|
||||||
@@ -17,7 +17,7 @@ import { reset } from '../navigation/NavigationService'
|
|||||||
import { Palette } from '../styles'
|
import { Palette } from '../styles'
|
||||||
import { FONT_FAMILY } from '../styles/Fonts'
|
import { FONT_FAMILY } from '../styles/Fonts'
|
||||||
|
|
||||||
const CreatePassword = () => {
|
const CreatePassword = ({ navigation }) => {
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const email = route?.params?.email || ''
|
const email = route?.params?.email || ''
|
||||||
const firstName = route?.params?.firstName || ''
|
const firstName = route?.params?.firstName || ''
|
||||||
@@ -29,10 +29,8 @@ const CreatePassword = () => {
|
|||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
const [passwordError, setPasswordError] = useState('')
|
const [passwordError, setPasswordError] = useState('')
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [isCguAccepted, setIsCguAccepted] = useState(false)
|
|
||||||
const [isCguModalVisible, setIsCguModalVisible] = useState(false)
|
|
||||||
const [hasScrolledCguToEnd, setHasScrolledCguToEnd] = useState(false)
|
|
||||||
const [, setTooltip] = useGlobal('_tooltip')
|
const [, setTooltip] = useGlobal('_tooltip')
|
||||||
|
const termsAccepted = route.params?.termsAccepted === true
|
||||||
|
|
||||||
const handlePasswordChange = (text) => {
|
const handlePasswordChange = (text) => {
|
||||||
setPassword(text)
|
setPassword(text)
|
||||||
@@ -52,31 +50,8 @@ const CreatePassword = () => {
|
|||||||
|
|
||||||
const isPasswordValid = checkIfPasswordIsStrongEnough({ password })
|
const isPasswordValid = checkIfPasswordIsStrongEnough({ password })
|
||||||
|
|
||||||
const handleToggleCguAccepted = () => {
|
const handleOpenTerms = () => {
|
||||||
setIsCguAccepted((prev) => !prev)
|
navigation.navigate(Routes.RegistrationTerms, { sourceRouteKey: route.key })
|
||||||
}
|
|
||||||
|
|
||||||
const handleOpenCguModal = () => {
|
|
||||||
setHasScrolledCguToEnd(false)
|
|
||||||
setIsCguModalVisible(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleCloseCguModal = () => {
|
|
||||||
setIsCguModalVisible(false)
|
|
||||||
setHasScrolledCguToEnd(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleCguScroll = ({ nativeEvent }) => {
|
|
||||||
const { layoutMeasurement, contentOffset, contentSize } = nativeEvent
|
|
||||||
const paddingToBottom = 20
|
|
||||||
const contentFits = contentSize.height <= layoutMeasurement.height + 1
|
|
||||||
const isAtEnd =
|
|
||||||
layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom
|
|
||||||
if (isAtEnd) {
|
|
||||||
setHasScrolledCguToEnd(true)
|
|
||||||
} else if (contentFits) {
|
|
||||||
setHasScrolledCguToEnd(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const onCreateAccount = async () => {
|
const onCreateAccount = async () => {
|
||||||
@@ -89,11 +64,12 @@ const CreatePassword = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isCguAccepted) {
|
if (!termsAccepted) {
|
||||||
setTooltip({
|
setTooltip({
|
||||||
text: 'Tu dois accepter les CGU pour continuer',
|
text: 'Tu dois accepter les CGU et CGV pour continuer',
|
||||||
type: 'error',
|
type: 'error',
|
||||||
})
|
})
|
||||||
|
handleOpenTerms()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +92,8 @@ const CreatePassword = () => {
|
|||||||
...(country?.code ? { countryCode: country.code } : {}),
|
...(country?.code ? { countryCode: country.code } : {}),
|
||||||
...(country?.name ? { countryName: country.name } : {}),
|
...(country?.name ? { countryName: country.name } : {}),
|
||||||
registrationFlowRequired: true,
|
registrationFlowRequired: true,
|
||||||
|
termsAcceptedAt: firebase.firestore.FieldValue.serverTimestamp(),
|
||||||
|
termsVersion: REGISTRATION_TERMS_VERSION,
|
||||||
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
|
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
|
||||||
updatedAt: firebase.firestore.FieldValue.serverTimestamp(),
|
updatedAt: firebase.firestore.FieldValue.serverTimestamp(),
|
||||||
},
|
},
|
||||||
@@ -207,7 +185,7 @@ const CreatePassword = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Pressable
|
<Pressable
|
||||||
onPress={handleToggleCguAccepted}
|
onPress={handleOpenTerms}
|
||||||
style={{
|
style={{
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@@ -225,7 +203,7 @@ const CreatePassword = () => {
|
|||||||
borderColor: Palette.white,
|
borderColor: Palette.white,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isCguAccepted ? (
|
{termsAccepted ? (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
width: 9,
|
width: 9,
|
||||||
@@ -243,21 +221,23 @@ const CreatePassword = () => {
|
|||||||
fontFamily: FONT_FAMILY.InterRegular,
|
fontFamily: FONT_FAMILY.InterRegular,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
J'accepte les
|
{termsAccepted ? 'CGU et CGV acceptées' : 'Lire et accepter les'}
|
||||||
</Text>
|
|
||||||
</Pressable>
|
|
||||||
<Pressable onPress={handleOpenCguModal}>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 14,
|
|
||||||
color: Palette.white,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
textDecorationLine: 'underline',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
CGU
|
|
||||||
</Text>
|
</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
{!termsAccepted ? (
|
||||||
|
<Pressable onPress={handleOpenTerms}>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 14,
|
||||||
|
color: Palette.white,
|
||||||
|
fontFamily: FONT_FAMILY.InterRegular,
|
||||||
|
textDecorationLine: 'underline',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
CGU et CGV
|
||||||
|
</Text>
|
||||||
|
</Pressable>
|
||||||
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<GradientButton
|
<GradientButton
|
||||||
@@ -267,253 +247,11 @@ const CreatePassword = () => {
|
|||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
}}
|
}}
|
||||||
onPress={onCreateAccount}
|
onPress={onCreateAccount}
|
||||||
disabled={loading || !email || !isPasswordValid || !isCguAccepted}
|
disabled={loading || !email || !isPasswordValid || !termsAccepted}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</ItemContainer>
|
</ItemContainer>
|
||||||
</View>
|
</View>
|
||||||
<Modal
|
|
||||||
animationType="slide"
|
|
||||||
visible={isCguModalVisible}
|
|
||||||
transparent
|
|
||||||
onRequestClose={handleCloseCguModal}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
backgroundColor: Palette.transparentBlack,
|
|
||||||
justifyContent: 'center',
|
|
||||||
paddingHorizontal: 20,
|
|
||||||
paddingVertical: 40,
|
|
||||||
alignItems: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
backgroundColor: Palette.darkPurple,
|
|
||||||
borderRadius: 16,
|
|
||||||
padding: 20,
|
|
||||||
paddingTop: 28,
|
|
||||||
maxHeight: '75%',
|
|
||||||
width: '90%',
|
|
||||||
flexShrink: 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Pressable
|
|
||||||
onPress={handleCloseCguModal}
|
|
||||||
style={{
|
|
||||||
position: 'absolute',
|
|
||||||
top: 12,
|
|
||||||
right: 12,
|
|
||||||
padding: 6,
|
|
||||||
zIndex: 2,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 16,
|
|
||||||
color: Palette.gray,
|
|
||||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
X
|
|
||||||
</Text>
|
|
||||||
</Pressable>
|
|
||||||
<View style={{ gap: 16, flex: 1 }}>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 20,
|
|
||||||
color: Palette.white,
|
|
||||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
|
||||||
textAlign: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Conditions Générales d'Utilisation
|
|
||||||
</Text>
|
|
||||||
<ScrollView
|
|
||||||
showsVerticalScrollIndicator={false}
|
|
||||||
contentContainerStyle={{ gap: 16, paddingBottom: 12 }}
|
|
||||||
onScroll={handleCguScroll}
|
|
||||||
onMomentumScrollEnd={handleCguScroll}
|
|
||||||
scrollEventThrottle={16}
|
|
||||||
style={{ flex: 1 }}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 14,
|
|
||||||
color: Palette.gray,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
lineHeight: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cupidatat incididunt aute aute velit deserunt labore excepteur eu velit cillum
|
|
||||||
est. Laboris in sunt ea Lorem culpa velit nisi ad elit esse voluptate id
|
|
||||||
adipisicing nulla magna. Duis qui fugiat consequat elit velit aute ad.
|
|
||||||
Reprehenderit proident duis exercitation velit proident aute minim. Anim
|
|
||||||
reprehenderit mollit consectetur id sint adipisicing pariatur tempor sit pariatur
|
|
||||||
proident nostrud. Sit culpa tempor enim ut consectetur sunt aute est reprehenderit
|
|
||||||
incididunt incididunt in ullamco consectetur. Eiusmod non incididunt proident
|
|
||||||
eiusmod. Esse Lorem ut amet in est id aute consectetur.
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 14,
|
|
||||||
color: Palette.gray,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
lineHeight: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Aliqua est sint consectetur occaecat exercitation. Elit nisi velit ad qui eiusmod
|
|
||||||
reprehenderit proident labore nostrud labore consequat enim fugiat non. Eiusmod
|
|
||||||
occaecat pariatur deserunt velit elit sint irure fugiat excepteur labore ad velit
|
|
||||||
ex deserunt laborum. Aliqua excepteur reprehenderit nostrud aliqua pariatur aliqua
|
|
||||||
excepteur Lorem consectetur. Ut est culpa ullamco ipsum Lorem ullamco ea labore
|
|
||||||
anim.
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 14,
|
|
||||||
color: Palette.gray,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
lineHeight: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Et ut ex duis tempor amet aliquip cupidatat sit sit. Aliqua consectetur amet duis
|
|
||||||
fugiat nulla duis culpa exercitation reprehenderit. Ea voluptate proident ad elit
|
|
||||||
pariatur do. Culpa incididunt deserunt dolor ut officia aliquip ut occaecat
|
|
||||||
eiusmod sint veniam. Deserunt consequat adipisicing aliquip velit labore fugiat
|
|
||||||
aute culpa id sint. Adipisicing eu commodo ex do aliqua in labore laboris sit sunt
|
|
||||||
adipisicing excepteur. Do sint velit veniam pariatur consequat proident cupidatat
|
|
||||||
in incididunt ullamco.
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 14,
|
|
||||||
color: Palette.gray,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
lineHeight: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Culpa eu cillum fugiat elit eiusmod enim. Cupidatat culpa aliquip culpa et tempor
|
|
||||||
est velit. Aute id deserunt non ut minim deserunt adipisicing sit veniam eu id
|
|
||||||
incididunt adipisicing dolore. Eiusmod nisi excepteur est voluptate consequat
|
|
||||||
reprehenderit non exercitation commodo aute.
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 14,
|
|
||||||
color: Palette.gray,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
lineHeight: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Eu culpa enim dolore anim ipsum eu veniam mollit dolore officia cupidatat laborum
|
|
||||||
officia do. Ad proident in anim nisi exercitation consequat exercitation occaecat
|
|
||||||
consequat ut laborum esse consectetur ullamco. Enim elit sit in id velit quis
|
|
||||||
nostrud nostrud eu labore aute reprehenderit voluptate deserunt. Minim voluptate
|
|
||||||
et duis voluptate enim duis.
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 14,
|
|
||||||
color: Palette.gray,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
lineHeight: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Minim laboris deserunt minim ex. Duis aliquip cillum proident. Magna velit nisi
|
|
||||||
fugiat. Non id proident pariatur elit in exercitation et amet id qui ad laborum
|
|
||||||
nulla ullamco ea.
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 14,
|
|
||||||
color: Palette.gray,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
lineHeight: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cillum nisi aute dolore culpa est veniam cupidatat sunt sint ipsum. Amet ullamco
|
|
||||||
minim non voluptate cillum dolore sunt irure nulla pariatur excepteur voluptate
|
|
||||||
id. Commodo ullamco aliqua non ea mollit ullamco do minim dolor magna. Ipsum eu
|
|
||||||
minim quis laborum do dolore labore eiusmod et. Ullamco officia velit anim.
|
|
||||||
Exercitation voluptate reprehenderit ex et do eu fugiat tempor do cillum ad.
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 14,
|
|
||||||
color: Palette.gray,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
lineHeight: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cupidatat consectetur excepteur commodo laborum incididunt laboris minim dolore ut
|
|
||||||
ipsum dolor ullamco culpa aliquip. Cillum proident quis consectetur voluptate
|
|
||||||
labore nisi Lorem pariatur in esse. Amet ipsum mollit officia fugiat Lorem ipsum
|
|
||||||
elit officia. Esse reprehenderit magna quis irure sit consectetur dolore sunt
|
|
||||||
mollit aliquip eiusmod voluptate amet. Ex irure culpa ea cupidatat nulla ea labore
|
|
||||||
aute occaecat consequat consectetur cillum amet. Velit ad do occaecat non elit
|
|
||||||
quis. Amet id reprehenderit ullamco amet tempor deserunt exercitation elit
|
|
||||||
consectetur minim aliqua. Cillum do aliquip do ea ipsum veniam deserunt in ipsum
|
|
||||||
pariatur nisi proident et ut deserunt.
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 14,
|
|
||||||
color: Palette.gray,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
lineHeight: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Mollit et adipisicing velit tempor deserunt excepteur fugiat eiusmod adipisicing.
|
|
||||||
Tempor do ex duis dolor deserunt cillum officia est nisi mollit fugiat. Amet duis
|
|
||||||
ea laboris officia aliquip id sint voluptate consectetur velit elit reprehenderit
|
|
||||||
nostrud exercitation. Ea dolore adipisicing nulla incididunt laboris sint commodo
|
|
||||||
non mollit eiusmod. Tempor nulla eu laborum tempor veniam laboris consequat non
|
|
||||||
consequat exercitation pariatur velit. Voluptate magna mollit esse incididunt id.
|
|
||||||
Pariatur eu irure esse ullamco fugiat culpa.
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 14,
|
|
||||||
color: Palette.gray,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
lineHeight: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Sint dolore aliqua pariatur do mollit occaecat deserunt qui proident non
|
|
||||||
exercitation mollit cillum culpa. Est cupidatat consequat ea commodo laborum
|
|
||||||
labore sunt excepteur labore aute est amet anim. Tempor deserunt labore mollit
|
|
||||||
enim officia aliqua occaecat. Ullamco mollit qui mollit do ex irure enim.
|
|
||||||
</Text>
|
|
||||||
</ScrollView>
|
|
||||||
{hasScrolledCguToEnd ? (
|
|
||||||
<View style={{ gap: 10 }}>
|
|
||||||
<GradientButton
|
|
||||||
title="Accepter sans réserve"
|
|
||||||
onPress={() => {
|
|
||||||
setIsCguAccepted(true)
|
|
||||||
handleCloseCguModal()
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<BorderGradientButton title="Refuser" onPress={handleCloseCguModal} />
|
|
||||||
</View>
|
|
||||||
) : (
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 12,
|
|
||||||
color: Palette.gray,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
textAlign: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Fais défiler jusqu'en bas pour afficher les actions
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</Modal>
|
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import Page from '../layouts/Page'
|
|||||||
|
|
||||||
import { Fonts } from '../styles'
|
import { Fonts } from '../styles'
|
||||||
|
|
||||||
const privacyPolicy = `Politique de Confidentialité de minuit.starter
|
const privacyPolicy = `Politique de Confidentialité de MusicLand
|
||||||
|
|
||||||
1. Introduction
|
1. Introduction
|
||||||
|
|
||||||
La présente Politique de Confidentialité s'applique à l'application "minuit.starter" éditée par MINUIT.AGENCY. Elle a pour objet d'informer les utilisateurs de la manière dont leurs informations personnelles sont collectées, utilisées et protégées.
|
La présente Politique de Confidentialité s'applique à l'application "MusicLand" éditée par MINUIT.AGENCY. Elle a pour objet d'informer les utilisateurs de la manière dont leurs informations personnelles sont collectées, utilisées et protégées.
|
||||||
|
|
||||||
2. Collecte des données
|
2. Collecte des données
|
||||||
|
|
||||||
|
|||||||
+81
-8
@@ -32,7 +32,7 @@ import { getRouteAfterAuthentication } from '../utils/registrationFlow'
|
|||||||
|
|
||||||
const LANGUAGE_STORAGE_KEY = 'preferredLanguage'
|
const LANGUAGE_STORAGE_KEY = 'preferredLanguage'
|
||||||
|
|
||||||
const Register = ({ navigation }) => {
|
const Register = ({ navigation, route }) => {
|
||||||
const { width: viewportWidth, height: viewportHeight } = useWindowDimensions()
|
const { width: viewportWidth, height: viewportHeight } = useWindowDimensions()
|
||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
const [firstName, setFirstName] = useState('')
|
const [firstName, setFirstName] = useState('')
|
||||||
@@ -80,9 +80,26 @@ const Register = ({ navigation }) => {
|
|||||||
} = useSocialAuth({
|
} = useSocialAuth({
|
||||||
onSuccess: afterSocialAuth,
|
onSuccess: afterSocialAuth,
|
||||||
preferredLanguage,
|
preferredLanguage,
|
||||||
|
termsAccepted: route.params?.termsAccepted === true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const isBusy = socialLoading
|
const isBusy = socialLoading
|
||||||
|
const termsAccepted = route.params?.termsAccepted === true
|
||||||
|
|
||||||
|
const openRegistrationTerms = useCallback(() => {
|
||||||
|
navigation.navigate(Routes.RegistrationTerms, { sourceRouteKey: route.key })
|
||||||
|
}, [navigation, route.key])
|
||||||
|
|
||||||
|
const requireTermsAcceptance = useCallback(
|
||||||
|
(action) => {
|
||||||
|
if (!termsAccepted) {
|
||||||
|
openRegistrationTerms()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
action()
|
||||||
|
},
|
||||||
|
[openRegistrationTerms, termsAccepted]
|
||||||
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
AsyncStorage.getItem(LANGUAGE_STORAGE_KEY)
|
AsyncStorage.getItem(LANGUAGE_STORAGE_KEY)
|
||||||
@@ -121,12 +138,17 @@ const Register = ({ navigation }) => {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (!termsAccepted) {
|
||||||
|
openRegistrationTerms()
|
||||||
|
return
|
||||||
|
}
|
||||||
navigate(Routes.CreatePassword, {
|
navigate(Routes.CreatePassword, {
|
||||||
email: email.trim(),
|
email: email.trim(),
|
||||||
firstName: firstName.trim(),
|
firstName: firstName.trim(),
|
||||||
lastName: lastName.trim(),
|
lastName: lastName.trim(),
|
||||||
birthDate: birthDate ? birthDate.toISOString() : null,
|
birthDate: birthDate ? birthDate.toISOString() : null,
|
||||||
preferredLanguage,
|
preferredLanguage,
|
||||||
|
termsAccepted: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,14 +247,35 @@ const Register = ({ navigation }) => {
|
|||||||
/>
|
/>
|
||||||
<View style={styles.socialWrapper}>
|
<View style={styles.socialWrapper}>
|
||||||
{isAppleSignInAvailable ? (
|
{isAppleSignInAvailable ? (
|
||||||
<AppleAuthButton onPress={signInWithApple} disabled={isBusy} loading={socialLoading} />
|
<AppleAuthButton
|
||||||
|
onPress={() => requireTermsAcceptance(signInWithApple)}
|
||||||
|
disabled={isBusy}
|
||||||
|
loading={socialLoading}
|
||||||
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<GoogleAuthButton onPress={signInWithGoogle} disabled={isBusy} loading={socialLoading} />
|
<GoogleAuthButton
|
||||||
|
onPress={() => requireTermsAcceptance(signInWithGoogle)}
|
||||||
|
disabled={isBusy}
|
||||||
|
loading={socialLoading}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.footer}>
|
<View style={styles.footer}>
|
||||||
<Text style={styles.terms}>
|
<Pressable
|
||||||
En t’inscrivant, tu acceptes nos conditions générales{'\n'}
|
accessibilityRole="button"
|
||||||
d’utilisation et notre politique de confidentialité.
|
onPress={openRegistrationTerms}
|
||||||
|
style={styles.termsAcceptance}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[styles.termsIndicator, termsAccepted ? styles.termsIndicatorAccepted : null]}
|
||||||
|
>
|
||||||
|
{termsAccepted ? <View style={styles.termsIndicatorDot} /> : null}
|
||||||
|
</View>
|
||||||
|
<Text style={styles.terms}>
|
||||||
|
{termsAccepted ? 'CGU et CGV acceptées' : 'Lire et accepter les CGU et CGV'}
|
||||||
|
</Text>
|
||||||
|
</Pressable>
|
||||||
|
<Text style={styles.privacyText}>
|
||||||
|
En t’inscrivant, tu acceptes notre politique de confidentialité.
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={styles.bottomFooterText}>
|
<Text style={styles.bottomFooterText}>
|
||||||
@@ -424,12 +467,42 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: 4,
|
gap: 8,
|
||||||
|
},
|
||||||
|
termsAcceptance: {
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
gap: 8,
|
||||||
|
},
|
||||||
|
termsIndicator: {
|
||||||
|
alignItems: 'center',
|
||||||
|
borderColor: Palette.white,
|
||||||
|
borderRadius: 100,
|
||||||
|
borderWidth: 1,
|
||||||
|
height: 17,
|
||||||
|
justifyContent: 'center',
|
||||||
|
width: 17,
|
||||||
|
},
|
||||||
|
termsIndicatorAccepted: {
|
||||||
|
borderColor: Palette.green,
|
||||||
|
},
|
||||||
|
termsIndicatorDot: {
|
||||||
|
backgroundColor: Palette.green,
|
||||||
|
borderRadius: 100,
|
||||||
|
height: 9,
|
||||||
|
width: 9,
|
||||||
},
|
},
|
||||||
terms: {
|
terms: {
|
||||||
fontSize: 12,
|
fontSize: 14,
|
||||||
|
color: Palette.white,
|
||||||
|
fontFamily: FONT_FAMILY.HelveticaNeueRegular,
|
||||||
|
textAlign: 'center',
|
||||||
|
textDecorationLine: 'underline',
|
||||||
|
},
|
||||||
|
privacyText: {
|
||||||
color: Palette.gray,
|
color: Palette.gray,
|
||||||
fontFamily: FONT_FAMILY.HelveticaNeueRegular,
|
fontFamily: FONT_FAMILY.HelveticaNeueRegular,
|
||||||
|
fontSize: 12,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
loginText: {
|
loginText: {
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
import { CommonActions } from '@react-navigation/native'
|
||||||
|
import React, { useCallback, useState } from 'react'
|
||||||
|
import { ScrollView, StyleSheet, Text, View } from 'react-native'
|
||||||
|
|
||||||
|
import { background } from '../assets'
|
||||||
|
import GradientButton from '../components/GradientButton'
|
||||||
|
import { isWeb } from '../hooks/useLayoutType'
|
||||||
|
import Page from '../layouts/Page'
|
||||||
|
import { Palette } from '../styles'
|
||||||
|
import { FONT_FAMILY } from '../styles/Fonts'
|
||||||
|
import { termsOfUse } from './TermsOfUse'
|
||||||
|
|
||||||
|
const RegistrationTerms = ({ navigation, route }) => {
|
||||||
|
const [hasReachedEnd, setHasReachedEnd] = useState(false)
|
||||||
|
const sourceRouteKey = route.params?.sourceRouteKey
|
||||||
|
|
||||||
|
const updateScrollStatus = useCallback(({ nativeEvent }) => {
|
||||||
|
const { contentOffset, contentSize, layoutMeasurement } = nativeEvent
|
||||||
|
const endThreshold = 20
|
||||||
|
const reachedEnd =
|
||||||
|
contentSize.height <= layoutMeasurement.height + 1 ||
|
||||||
|
layoutMeasurement.height + contentOffset.y >= contentSize.height - endThreshold
|
||||||
|
|
||||||
|
if (reachedEnd) {
|
||||||
|
setHasReachedEnd(true)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleAccept = useCallback(() => {
|
||||||
|
if (!hasReachedEnd || !sourceRouteKey) return
|
||||||
|
|
||||||
|
navigation.dispatch({
|
||||||
|
...CommonActions.setParams({ termsAccepted: true }),
|
||||||
|
source: sourceRouteKey,
|
||||||
|
})
|
||||||
|
navigation.goBack()
|
||||||
|
}, [hasReachedEnd, navigation, sourceRouteKey])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page
|
||||||
|
width={isWeb ? 760 : null}
|
||||||
|
maxWidth={760}
|
||||||
|
backgroundImg={isWeb ? background.loginBgWeb : background.homeBG}
|
||||||
|
headerType="NAVIGATION"
|
||||||
|
title="CGU et CGV"
|
||||||
|
>
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text style={styles.introduction}>
|
||||||
|
Lis les conditions générales jusqu'en bas pour pouvoir les accepter.
|
||||||
|
</Text>
|
||||||
|
<View style={styles.documentContainer}>
|
||||||
|
<ScrollView
|
||||||
|
contentContainerStyle={styles.documentContent}
|
||||||
|
onScroll={updateScrollStatus}
|
||||||
|
onMomentumScrollEnd={updateScrollStatus}
|
||||||
|
scrollEventThrottle={16}
|
||||||
|
showsVerticalScrollIndicator
|
||||||
|
>
|
||||||
|
<Text selectable style={styles.documentText}>
|
||||||
|
{termsOfUse}
|
||||||
|
</Text>
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.scrollHint}>
|
||||||
|
{hasReachedEnd
|
||||||
|
? 'Tu peux maintenant accepter les conditions.'
|
||||||
|
: 'Fais défiler le document jusqu’en bas pour continuer.'}
|
||||||
|
</Text>
|
||||||
|
<GradientButton
|
||||||
|
title="J’accepte les CGU et CGV"
|
||||||
|
onPress={handleAccept}
|
||||||
|
disabled={!hasReachedEnd}
|
||||||
|
containerStyle={styles.acceptButton}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
gap: 16,
|
||||||
|
paddingVertical: 16,
|
||||||
|
},
|
||||||
|
introduction: {
|
||||||
|
color: Palette.gray,
|
||||||
|
fontFamily: FONT_FAMILY.InterRegular,
|
||||||
|
fontSize: 14,
|
||||||
|
lineHeight: 20,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
documentContainer: {
|
||||||
|
flex: 1,
|
||||||
|
minHeight: 220,
|
||||||
|
overflow: 'hidden',
|
||||||
|
borderColor: Palette.ultraLightWhite,
|
||||||
|
borderRadius: 16,
|
||||||
|
borderWidth: 1,
|
||||||
|
backgroundColor: Palette.lightPurple,
|
||||||
|
},
|
||||||
|
documentContent: {
|
||||||
|
padding: 20,
|
||||||
|
},
|
||||||
|
documentText: {
|
||||||
|
color: Palette.gray,
|
||||||
|
fontFamily: FONT_FAMILY.InterRegular,
|
||||||
|
fontSize: 14,
|
||||||
|
lineHeight: 21,
|
||||||
|
},
|
||||||
|
scrollHint: {
|
||||||
|
color: Palette.gray,
|
||||||
|
fontFamily: FONT_FAMILY.InterRegular,
|
||||||
|
fontSize: 12,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
acceptButton: {
|
||||||
|
alignSelf: 'center',
|
||||||
|
width: '100%',
|
||||||
|
maxWidth: 420,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default RegistrationTerms
|
||||||
+11
-11
@@ -5,7 +5,7 @@ import Page from '../layouts/Page'
|
|||||||
|
|
||||||
import { Fonts } from '../styles'
|
import { Fonts } from '../styles'
|
||||||
|
|
||||||
const terms = `Conditions Générales d'Utilisation (CGU) de minuit.starter
|
export const termsOfUse = `Conditions Générales d'Utilisation (CGU) de MusicLand
|
||||||
|
|
||||||
Édition par MINUIT.AGENCY,
|
Édition par MINUIT.AGENCY,
|
||||||
44 RUE MINVIELLE, 33000 BORDEAUX,
|
44 RUE MINVIELLE, 33000 BORDEAUX,
|
||||||
@@ -15,16 +15,16 @@ Représenté par minuit.holdings, Président.
|
|||||||
|
|
||||||
Définitions :
|
Définitions :
|
||||||
|
|
||||||
Utilisateur : toute personne physique ou morale qui utilise l'application minuit.starter.
|
Utilisateur : toute personne physique ou morale qui utilise l'application MusicLand.
|
||||||
Contenu Utilisateur : toute information, texte, image, ou autre matériel que les utilisateurs publient ou partagent sur minuit.starter.
|
Contenu Utilisateur : toute information, texte, image, ou autre matériel que les utilisateurs publient ou partagent sur MusicLand.
|
||||||
Minuit.boost : service prioritaire commandé par les utilisateurs sur minuit.starter pour accélérer le processus de réalisation de leurs tâches.
|
Minuit.boost : service prioritaire commandé par les utilisateurs sur MusicLand pour accélérer le processus de réalisation de leurs tâches.
|
||||||
Tâche Supplémentaire : toute tâche additionnelle commandée par les utilisateurs sur minuit.starter.
|
Tâche Supplémentaire : toute tâche additionnelle commandée par les utilisateurs sur MusicLand.
|
||||||
Minuit.coin : unité de monnaie virtuelle utilisée sur minuit.starter pour acheter des services ou des tâches supplémentaires.
|
Minuit.coin : unité de monnaie virtuelle utilisée sur MusicLand pour acheter des services ou des tâches supplémentaires.
|
||||||
Acceptation des CGU et CGV
|
Acceptation des CGU et CGV
|
||||||
L'utilisation de "minuit.starter" et/ou le téléchargement de l'application sur l'App Store iOS implique l'acceptation inconditionnelle de ces CGU. Tout achat de services ou de tâches supplémentaires sur la plateforme implique également l'acceptation des Conditions Générales de Vente (CGV). Si vous n'êtes pas d'accord avec l'une de ces conditions, vous devez immédiatement cesser toute utilisation de l'application.
|
L'utilisation de "MusicLand" et/ou le téléchargement de l'application sur l'App Store iOS implique l'acceptation inconditionnelle de ces CGU. Tout achat de services ou de tâches supplémentaires sur la plateforme implique également l'acceptation des Conditions Générales de Vente (CGV). Si vous n'êtes pas d'accord avec l'une de ces conditions, vous devez immédiatement cesser toute utilisation de l'application.
|
||||||
|
|
||||||
Objet
|
Objet
|
||||||
"minuit.starter" fournit des outils pour aider les utilisateurs à publier des tâches, suivre l'évolution de leurs projets, commander des Minuit.boosts pour un service prioritaire, commander des tâches supplémentaires, et acheter des minuit.coins pour utiliser les services payants proposés sur la plateforme.
|
"MusicLand" fournit des outils pour aider les utilisateurs à publier des tâches, suivre l'évolution de leurs projets, commander des Minuit.boosts pour un service prioritaire, commander des tâches supplémentaires, et acheter des minuit.coins pour utiliser les services payants proposés sur la plateforme.
|
||||||
|
|
||||||
Fonctionnement AI de l'Application
|
Fonctionnement AI de l'Application
|
||||||
Toutes les informations, notamment les délais, fournies par l'application sont basées sur des algorithmes d'intelligence artificielle. Elles sont fournies "telles quelles", sans garantie d'exactitude, d'exhaustivité ou de pertinence pour des situations spécifiques. Les réponses du chat AI sont à titre informatif et ne doivent pas remplacer un avis professionnel.
|
Toutes les informations, notamment les délais, fournies par l'application sont basées sur des algorithmes d'intelligence artificielle. Elles sont fournies "telles quelles", sans garantie d'exactitude, d'exhaustivité ou de pertinence pour des situations spécifiques. Les réponses du chat AI sont à titre informatif et ne doivent pas remplacer un avis professionnel.
|
||||||
@@ -33,13 +33,13 @@ Accès & Utilisation
|
|||||||
Seuls les individus majeurs et capables juridiquement peuvent utiliser l'application. Toute utilisation illégale, abusive ou en violation des présentes CGU est interdite.
|
Seuls les individus majeurs et capables juridiquement peuvent utiliser l'application. Toute utilisation illégale, abusive ou en violation des présentes CGU est interdite.
|
||||||
|
|
||||||
Disponibilité & Interruption
|
Disponibilité & Interruption
|
||||||
L'accès à minuit.starter peut être interrompu, suspendu ou modifié à tout moment, pour n'importe quelle raison, sans préavis ni obligation. MINUIT.AGENCY ne sera pas responsable des pertes de données ou des interruptions de service.
|
L'accès à MusicLand peut être interrompu, suspendu ou modifié à tout moment, pour n'importe quelle raison, sans préavis ni obligation. MINUIT.AGENCY ne sera pas responsable des pertes de données ou des interruptions de service.
|
||||||
|
|
||||||
Confidentialité
|
Confidentialité
|
||||||
Nous traitons les données personnelles conformément à notre politique de confidentialité, que les utilisateurs doivent consulter séparément.
|
Nous traitons les données personnelles conformément à notre politique de confidentialité, que les utilisateurs doivent consulter séparément.
|
||||||
|
|
||||||
Responsabilité des Informations et Contenu Utilisateur
|
Responsabilité des Informations et Contenu Utilisateur
|
||||||
MINUIT.AGENCY ne garantit pas la véracité, la précision, ou la fiabilité des informations fournies par l'application. minuit.starter est une plateforme sur laquelle les utilisateurs peuvent publier du contenu. Malgré nos meilleurs efforts pour maintenir un environnement sûr et respectueux, MINUIT.AGENCY n'est pas responsable du contenu publié par les utilisateurs. Tout contenu publié reflète uniquement l'opinion de l'utilisateur qui le publie.
|
MINUIT.AGENCY ne garantit pas la véracité, la précision, ou la fiabilité des informations fournies par l'application. MusicLand est une plateforme sur laquelle les utilisateurs peuvent publier du contenu. Malgré nos meilleurs efforts pour maintenir un environnement sûr et respectueux, MINUIT.AGENCY n'est pas responsable du contenu publié par les utilisateurs. Tout contenu publié reflète uniquement l'opinion de l'utilisateur qui le publie.
|
||||||
|
|
||||||
Propriété Intellectuelle
|
Propriété Intellectuelle
|
||||||
Toute violation des droits de propriété intellectuelle de MINUIT.AGENCY pourra donner lieu à des poursuites judiciaires.
|
Toute violation des droits de propriété intellectuelle de MINUIT.AGENCY pourra donner lieu à des poursuites judiciaires.
|
||||||
@@ -67,7 +67,7 @@ Dernière mise à jour : 22/10/2023.`
|
|||||||
export default ({ navigation, route }) => {
|
export default ({ navigation, route }) => {
|
||||||
return (
|
return (
|
||||||
<Page headerType="NAVIGATE" title={"Conditions Générales d'Utilisation"} scrollEnabled>
|
<Page headerType="NAVIGATE" title={"Conditions Générales d'Utilisation"} scrollEnabled>
|
||||||
<Text style={{ ...Fonts({ type: 'default' }) }}>{terms}</Text>
|
<Text style={{ ...Fonts({ type: 'default' }) }}>{termsOfUse}</Text>
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user