11import React from "react" ;
2- import { View , Text , StyleSheet } from "react-native" ;
2+ import { View , Text , StyleSheet , Image , ActivityIndicator , Pressable , Platform } from "react-native" ;
33import { SafeAreaView } from "react-native-safe-area-context" ;
4+ import { useAuth } from "@/hooks/useAuth" ;
5+ import { useUserProfile } from "@/hooks/useUserProfile" ;
46
57export default function SettingsScreen ( ) {
8+ const { user, loading, error, signInWithGoogle, signOut } = useAuth ( ) ;
9+ const { profile, loading : profileLoading } = useUserProfile ( user ?. uid ) ;
10+
11+ const onPressSignIn = async ( ) => {
12+ await signInWithGoogle ( ) ;
13+ } ;
14+
15+ const onPressSignOut = async ( ) => {
16+ await signOut ( ) ;
17+ } ;
18+
619 return (
720 < SafeAreaView style = { styles . container } >
821 < View style = { styles . header } >
922 < Text style = { styles . headerTitle } > 設定</ Text >
1023 </ View >
1124 < View style = { styles . content } >
12- < Text style = { styles . placeholderText } > 設定機能は開発中です</ Text >
25+ { loading ? (
26+ < ActivityIndicator size = "large" color = "#4C6EF5" />
27+ ) : user ? (
28+ < View style = { styles . card } >
29+ < View style = { styles . row } >
30+ { user . photoURL ? (
31+ < Image source = { { uri : user . photoURL } } style = { styles . avatar } />
32+ ) : (
33+ < View style = { [ styles . avatar , styles . avatarFallback ] } >
34+ < Text style = { styles . avatarFallbackText } >
35+ { user . displayName ?. [ 0 ] ?. toUpperCase ( ) || "U" }
36+ </ Text >
37+ </ View >
38+ ) }
39+ < View style = { { flex : 1 } } >
40+ < Text style = { styles . name } > { user . displayName || "Signed in user" } </ Text >
41+ < Text style = { styles . email } > { user . email } </ Text >
42+ </ View >
43+ </ View >
44+
45+ < View style = { styles . divider } />
46+
47+ < View style = { styles . infoRow } >
48+ < Text style = { styles . infoLabel } > UID</ Text >
49+ < Text style = { styles . infoValue } numberOfLines = { 1 } > { user . uid } </ Text >
50+ </ View >
51+ < View style = { styles . infoRow } >
52+ < Text style = { styles . infoLabel } > Username</ Text >
53+ { profileLoading ? (
54+ < ActivityIndicator size = "small" />
55+ ) : (
56+ < Text style = { styles . infoValue } > { profile ?. username ?? "未設定" } </ Text >
57+ ) }
58+ </ View >
59+
60+ < View style = { { height : 16 } } />
61+
62+ < Pressable
63+ onPress = { onPressSignOut }
64+ style = { ( { pressed } ) => [ styles . button , styles . signOutButton , pressed && styles . buttonPressed ] }
65+ >
66+ < Text style = { styles . buttonText } > サインアウト</ Text >
67+ </ Pressable >
68+ </ View >
69+ ) : (
70+ < View style = { styles . card } >
71+ < Text style = { styles . placeholderText } > サインインして機能を利用できます。</ Text >
72+ { error ? < Text style = { styles . errorText } > { String ( error ?. message || error ) } </ Text > : null }
73+ < View style = { { height : 16 } } />
74+ < Pressable
75+ disabled = { loading }
76+ onPress = { onPressSignIn }
77+ style = { ( { pressed } ) => [ styles . button , styles . signInButton , ( pressed || loading ) && styles . buttonPressed ] }
78+ >
79+ < Text style = { [ styles . buttonText , { color : "#fff" } ] } > Google でサインイン</ Text >
80+ </ Pressable >
81+ </ View >
82+ ) }
1383 </ View >
1484 </ SafeAreaView >
1585 ) ;
@@ -34,11 +104,94 @@ const styles = StyleSheet.create({
34104 } ,
35105 content : {
36106 flex : 1 ,
107+ padding : 20 ,
108+ } ,
109+ card : {
110+ width : "100%" ,
111+ backgroundColor : "#fff" ,
112+ borderRadius : 16 ,
113+ padding : 20 ,
114+ ...( Platform . select ( {
115+ web : { boxShadow : "0 2px 8px rgba(0,0,0,0.08)" } ,
116+ default : {
117+ shadowColor : "#000" ,
118+ shadowOpacity : 0.08 ,
119+ shadowRadius : 8 ,
120+ shadowOffset : { width : 0 , height : 2 } ,
121+ elevation : 2 ,
122+ } ,
123+ } ) as any ) ,
124+ } ,
125+ row : {
126+ flexDirection : "row" ,
127+ alignItems : "center" ,
128+ gap : 12 ,
129+ } ,
130+ avatar : {
131+ width : 56 ,
132+ height : 56 ,
133+ borderRadius : 28 ,
134+ backgroundColor : "#dee2e6" ,
135+ } ,
136+ avatarFallback : {
137+ alignItems : "center" ,
37138 justifyContent : "center" ,
139+ } ,
140+ avatarFallbackText : {
141+ fontWeight : "700" ,
142+ color : "#495057" ,
143+ } ,
144+ name : {
145+ fontSize : 18 ,
146+ fontWeight : "700" ,
147+ color : "#212529" ,
148+ } ,
149+ email : {
150+ fontSize : 14 ,
151+ color : "#495057" ,
152+ } ,
153+ divider : {
154+ height : 1 ,
155+ backgroundColor : "#e9ecef" ,
156+ marginVertical : 16 ,
157+ } ,
158+ infoRow : {
159+ flexDirection : "row" ,
38160 alignItems : "center" ,
161+ justifyContent : "space-between" ,
162+ gap : 16 ,
163+ } ,
164+ infoLabel : {
165+ fontSize : 14 ,
166+ color : "#495057" ,
167+ } ,
168+ infoValue : {
169+ fontSize : 14 ,
170+ color : "#212529" ,
171+ flex : 1 ,
172+ textAlign : "right" ,
39173 } ,
40174 placeholderText : {
41175 fontSize : 16 ,
42176 color : "#666" ,
43177 } ,
178+ button : {
179+ paddingVertical : 14 ,
180+ borderRadius : 12 ,
181+ alignItems : "center" ,
182+ } ,
183+ buttonPressed : {
184+ opacity : 0.8 ,
185+ } ,
186+ signInButton : {
187+ backgroundColor : "#4C6EF5" ,
188+ } ,
189+ signOutButton : {
190+ backgroundColor : "#f1f3f5" ,
191+ } ,
192+ buttonText : {
193+ fontSize : 16 ,
194+ fontWeight : "600" ,
195+ color : "#212529" ,
196+ } ,
44197} ) ;
0 commit comments