カレンダーにマーキングする


## 実装した機能
カレンダーに目覚ましチャレンジが成功した場合、マーキングする。

※2024/01/04の青円の印がマーキング後のイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676445/acca9aa7-e4a9-1929-7d88-7d79499fbdbc.png)



## 使ったもの
カレンダー　react-native-calendars
ナビゲーター　react-navigation

https://github.com/wix/react-native-calendars

https://reactnavigation.org/

## やったこと
### UI
カレンダーの表示　画面の上半分をカレンダー表示にしたかった
デザインはシンプルにデフォルトを利用している。
下半分は別機能に利用するため、残しておきたかった。

```react
const HistoryScreen = () => {
    return (
        <View style={styles.container}>
              {/* 上部：カレンダー */}
              <View style={styles.calendarContainer}>
                <Calendar
                  markedDates={markedDates}
                  // その他のプロパティ
                />
              </View>
            </View>
      );
    };

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  calendarContainer: {
    // カレンダーコンポーネントのスタイル
  },
export default HistoryScreen;

```

### react-native-calendars
テストとして、ダミーデータでマーキングできるか確認してみた

```react
    const markedDates = {
    "2023-12-01": { selected: true, marked: true, dotColor: "green" }, // 今日
    "2023-11-30": { selected: true, marked: true, dotColor: "green" }, // 昨日
  };
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676445/6d2ceb64-9afc-7931-d490-ac7d5019c46b.png)


### 画面間のデータの受け渡し
次にアラームを止めた際に、historyScreen.jsにデータが流れるようにした


1. App.js　でナビゲータを設定
    ```react
    import * as React from "react";
    import { View, Text, SafeAreaView } from "react-native";
    import { NavigationContainer } from "@react-navigation/native";
    import { createStackNavigator } from "@react-navigation/stack";
    
    import HistoryScreen from "./screens/HistoryScreen";
    import AlarmScreen from "./screens/AlarmScreen";
    
    const Stack = createStackNavigator();
    
    export default function App() {
      return (
        <NavigationContainer>
          <Stack.Navigator>
            <Stack.Screen name="History" component={HistoryScreen} />
            <Stack.Screen name="Alarm" component={AlarmScreen} />
          </Stack.Navigator>
        </NavigationContainer>
      );
    }
    
    ```

1. AlarmScreen.jsで引値を設定
    ```react
    // AlarmScreen.js
    
    import React, { useState, useEffect } from 'react';
    import { View, Text, TouchableOpacity, Switch, StyleSheet, Image, Button } from 'react-native';
    import { Audio } from 'expo-av';
    import DateTimePicker from '@react-native-community/datetimepicker';
    import Modal from 'react-native-modal';
    
    const AlarmScreen = ({ navigation }) => {
      // ... 他のコード
    
      const stopAlarm = async () => {
        if (sound) {
          clearInterval(alarmIntervalId); // インターバルの停止
          await sound.unloadAsync();
    
          // アラームが止まった情報をHistoryScreenに送信
          navigation.navigate('History', { alarmStopped: true });
        }
      };
    
      // ... 他のコード
    };
    
    export default AlarmScreen;
    
    ```
1. History.jsの更新
    
    routeを引数として、AlarmScreenから渡されたパラメータを利用した。
    routeの中身は、以下の通り。
     ```
     {"key": "History-XXXXXXXXXXXXX", "name": "History", "params": {"alarmStopped": true}, "path": undefined}
     ```
     alarmStoppedをトリガーに、カレンダーにマーキングする処理を実装した。
    
    ```react
    // HistoryScreen.js
    
    import React, { useState, useEffect } from 'react';
    import { View, Text, StyleSheet, FlatList } from 'react-native';
    import { Calendar } from 'react-native-calendars';
    
    const HistoryScreen = ({ route }) => {
      const [markedDates, setMarkedDates] = useState({});
    
      useEffect(() => {
        // アラームが止まった情報があればカレンダーを更新
        if (route.params?.alarmStopped) {
          updateCalendar(); // カレンダー更新関数の呼び出し
        }
      }, [route.params?.alarmStopped]);
    
      const updateCalendar = () => {
        const currentDate = new Date();
        const formattedDate = `${currentDate.getFullYear()}-${currentDate.getMonth() + 1}-${currentDate.getDate()}`;
    
        // カレンダーの日付を更新
        setMarkedDates((prevMarkedDates) => {
          return {
            ...prevMarkedDates,
            [formattedDate]: { selected: true, marked: true, dotColor: 'green' },
          };
        });
      };
    
      // ... 他のコード
    };
    
    export default HistoryScreen;
    
    ```
    


:::note info
詰まったところ
カレンダーの日付フォーマットがyyyy-mm-dd指定だった。
    getMonthで取ると　1月→1　表示になってしまった
そこでpadStart(2, "0")でゼロパディングした。
:::