こんにちは、皆さん!今回は、Reactを使ったモダンな電卓アプリケーション「Dentaku」を開発し、Vercelにデプロイした経験をシェアしたいと思います。プロジェクトの全体像から、具体的な手順まで詳しく紹介しますので、ぜひ参考にしてください。
アプリリンク
プロジェクトの概要
「Dentaku」は、シンプルでスタイリッシュな電卓アプリケーションです。最新のWeb技術を活用し、ユーザーに快適な使用感を提供することを目指しています。以下はプロジェクトの主な特徴です。
- フロントエンドフレームワーク: React
- ホスティング: Vercel
- スタイル: Tailwind CSS
- 機能: 基本的な計算機能(加算、減算、乗算、除算)
アプリケーションの機能
基本的な機能
数字入力: 0から9までの数字ボタンを使って、計算したい数値を入力できます。
小数点入力: 小数点ボタンを使って、小数を入力できます。
四則演算: 加算、減算、乗算、除算の基本的な計算機能を提供します。
結果表示: =ボタンを押すと計算結果が表示されます。
クリア機能: Clearボタンを押すと、現在の入力と計算結果がクリアされます。
プロジェクトのセットアップ
1. Create React Appの利用
まずは、Create React Appを使ってReactプロジェクトを作成しました。
npx create-react-app dentaku
cd dentaku
2. Tailwind CSSのインストールと設定
次に、Tailwind CSSをインストールし、設定を行いました。
npm install -D tailwindcss
npx tailwindcss init
tailwind.config.js
を以下のように設定します。
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
"./public/index.html",
],
theme: {
extend: {},
},
plugins: [],
}
src/index.css
に以下を追加します。
@tailwind base;
@tailwind components;
@tailwind utilities;
3. 電卓コンポーネントの作成
src/components/MainComponent.js
に電卓コンポーネントを作成します。
"use client";
import React from "react";
function MainComponent() {
const [display, setDisplay] = React.useState("0");
const [currentValue, setCurrentValue] = React.useState("");
const [previousValue, setPreviousValue] = React.useState("");
const [operation, setOperation] = React.useState(null);
const handleNumber = (num) => {
if (display === "0" || operation) {
setDisplay(num);
setCurrentValue(num);
} else {
setDisplay((prevDisplay) => prevDisplay + num);
setCurrentValue((prevValue) => prevValue + num);
}
};
const handleOperation = (op) => {
if (currentValue) {
setPreviousValue(currentValue);
setOperation(op);
setCurrentValue("");
}
};
const handleEqual = () => {
if (previousValue && currentValue && operation) {
const prev = parseFloat(previousValue);
const curr = parseFloat(currentValue);
const operations = {
"+": (a, b) => a + b,
"-": (a, b) => a - b,
"*": (a, b) => a * b,
"/": (a, b) => a / b,
};
const result = operations[operation](prev, curr);
setDisplay(result.toString());
setCurrentValue(result.toString());
setPreviousValue("");
setOperation(null);
}
};
const handleClear = () => {
setDisplay("0");
setCurrentValue("");
setPreviousValue("");
setOperation(null);
};
const renderButton = (btn) => {
const isOperation = ["+", "-", "*", "/"].includes(btn);
const isEqual = btn === "=";
const onClick = isOperation
? () => handleOperation(btn)
: isEqual
? handleEqual
: () => handleNumber(btn);
let buttonClass =
"bg-gradient-to-r from-indigo-500 to-purple-600 hover:from-indigo-600 hover:to-purple-700 text-white font-bold py-4 px-6 rounded-full shadow-lg transition duration-300 ease-in-out transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-purple-400 text-2xl";
if (isOperation || isEqual) {
buttonClass =
"bg-gradient-to-r from-pink-500 to-red-600 hover:from-pink-600 hover:to-red-700 text-white font-bold py-4 px-6 rounded-full shadow-lg transition duration-300 ease-in-out transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-red-400 text-2xl";
}
return (
<button key={btn} className={buttonClass} onClick={onClick}>
{btn}
</button>
);
};
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-gradient-to-r from-purple-400 via-pink-500 to-red-500 font-roboto p-4">
<div className="bg-white bg-opacity-20 backdrop-filter backdrop-blur-lg p-8 rounded-2xl shadow-2xl w-full max-w-md">
<div className="bg-gray-800 p-4 mb-6 rounded-xl">
<p className="text-right text-5xl text-white overflow-x-auto whitespace-nowrap">
{display}
</p>
</div>
<div className="grid grid-cols-4 gap-4">
{[
"7",
"8",
"9",
"/",
"4",
"5",
"6",
"*",
"1",
"2",
"3",
"-",
"0",
".",
"=",
"+",
].map(renderButton)}
<button
className="col-span-4 bg-gradient-to-r from-yellow-400 to-orange-500 hover:from-yellow-500 hover:to-orange-600 text-white font-bold py-4 px-6 rounded-full shadow-lg transition duration-300 ease-in-out transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-orange-400 text-2xl"
onClick={handleClear}
>
Clear
</button>
</div>
</div>
</div>
);
}
export default MainComponent;
4. App.js
の修正
src/App.js
を以下のように修正します。
import React from 'react';
import './App.css';
import './index.css';
import MainComponent from './components/MainComponent';
function App() {
return (
<div className="App">
<MainComponent />
</div>
);
}
export default App;
GitHubへのアップロード
次に、プロジェクトをGitHubにアップロードします。
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/<your-username>/dentaku.git
git branch -M main
git push -u origin main
Vercelへのデプロイ
Vercelにデプロイする手順は以下の通りです。
-
Vercel CLIのインストール
npm install -g vercel
-
Vercelにログイン
vercel login
-
プロジェクトのデプロイ
vercel
まとめ
以上の手順で、Reactを使ったモダンな電卓アプリケーション「Dentaku」を開発し、Vercelにデプロイすることができました。興味のある方はぜひこちらからアプリケーションをお試しください。
ご質問やフィードバックがあれば、コメント欄でお知らせください。最後まで読んでいただき、ありがとうございました!
以下は、「Dentaku」電卓アプリケーションのユーザーポリシーのドラフトです。
Dentaku ユーザーポリシー
はじめに
このユーザーポリシーは、Dentaku電卓アプリケーション(以下「本アプリ」)の利用に関するガイドラインを提供するものです。本アプリを利用することで、本ポリシーの内容に同意したものとみなされます。本アプリの提供者(以下「当社」)は、本ポリシーを随時変更することができます。変更があった場合は、最新のポリシーを本アプリまたは当社のウェブサイトで公開します。
1. 利用規約
1.1. 本アプリの利用
- 本アプリは、無料で提供される計算機能をユーザーに提供します。
- 本アプリの利用にあたり、ユーザーは本ポリシーを遵守するものとします。
1.2. 禁止事項
- 本アプリの機能を悪用すること。
- 他のユーザーまたは第三者に損害を与える行為。
- 本アプリの正常な運営を妨げる行為。
- 法令または公序良俗に反する行為。
2. プライバシー
2.1. 収集情報
- 本アプリは、個人情報を収集しません。
- ユーザーの利用状況や設定などの情報は、アプリのパフォーマンス改善のために匿名で収集される場合があります。
2.2. クッキーの使用
- 本アプリはクッキーを使用しません。
3. 免責事項
3.1. サービスの提供
- 当社は、本アプリの内容および提供するサービスが正確であるよう努めますが、その完全性、正確性、信頼性を保証するものではありません。
- 当社は、本アプリの利用に関連して生じたいかなる損害についても、一切責任を負いません。
3.2. サービスの変更
- 当社は、本アプリの内容や機能を予告なく変更、追加、または削除することがあります。
4. 知的財産権
- 本アプリに関するすべてのコンテンツ、デザイン、ロゴ、トレードマーク、その他の知的財産は、当社またはそのライセンサーに帰属します。
- ユーザーは、当社の事前の書面による承諾なしに、これらのコンテンツを複製、転用、配布、公開することはできません。
5. お問い合わせ
-
本ポリシーに関するお問い合わせは、以下の連絡先までお願いいたします。
連絡先: [お問い合わせフォームまたはメールアドレス]
6. 最終条項
- 本ポリシーは、2024年7月29日から適用されます。
- 本ポリシーの変更があった場合、変更後のポリシーは本アプリまたは当社のウェブサイトで公開されます。