Compare commits
10 Commits
bugfix/iro
...
061bc18df7
| Author | SHA1 | Date | |
|---|---|---|---|
| 061bc18df7 | |||
|
|
ecf0240ba9 | ||
| 90127d1e0d | |||
|
|
8daea3ea47 | ||
| 318e2144f0 | |||
| fe1de2bbf9 | |||
| 7b7554c84b | |||
| c884bf812c | |||
| 91f9ed5474 | |||
| adad656df2 |
16
.github/workflows/docker-publish.yml
vendored
16
.github/workflows/docker-publish.yml
vendored
@@ -13,22 +13,22 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Login to Gitea Registry
|
- name: Login to Gitea Registry
|
||||||
run: echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login 192.168.31.100:3847 -u ${{ secrets.REGISTRY_USER }} --password-stdin
|
run: echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login gitea.arreliny.dedyn.io -u ${{ secrets.REGISTRY_USER }} --password-stdin
|
||||||
|
|
||||||
- name: Build and push backend image
|
- name: Build and push backend image
|
||||||
run: |
|
run: |
|
||||||
docker build -t 192.168.31.100:3847/arrelin/family_budget-backend:latest -t 192.168.31.100:3847/arrelin/family_budget-backend:${{ gitea.sha }} ./backend
|
docker build -t gitea.arreliny.dedyn.io/arrelin/family_budget-backend:latest -t gitea.arreliny.dedyn.io/arrelin/family_budget-backend:${{ gitea.sha }} ./backend
|
||||||
docker push 192.168.31.100:3847/arrelin/family_budget-backend:latest
|
docker push gitea.arreliny.dedyn.io/arrelin/family_budget-backend:latest
|
||||||
docker push 192.168.31.100:3847/arrelin/family_budget-backend:${{ gitea.sha }}
|
docker push gitea.arreliny.dedyn.io/arrelin/family_budget-backend:${{ gitea.sha }}
|
||||||
|
|
||||||
- name: Build and push frontend image
|
- name: Build and push frontend image
|
||||||
run: |
|
run: |
|
||||||
docker build -t 192.168.31.100:3847/arrelin/family_budget-frontend:latest -t 192.168.31.100:3847/arrelin/family_budget-frontend:${{ gitea.sha }} ./frontend
|
docker build -t gitea.arreliny.dedyn.io/arrelin/family_budget-frontend:latest -t gitea.arreliny.dedyn.io/arrelin/family_budget-frontend:${{ gitea.sha }} ./frontend
|
||||||
docker push 192.168.31.100:3847/arrelin/family_budget-frontend:latest
|
docker push gitea.arreliny.dedyn.io/arrelin/family_budget-frontend:latest
|
||||||
docker push 192.168.31.100:3847/arrelin/family_budget-frontend:${{ gitea.sha }}
|
docker push gitea.arreliny.dedyn.io/arrelin/family_budget-frontend:${{ gitea.sha }}
|
||||||
|
|
||||||
- name: Logout
|
- name: Logout
|
||||||
run: docker logout 192.168.31.100:3847
|
run: docker logout gitea.arreliny.dedyn.io
|
||||||
|
|
||||||
- name: Trigger Coolify redeploy
|
- name: Trigger Coolify redeploy
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -63,6 +63,8 @@
|
|||||||
"addCategory": "Add category",
|
"addCategory": "Add category",
|
||||||
"deleteConfirm": "Delete category?",
|
"deleteConfirm": "Delete category?",
|
||||||
"resetConfirm": "Delete all expenses for this category?",
|
"resetConfirm": "Delete all expenses for this category?",
|
||||||
|
"editTitle": "Category settings",
|
||||||
|
"editError": "Error updating category",
|
||||||
"createError": "Error creating category",
|
"createError": "Error creating category",
|
||||||
"deleteError": "Error deleting category",
|
"deleteError": "Error deleting category",
|
||||||
"resetError": "Error resetting expenses"
|
"resetError": "Error resetting expenses"
|
||||||
|
|||||||
@@ -63,6 +63,8 @@
|
|||||||
"addCategory": "Добавить категорию",
|
"addCategory": "Добавить категорию",
|
||||||
"deleteConfirm": "Удалить категорию?",
|
"deleteConfirm": "Удалить категорию?",
|
||||||
"resetConfirm": "Удалить все траты по этой категории?",
|
"resetConfirm": "Удалить все траты по этой категории?",
|
||||||
|
"editTitle": "Настройки категории",
|
||||||
|
"editError": "Ошибка обновления категории",
|
||||||
"createError": "Ошибка создания категории",
|
"createError": "Ошибка создания категории",
|
||||||
"deleteError": "Ошибка удаления категории",
|
"deleteError": "Ошибка удаления категории",
|
||||||
"resetError": "Ошибка сброса трат"
|
"resetError": "Ошибка сброса трат"
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import {
|
|||||||
Copy,
|
Copy,
|
||||||
Check,
|
Check,
|
||||||
User,
|
User,
|
||||||
|
Settings,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import ShoppingListModal from '../components/ShoppingListModal';
|
import ShoppingListModal from '../components/ShoppingListModal';
|
||||||
|
|
||||||
@@ -45,6 +46,10 @@ export default function FamilyView() {
|
|||||||
const [expenseAmount, setExpenseAmount] = useState('');
|
const [expenseAmount, setExpenseAmount] = useState('');
|
||||||
const [expenseDescription, setExpenseDescription] = useState('');
|
const [expenseDescription, setExpenseDescription] = useState('');
|
||||||
|
|
||||||
|
const [showEditCategory, setShowEditCategory] = useState<number | null>(null);
|
||||||
|
const [editCategoryName, setEditCategoryName] = useState('');
|
||||||
|
const [editCategoryLimit, setEditCategoryLimit] = useState('');
|
||||||
|
|
||||||
const [showHistory, setShowHistory] = useState<number | null>(null);
|
const [showHistory, setShowHistory] = useState<number | null>(null);
|
||||||
const [showArchive, setShowArchive] = useState<number | null>(null);
|
const [showArchive, setShowArchive] = useState<number | null>(null);
|
||||||
const [historyData, setHistoryData] = useState<ExpenseHistoryResponse | null>(null);
|
const [historyData, setHistoryData] = useState<ExpenseHistoryResponse | null>(null);
|
||||||
@@ -181,6 +186,29 @@ export default function FamilyView() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleOpenEditCategory = (category: Category) => {
|
||||||
|
setEditCategoryName(category.name);
|
||||||
|
setEditCategoryLimit(parseFloat(category.limit_amount.toString()).toString());
|
||||||
|
setShowEditCategory(category.id);
|
||||||
|
setShowAddExpense(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpdateCategory = async (categoryId: number) => {
|
||||||
|
if (!familyId || !editCategoryName || !editCategoryLimit) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await categoryApi.update(parseInt(familyId), categoryId, {
|
||||||
|
name: editCategoryName,
|
||||||
|
limit_amount: parseFloat(editCategoryLimit),
|
||||||
|
});
|
||||||
|
setShowEditCategory(null);
|
||||||
|
loadCategories();
|
||||||
|
} catch (err: any) {
|
||||||
|
const errorMsg = err.response?.data?.message || err.message || t('category.editError');
|
||||||
|
alert(`${t('category.editError')}: ${errorMsg}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleShowHistory = async (categoryId: number) => {
|
const handleShowHistory = async (categoryId: number) => {
|
||||||
if (!familyId) return;
|
if (!familyId) return;
|
||||||
|
|
||||||
@@ -396,7 +424,15 @@ export default function FamilyView() {
|
|||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{showAddExpense !== category.id && (
|
{showAddExpense !== category.id && showEditCategory !== category.id && (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
onClick={() => handleOpenEditCategory(category)}
|
||||||
|
className="p-2 bg-gray-200 hover:bg-gray-300 text-gray-600 rounded-xl transition-all duration-300"
|
||||||
|
title={t('category.editTitle')}
|
||||||
|
>
|
||||||
|
<Settings className="w-4 h-4" />
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowAddExpense(category.id)}
|
onClick={() => setShowAddExpense(category.id)}
|
||||||
className="flex items-center gap-2 px-4 py-2 btn-danger text-white rounded-xl hover:shadow-lg transition-all duration-300 font-semibold whitespace-nowrap text-sm"
|
className="flex items-center gap-2 px-4 py-2 btn-danger text-white rounded-xl hover:shadow-lg transition-all duration-300 font-semibold whitespace-nowrap text-sm"
|
||||||
@@ -405,6 +441,7 @@ export default function FamilyView() {
|
|||||||
<span className="hidden sm:inline">{t('category.addExpense')}</span>
|
<span className="hidden sm:inline">{t('category.addExpense')}</span>
|
||||||
<span className="sm:hidden">{t('category.expense')}</span>
|
<span className="sm:hidden">{t('category.expense')}</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -511,6 +548,53 @@ export default function FamilyView() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{showEditCategory === category.id && (
|
||||||
|
<div className="glass-effect p-6 rounded-2xl border-2 border-gray-200 mt-4">
|
||||||
|
<h3 className="font-semibold text-gray-800 mb-4 text-center">
|
||||||
|
{t('category.editTitle')}
|
||||||
|
</h3>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||||
|
{t('category.categoryName')}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={editCategoryName}
|
||||||
|
onChange={(e) => setEditCategoryName(e.target.value)}
|
||||||
|
className="w-full px-4 py-3 border-2 border-gray-300 rounded-2xl focus:border-purple-500 focus:ring-2 focus:ring-purple-200 transition-all font-medium"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||||
|
{t('category.categoryLimit')}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={editCategoryLimit}
|
||||||
|
onChange={(e) => setEditCategoryLimit(e.target.value)}
|
||||||
|
className="w-full px-4 py-3 border-2 border-gray-300 rounded-2xl focus:border-purple-500 focus:ring-2 focus:ring-purple-200 transition-all text-center font-semibold text-lg"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-3">
|
||||||
|
<button
|
||||||
|
onClick={() => handleUpdateCategory(category.id)}
|
||||||
|
className="flex-1 flex items-center justify-center gap-2 px-5 py-3 btn-success text-white rounded-2xl hover:shadow-xl transition-all font-semibold"
|
||||||
|
>
|
||||||
|
<Check className="w-5 h-5" />
|
||||||
|
{t('common.save')}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setShowEditCategory(null)}
|
||||||
|
className="px-5 py-3 bg-gray-200 hover:bg-gray-300 text-gray-700 rounded-2xl transition-all font-medium"
|
||||||
|
>
|
||||||
|
<X className="w-5 h-5" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{showHistory === category.id && historyData && (
|
{showHistory === category.id && historyData && (
|
||||||
<div className="mt-4 glass-effect p-4 rounded-2xl border-2 border-blue-200">
|
<div className="mt-4 glass-effect p-4 rounded-2xl border-2 border-blue-200">
|
||||||
<div className="flex items-center justify-between mb-4">
|
<div className="flex items-center justify-between mb-4">
|
||||||
|
|||||||
Reference in New Issue
Block a user