mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 11:01:45 +00:00
fix(transactions): avoid crypto.randomUUID on initial load
This commit is contained in:
@@ -7,6 +7,12 @@ e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2.0.3] - 2026-03-26
|
||||
|
||||
### Corrigido
|
||||
|
||||
- Lançamentos: `/transactions` deixa de depender de `crypto.randomUUID()` no carregamento inicial, corrigindo a falha em ambientes self-hosted sem HTTPS ao abrir a página
|
||||
|
||||
## [2.0.2] - 2026-03-25
|
||||
|
||||
### Adicionado
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openmonetis",
|
||||
"version": "2.0.2",
|
||||
"version": "2.0.3",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack",
|
||||
|
||||
@@ -38,6 +38,7 @@ import {
|
||||
import { Separator } from "@/shared/components/ui/separator";
|
||||
import { Spinner } from "@/shared/components/ui/spinner";
|
||||
import { getTodayDateString } from "@/shared/utils/date";
|
||||
import { createClientSafeId } from "@/shared/utils/id";
|
||||
import {
|
||||
dateToPeriod,
|
||||
displayPeriod,
|
||||
@@ -120,6 +121,19 @@ interface TransactionRow {
|
||||
payerId: string | undefined;
|
||||
}
|
||||
|
||||
function createEmptyTransactionRow(
|
||||
defaultPayerId?: string | null,
|
||||
): TransactionRow {
|
||||
return {
|
||||
id: createClientSafeId(),
|
||||
purchaseDate: getTodayDateString(),
|
||||
name: "",
|
||||
amount: "",
|
||||
categoryId: undefined,
|
||||
payerId: defaultPayerId ?? undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function MassAddDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
@@ -153,15 +167,8 @@ export function MassAddDialog({
|
||||
const isCartaoSelected = paymentMethod === "Cartão de crédito";
|
||||
|
||||
// Transaction rows
|
||||
const [transactions, setTransactions] = useState<TransactionRow[]>([
|
||||
{
|
||||
id: crypto.randomUUID(),
|
||||
purchaseDate: getTodayDateString(),
|
||||
name: "",
|
||||
amount: "",
|
||||
categoryId: undefined,
|
||||
payerId: defaultPayerId ?? undefined,
|
||||
},
|
||||
const [transactions, setTransactions] = useState<TransactionRow[]>(() => [
|
||||
createEmptyTransactionRow(defaultPayerId),
|
||||
]);
|
||||
|
||||
// Categorias agrupadas e filtradas por tipo de transação
|
||||
@@ -175,14 +182,7 @@ export function MassAddDialog({
|
||||
const addTransaction = () => {
|
||||
setTransactions([
|
||||
...transactions,
|
||||
{
|
||||
id: crypto.randomUUID(),
|
||||
purchaseDate: getTodayDateString(),
|
||||
name: "",
|
||||
amount: "",
|
||||
categoryId: undefined,
|
||||
payerId: defaultPayerId ?? undefined,
|
||||
},
|
||||
createEmptyTransactionRow(defaultPayerId),
|
||||
]);
|
||||
};
|
||||
|
||||
@@ -256,16 +256,7 @@ export function MassAddDialog({
|
||||
setPeriod(selectedPeriod);
|
||||
setContaId(undefined);
|
||||
setCartaoId(defaultCardId ?? undefined);
|
||||
setTransactions([
|
||||
{
|
||||
id: crypto.randomUUID(),
|
||||
purchaseDate: getTodayDateString(),
|
||||
name: "",
|
||||
amount: "",
|
||||
categoryId: undefined,
|
||||
payerId: defaultPayerId ?? undefined,
|
||||
},
|
||||
]);
|
||||
setTransactions([createEmptyTransactionRow(defaultPayerId)]);
|
||||
} catch (_error) {
|
||||
// Error is handled by the onSubmit function
|
||||
} finally {
|
||||
|
||||
@@ -575,7 +575,7 @@ export function TransactionsPage({
|
||||
onConfirm={handleBulkEdit}
|
||||
/>
|
||||
|
||||
{allowCreate ? (
|
||||
{allowCreate && massAddOpen ? (
|
||||
<MassAddDialog
|
||||
open={massAddOpen}
|
||||
onOpenChange={setMassAddOpen}
|
||||
|
||||
37
src/shared/utils/id.ts
Normal file
37
src/shared/utils/id.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
const FALLBACK_HEX_RADIX = 16;
|
||||
|
||||
function randomHex(byteCount: number) {
|
||||
const cryptoApi = globalThis.crypto;
|
||||
|
||||
if (cryptoApi?.getRandomValues) {
|
||||
return Array.from(cryptoApi.getRandomValues(new Uint8Array(byteCount)))
|
||||
.map((byte) => byte.toString(FALLBACK_HEX_RADIX).padStart(2, "0"))
|
||||
.join("");
|
||||
}
|
||||
|
||||
let hex = "";
|
||||
|
||||
for (let index = 0; index < byteCount; index += 1) {
|
||||
hex += Math.floor(Math.random() * 256)
|
||||
.toString(FALLBACK_HEX_RADIX)
|
||||
.padStart(2, "0");
|
||||
}
|
||||
|
||||
return hex;
|
||||
}
|
||||
|
||||
export function createClientSafeId() {
|
||||
const cryptoApi = globalThis.crypto;
|
||||
|
||||
if (cryptoApi?.randomUUID) {
|
||||
return cryptoApi.randomUUID();
|
||||
}
|
||||
|
||||
return [
|
||||
randomHex(4),
|
||||
randomHex(2),
|
||||
randomHex(2),
|
||||
randomHex(2),
|
||||
randomHex(6),
|
||||
].join("-");
|
||||
}
|
||||
Reference in New Issue
Block a user