1+ // src/screens/user-settings/SettingsScreen.tsx
2+
13import React , { useState , useEffect } from 'react' ;
24import {
35 View ,
@@ -17,7 +19,7 @@ import {
1719import Slider from '@react-native-community/slider' ;
1820import MultiSelect from 'react-native-multiple-select' ;
1921import useStore from '../../store/store' ;
20- import { saveScheduleToDevice , shareSchedule } from '../../utils/exportSchedule' ;
22+ import { saveScheduleToDevice , shareSchedule , saveScheduleToDeviceWithName } from '../../utils/exportSchedule' ;
2123import pickCSVFile , { pickCSVFileRaw } from '../../utils/csv-picker' ;
2224import { importAndAddToRegisterFromContent } from '../../utils/csv-import' ;
2325
@@ -37,6 +39,8 @@ const SettingsScreen: React.FC = () => {
3739 registers,
3840 activeRegister,
3941 selectedRegisters,
42+ viewingRegisters,
43+ setViewingRegisters,
4044 setDefaultTargetPercentage,
4145 updateAllRegistersTargetPercentage,
4246 selectedSchedules,
@@ -54,7 +58,15 @@ const SettingsScreen: React.FC = () => {
5458 const [ newTargetValue , setNewTargetValue ] = useState ( defaultTargetPercentage . toString ( ) ) ;
5559 const [ localLeadTime , setLocalLeadTime ] = useState ( notificationLeadTime ) ;
5660 const [ localSchedules , setLocalSchedules ] = useState < string [ ] > ( selectedSchedules ) ;
57-
61+ // CSV filename modal state
62+ const [ showFileNameModal , setShowFileNameModal ] = useState ( false ) ;
63+ const [ csvFileName , setCsvFileName ] = useState ( 'MySchedule' ) ;
64+ const [ isSaving , setIsSaving ] = useState ( false ) ;
65+
66+ const registerOptions = Object . keys ( registers ) . map ( key => ( {
67+ id : key ,
68+ name : registers [ parseInt ( key ) ] . name ,
69+ } ) ) ;
5870 // Effects
5971 useEffect ( ( ) => {
6072 setAppVersion ( packageJson . version ) ;
@@ -103,56 +115,56 @@ const SettingsScreen: React.FC = () => {
103115 } ;
104116
105117 // Export functionality handlers
106- const handleSaveScheduleToDevice = async ( ) => {
118+ // Show modal to enter filename
119+ const handleSaveScheduleToDevice = ( ) => {
120+ setShowFileNameModal ( true ) ;
121+ } ;
122+
123+ // Actually save with filename
124+ const handleConfirmSaveFileName = async ( ) => {
125+ setIsSaving ( true ) ;
107126 try {
108- console . log ( 'Starting save to device...' ) ;
109- console . log ( 'Available registers:' , Object . keys ( registers ) ) ;
110- console . log ( 'Selected registers from store:' , selectedRegisters ) ;
111-
112- // Use all registers if no specific selection is available
113- const currentSelectedRegisters = selectedRegisters && selectedRegisters . length > 0
114- ? selectedRegisters
127+ const currentSelectedRegisters = selectedRegisters && selectedRegisters . length > 0
128+ ? selectedRegisters
115129 : Object . keys ( registers ) . map ( key => parseInt ( key , 10 ) ) ;
116-
117- console . log ( 'Using registers for export:' , currentSelectedRegisters ) ;
118-
119130 if ( currentSelectedRegisters . length === 0 ) {
120131 Alert . alert ( 'No Data' , 'No registers found to export. Please create some schedules first.' ) ;
132+ setIsSaving ( false ) ;
121133 return ;
122134 }
123-
124- await saveScheduleToDevice ( {
125- selectedRegisters : currentSelectedRegisters ,
126- registers
127- } ) ;
135+ await saveScheduleToDeviceWithName ( {
136+ selectedRegisters : currentSelectedRegisters ,
137+ registers
138+ } , csvFileName ) ;
139+ setShowFileNameModal ( false ) ;
128140 } catch ( error ) {
129- console . error ( 'Save to device error:' , error ) ;
130141 const errorMessage = error instanceof Error ? error . message : 'Unknown error' ;
131142 Alert . alert ( 'Error' , `Failed to save schedule to device: ${ errorMessage } ` ) ;
132143 }
144+ setIsSaving ( false ) ;
133145 } ;
134146
135147 const handleShareSchedule = async ( ) => {
136148 try {
137149 console . log ( 'Starting share schedule...' ) ;
138150 console . log ( 'Available registers:' , Object . keys ( registers ) ) ;
139151 console . log ( 'Selected registers from store:' , selectedRegisters ) ;
140-
152+
141153 // Use all registers if no specific selection is available
142- const currentSelectedRegisters = selectedRegisters && selectedRegisters . length > 0
143- ? selectedRegisters
154+ const currentSelectedRegisters = selectedRegisters && selectedRegisters . length > 0
155+ ? selectedRegisters
144156 : Object . keys ( registers ) . map ( key => parseInt ( key , 10 ) ) ;
145-
157+
146158 console . log ( 'Using registers for share:' , currentSelectedRegisters ) ;
147-
159+
148160 if ( currentSelectedRegisters . length === 0 ) {
149161 Alert . alert ( 'No Data' , 'No registers found to share. Please create some schedules first.' ) ;
150162 return ;
151163 }
152-
153- await shareSchedule ( {
154- selectedRegisters : currentSelectedRegisters ,
155- registers
164+
165+ await shareSchedule ( {
166+ selectedRegisters : currentSelectedRegisters ,
167+ registers
156168 } ) ;
157169 } catch ( error ) {
158170 console . error ( 'Share schedule error:' , error ) ;
@@ -164,7 +176,7 @@ const SettingsScreen: React.FC = () => {
164176 const handleImportSchedule = async ( ) => {
165177 try {
166178 console . log ( 'Starting CSV import...' ) ;
167-
179+
168180 if ( ! registers [ activeRegister ] ) {
169181 Alert . alert ( 'Error' , 'No active register found. Please create a register first.' ) ;
170182 return ;
@@ -173,7 +185,7 @@ const SettingsScreen: React.FC = () => {
173185 // Use raw CSV content instead of parsed data
174186 const csvContent = await pickCSVFileRaw ( ) ;
175187 console . log ( 'Raw CSV Content received:' , csvContent ) ;
176-
188+
177189 if ( ! csvContent ) {
178190 console . log ( 'No CSV content received (user cancelled or error)' ) ;
179191 return ;
@@ -238,7 +250,6 @@ const SettingsScreen: React.FC = () => {
238250 < Text style = { styles . infoValue } > { registerInfo . name } </ Text >
239251 < Text style = { styles . infoSubtext } > { registerInfo . totalCards } subjects</ Text >
240252 </ View >
241-
242253 { /* Preferences Section */ }
243254 < View style = { styles . settingsSection } >
244255 < Text style = { styles . sectionTitle } > Preferences</ Text >
@@ -294,6 +305,7 @@ const SettingsScreen: React.FC = () => {
294305 </ View >
295306 </ View >
296307
308+
297309 { /* Notifications & Alerts Section */ }
298310 < View style = { styles . settingsSection } >
299311 < Text style = { styles . sectionTitle } > Notifications & Alerts </ Text >
@@ -333,29 +345,71 @@ const SettingsScreen: React.FC = () => {
333345 />
334346 < Button title = "Save Settings" onPress = { handleSave } color = "#4CAF50" />
335347 </ View >
336-
337348 { /* Utilities Section */ }
338349 < View style = { styles . settingsSection } >
339350 < Text style = { styles . sectionTitle } > Utilities</ Text >
340351
341352 < TouchableOpacity style = { styles . utilityButton } onPress = { handleSaveScheduleToDevice } >
342353 < View style = { styles . utilityButtonContent } >
343- < Image
344- source = { require ( '../../assets/icons/save.png' ) }
345- style = { styles . utilityIcon }
354+ < Image
355+ source = { require ( '../../assets/icons/save.png' ) }
356+ style = { styles . utilityIcon }
346357 />
347358 < View style = { styles . utilityTextContainer } >
348359 < Text style = { styles . utilityButtonText } > Save Schedule to Device</ Text >
349360 < Text style = { styles . utilityButtonDescription } > Save your schedule as CSV to Downloads</ Text >
350361 </ View >
351362 </ View >
352363 </ TouchableOpacity >
364+ { /* CSV Filename Modal */ }
365+ < Modal
366+ visible = { showFileNameModal }
367+ transparent = { true }
368+ animationType = "fade"
369+ onRequestClose = { ( ) => setShowFileNameModal ( false ) }
370+ >
371+ < View style = { styles . modalOverlay } >
372+ < View style = { styles . modalContainer } >
373+ < Text style = { styles . modalTitle } > Enter CSV Filename</ Text >
374+ < Text style = { styles . modalSubtitle } > This will be the name of your exported CSV file.</ Text >
375+ < View style = { styles . inputContainer } >
376+ < TextInput
377+ style = { styles . input }
378+ value = { csvFileName }
379+ onChangeText = { setCsvFileName }
380+ placeholder = "Enter filename"
381+ placeholderTextColor = "#71717A"
382+ maxLength = { 40 }
383+ selectTextOnFocus = { true }
384+ autoFocus = { true }
385+ />
386+ < Text style = { styles . percentSymbol } > .csv</ Text >
387+ </ View >
388+ < View style = { styles . modalButtons } >
389+ < TouchableOpacity
390+ style = { [ styles . modalButton , styles . cancelButton ] }
391+ onPress = { ( ) => setShowFileNameModal ( false ) }
392+ disabled = { isSaving }
393+ >
394+ < Text style = { styles . cancelButtonText } > Cancel</ Text >
395+ </ TouchableOpacity >
396+ < TouchableOpacity
397+ style = { [ styles . modalButton , styles . saveButton ] }
398+ onPress = { handleConfirmSaveFileName }
399+ disabled = { isSaving || ! csvFileName . trim ( ) }
400+ >
401+ < Text style = { styles . saveButtonText } > { isSaving ? 'Saving...' : 'Save' } </ Text >
402+ </ TouchableOpacity >
403+ </ View >
404+ </ View >
405+ </ View >
406+ </ Modal >
353407
354408 < TouchableOpacity style = { styles . utilityButton } onPress = { handleShareSchedule } >
355409 < View style = { styles . utilityButtonContent } >
356- < Image
357- source = { require ( '../../assets/icons/share.png' ) }
358- style = { styles . utilityIcon }
410+ < Image
411+ source = { require ( '../../assets/icons/share.png' ) }
412+ style = { styles . utilityIcon }
359413 />
360414 < View style = { styles . utilityTextContainer } >
361415 < Text style = { styles . utilityButtonText } > Share Schedule</ Text >
@@ -366,9 +420,9 @@ const SettingsScreen: React.FC = () => {
366420
367421 < TouchableOpacity style = { styles . utilityButton } onPress = { handleImportSchedule } >
368422 < View style = { styles . utilityButtonContent } >
369- < Image
370- source = { require ( '../../assets/icons/export.png' ) }
371- style = { styles . utilityIcon }
423+ < Image
424+ source = { require ( '../../assets/icons/export.png' ) }
425+ style = { styles . utilityIcon }
372426 />
373427 < View style = { styles . utilityTextContainer } >
374428 < Text style = { styles . utilityButtonText } > Import Schedule from CSV</ Text >
@@ -456,7 +510,6 @@ const SettingsScreen: React.FC = () => {
456510 </ >
457511 ) ;
458512} ;
459-
460513// Styles
461514const styles = StyleSheet . create ( {
462515 container : {
@@ -713,5 +766,4 @@ const styles = StyleSheet.create({
713766 color : '#A1A1AA' ,
714767 } ,
715768} ) ;
716-
717769export default SettingsScreen ;
0 commit comments