AmplifyStudio & Figma

# この記事の目的

AmplifyStudioとFigmaを連携させてUIコンポーネントの自動生成が可能となったので試してみました。
位置付けとしては個人的な備忘録ですが、誰かの参考になれば幸いです。

# 内容
この記事は、以下のチュートリアル記事の抜粋翻訳及び補足です。（翻訳してポストして良いと言う旨は元記事の著者に了解をもらっています。）
チュートリアルを実施する場合には、リンク元から飛べるYouTubeを見ながら進めるのが一番分かり易いと思います。
尚、Amplifyから自動生成コードをpullする箇所は元記事だけだと詰まる可能性があるので、補記しました。

https://dev.to/aspittel/build-a-social-media-timeline-with-amplify-studio-2lof


# 環境
今回は、以下の環境で開発しています。（なお、記事の内容は特に環境に依存しません）
* Windows10Pro
* WSL2（Ubuntu)
* VSCode

# 前提
* 以下のアカウントを作成済みであること
  * AWS
  * Figma
* ローカル開発環境に以下がインストール済みであること（LTS版を前提に説明）
  * node
  * npm

# 大まかな手順

* AmplifyStudioを用いてDataModelを定義
* Figmaを用いて画面デザインをUIKitをベースに作成
* FigmaとAmplifyStudioを同期してDataModelとUIを紐付け
* ローカルのReactプロジェクトとAmplifyStudioの紐付け

# 手順詳細

## AmplifyStudioを用いてDataModelを定義

### DataModel定義
まず、AmplifyStudioでプロジェクトを作成します。
AmplifyStduioにはAWSマネジメントコンソールからアクセス可能です。

Amplifyのメニューからアプリケーション（今回は「twetwe」という名前）を作成し、以下の画面に遷移します。
その後に、「LaunchStduio」を押下します。
![pic01_amplify_top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/dea8efc4-b41c-e4a3-66b7-5c9f88d4dd70.png)

AmplifyStduioのトップ画面から、「Create data model」を押下します。
こうすると「Data modeling」画面に遷移します。
![pic02_enter_to_data_model.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/8ec7aac0-1cdb-9db1-5078-621626e513cd.png)

「Data modeling」画面でデータモデルの定義をします。
ここでは以下の二つを定義しました。
定義終了後に、「Save and Deploy」を押下します。
* User
    * id
    * profilePic: AWSURL
    * name: String
    * handle: String
    
* Post
    * id
    * content: String
    * postedAt: AWSDateTime
    * likes: int
    * RelationShip (Userとの1対1のリレーションシップ)
![pic03_data_modeling.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/99670a25-1543-7c72-8320-a7d73da59358.png)


### テストデータの登録
AmplifyStudioの左ペインの「Content」からテストデータの登録ができます。
ここでは、UserとPostにデータを登録する例を提示します。

まずUserを登録
![pic06_add_user_on_content.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/3ab8c063-dc51-be06-9ba3-f4c0561d301c.png)
次にPost
![pic07_add_post_on_content.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/1761cad1-f34f-05ea-9d96-c510b66668e6.png)

自動的にDynamoDBに反映されるのでかなり楽チンです。
![pic07b_dynamo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/699037cd-05c1-b053-4ed5-5ff092991d3e.png)


## Figmaを用いて画面デザインをUIKitをベースに作成
ゼロからFigmaでUIを作ると大変なので[AWS Amplify UI Kit](https://www.figma.com/community/file/1047600760128127424)を使います。Figmaファイルを自分のアカウントに「Duplicate」します。

「CommentCard」というコンポーネントに対していくつかの変更を行います。
* 「like button」以外の「share action」のコンポーネントを削除します
* 「Lorem ipsum」を削除します
* 「"Danny liked this"」を削除します
* 「Body」と「Share」をグルーピングして「CardContent」を作ります

![pic8_figma.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/690e24bf-0737-31d9-f35f-31647c955dd9.png)


## FigmaとAmplifyStdioを同期してDataModelとUIを紐付け

### FigmaのコンポーネントをAmplifyStudioに反映する
AmplifyStudioで左ペインの「UI Library」を選択し、”Get Started”からFigma fileのリンクをペーストします。
![pic09_sync_with_figma.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/6929bf8b-d2c5-f4ff-8114-297a64832d52.png)

AmplifyStduioにUIコンポーネントが反映されました。
（今回は使わないコンポーネントもsyncしましたが、必要なものだけに絞っても良いかもしれません）
![pic11_synced.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/23133151-7c00-cc0e-7b0e-3b08bfd315e5.png)

### UIとDataの紐付け

#### 項目のマッピング
コンポーネントがスタジオに読み込まれたら、"CommentCard"コンポーネントを選択します。まず、`Lorem Ipsum`テキストをクリックします。そして、`label prop`に`post.content`を設定します。

`Authorラベル`を`user.name`に設定します。
`99`のラベルを`post.likes`にセットします。
`画像のsrc`を`user.profilePic`に設定します。

`Timestamp`には、ユーザーのハンドルネームを追加します。Propラベルを"@"に設定し、"concatenate "を選択し、`user.handle`を選択します。

#### リンクの追加
Authorテキストにリンクを追加してみましょう。
まず`prop`に`as`を入力しValueに`a`を入力します。次に`href prop`を"/users/" + user.idに設定しましょう。これで、著者のテキストがユーザーのプロファイルにリンクされるようになります。

#### Eventを追加
CardContentグループを選択し、ソーシャルメディアの投稿がマウスオーバーされるたびにグレーになるようにします。

prop `onMouseEnter` を選択します。アクションを要素の`Modify element property`に設定します。`backgroundColor`を#00000008に設定します。
`onMouseLeave`についても同じことを繰り返しますが、今回は背景色を`transparent`に設定します。

## ローカルのReactプロジェクトとAmplifyStudioの紐付け
最後に自動生成されたReactコンポーネント（ソースコード）を取り込んで、アプリを動かしてみます。

### Amplifyのセッティング
この記事の前提条件では、amplify cliコマンドのインストールが未済なので、まずは、インストールと設定を行います。
内容については[こちらのinstall手順](https://docs.amplify.aws/cli/start/install/#option-2-follow-the-instructions)も参照ください。

```shell
curl -sL https://aws-amplify.github.io/amplify-cli/install | bash && $SHELL

# aws configureのガイドに沿って、Amplifyの管理者権限を持ったIAMユーザーの作成（既存ユーザーも使用可）と、Credential情報の設定を行います。
amplify configure
```


### react project作成
以下のコマンドを用いてreact projectを作成します。
```shell
npx create-react-app tweettweet
```

### 必要なライブラリーのインストール
`@aws-amplify/ui-react`と`aws-amplify`をインストールします。
```shell
npm i @aws-amplify/ui-react aws-amplify
```

### AWSからui-componentsとmodelをpullします。
:::note warn
警告
AmplifyStduio上ではコード取得のコマンドが、以下の形式で案内されます。
`amplify pull --appId <APP_ID> --envName staging`
しかしながら、これを実行すると、pullが失敗します。

この問題は、以下のissueに上がっています。（結構炎上しています）
https://github.com/aws-amplify/amplify-adminui/issues/84

:::

上記の問題は、引数なしで`amplify pull` することで解決します。

```shell
amplify pull
```
こうすると、対話形式で、連携するappIdなどを聞かれるので、それに答えていきます。
![pic14_amplify_pull_no_arg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/6f42157b-478a-2084-b907-a1ce2362b2f4.png)

### コードの修正
以下の箇所のコード修正を行います。
ポイントとしては、自動生成されたコードは一切編集しません！

index.js
```diff_javascript:index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
+import '@aws-amplify/ui-react/styles.css'
+import config from './aws-exports'
+import { Amplify } from 'aws-amplify'

+import { AmplifyProvider } from '@aws-amplify/ui-react'

+Amplify.configure(config)

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
-  <React.StrictMode>
+  <AmplifyProvider>
    <App />
-  </React.StrictMode>
+  </AmplifyProvider>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
```

index.css
```diff_css:index.css
+@import url('https://fonts.googleapis.com/css2?family=Inter:slnt,wght@-10..0,100..900&display=swap');

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}

```

App.js（変更箇所が多いので以下のコードをマルっとコピーすることをお勧めします。）
```javascript:App.js
import { DataStore } from 'aws-amplify';
import { Post } from './models';

import { useEffect, useState } from 'react';
import { CommentCard } from './ui-components';

function App() {
  const [posts, setPosts] = useState([]);

  const getPosts = async () => {
    const data = await DataStore.query(Post);
    setPosts(data);
  };

  useEffect(() => {
    getPosts();
  }, []);

  return (
    <div>
      {posts.map((post) => (
        <CommentCard
          post={post}
          key={post.id}
          user={post.User}
          overrides={{
            Share: {
              onClick: async (e) => {
                e.preventDefault();
                const postToChange = await DataStore.query(Post, post.id);
                await DataStore.save(
                  Post.copyOf(postToChange, (updated) => {
                    updated.likes += 1;
                  })
                );
                getPosts();
              },
            },
          }}
        />
      ))}
    </div>
  );
}
export default App;

```

### 実行してみる

```shell
cd tweettweet
npm start

```

# 感想
初期セットアップまで含めると、Figma、AWSマネジメントコンソール、AmplifyStudio、Terminal、VSCodeなど様々な環境を使うので、若干混乱します。
バックエンドに複雑な処理がないアプリケーションならば簡単に構築してホスティングまでできそうです。
Figma力が高まると色々なことができそうです。

チームとして開発する場合、UX/UIデザイン担当とエンジニアの役割分担やナレッジの共有など工夫が必要と思います。

# 参考
https://dev.to/aspittel/build-a-social-media-timeline-with-amplify-studio-2lof