React で作る柔軟な割り勘アプリ:動的な人数調整とリアルタイム計算機能付き
今回のブログ記事では、Reactを使って作成した高機能な割り勘アプリのコンポーネントを紹介します。このアプリは、複数人での利用を想定し、直感的なユーザーインターフェースを備えています。
主な特徴:
動的な人数調整:2人以上の支払い者を簡単に追加・削除できます。
スライダーによる割合設定:各参加者の支払い割合をスムーズに調整可能。
リアルタイム自動計算:全体の割合が常に100%になるよう自動調整します。
柔軟な金額計算:合計金額を入力すると、各人の支払額をリアルタイムで計算。
モダンなUI:shadcn/uiライブラリを活用し、美しく使いやすいデザインを実現。
このブログでは、コンポーネントの実装詳細や、Reactの特徴を活かした状態管理、ユーザーインタラクションの処理方法について深く掘り下げています。さらに、shadcn/uiライブラリの活用法や、コンポーネントのカスタマイズについても触れています。
React開発者はもちろん、使いやすいWebアプリケーションの設計に興味がある方にとって、参考になる内容となっています。ぜひ、あなたのプロジェクトにこのコンポーネントを取り入れ、カスタマイズしてみてください!
import React, { useState, useEffect } from 'react';
import { Slider } from '@/components/ui/slider';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
const SplitBillApp = () => {
const [people, setPeople] = useState([
{ name: '人物1', percentage: 50 },
{ name: '人物2', percentage: 50 },
]);
const [totalAmount, setTotalAmount] = useState(0);
useEffect(() => {
adjustPercentages();
}, [people]);
const adjustPercentages = () => {
const total = people.reduce((sum, person) => sum + person.percentage, 0);
if (total !== 100) {
const factor = 100 / total;
setPeople(people.map(person => ({
...person,
percentage: Math.round(person.percentage * factor)
})));
}
};
const handleSliderChange = (index, newValue) => {
const newPeople = [...people];
newPeople[index].percentage = newValue[0];
setPeople(newPeople);
};
const handleNameChange = (index, newName) => {
const newPeople = [...people];
newPeople[index].name = newName;
setPeople(newPeople);
};
const addPerson = () => {
setPeople([...people, { name: `人物${people.length + 1}`, percentage: 0 }]);
};
const removePerson = (index) => {
const newPeople = people.filter((_, i) => i !== index);
setPeople(newPeople);
};
return (
<div className="p-4 max-w-md mx-auto">
<h1 className="text-2xl font-bold mb-4">割り勘アプリ</h1>
<div className="mb-4">
<label className="block mb-2">合計金額</label>
<Input
type="number"
value={totalAmount}
onChange={(e) => setTotalAmount(Number(e.target.value))}
className="w-full"
/>
</div>
{people.map((person, index) => (
<div key={index} className="mb-4 p-4 border rounded">
<Input
value={person.name}
onChange={(e) => handleNameChange(index, e.target.value)}
className="mb-2"
/>
<Slider
value={[person.percentage]}
onValueChange={(newValue) => handleSliderChange(index, newValue)}
max={100}
step={1}
className="mb-2"
/>
<div className="flex justify-between">
<span>{person.percentage}%</span>
<span>{Math.round(totalAmount * person.percentage / 100)}円</span>
</div>
{people.length > 2 && (
<Button onClick={() => removePerson(index)} className="mt-2">削除</Button>
)}
</div>
))}
<Button onClick={addPerson} className="mt-4">人物を追加</Button>
</div>
);
};
export default SplitBillApp;