diff --git a/app/src/app/app/changelog/page.tsx b/app/src/app/app/changelog/page.tsx
index cb1bcc026..18ac69009 100644
--- a/app/src/app/app/changelog/page.tsx
+++ b/app/src/app/app/changelog/page.tsx
@@ -44,6 +44,18 @@ export default async function Page() {
return (
+
+
+
+ Du kannst jetzt SILC-Transaktionen direkt über den “Neu”-Button in der
+ TopBar erstellen.
+
+
+
+
).then((mod) => mod.CreateProfitDistributionCycleForm),
);
+const CreateSilcTransactionForm = dynamic(() =>
+ import(
+ "@/modules/silc/components/CreateSilcTransactionForm"
+ ).then((mod) => mod.CreateSilcTransactionForm),
+);
+
export const createForms = {
citizen: {
formComponent: CreateCitizenForm,
@@ -80,6 +86,11 @@ export const createForms = {
modalHeading: "Neuer Task",
modalWidth: "w-[768px]",
},
+ silcTransaction: {
+ formComponent: CreateSilcTransactionForm,
+ modalHeading: "Neue SILC-Transaktion",
+ modalWidth: "w-[480px]",
+ },
};
interface CreateContext {
diff --git a/app/src/modules/shell/components/TopBar/Create.tsx b/app/src/modules/shell/components/TopBar/Create.tsx
index 56affff5c..e31ecdb55 100644
--- a/app/src/modules/shell/components/TopBar/Create.tsx
+++ b/app/src/modules/shell/components/TopBar/Create.tsx
@@ -39,6 +39,10 @@ export const Create = ({ className }: Props) => {
const showCreateTask = Boolean(
authentication && authentication.authorize("task", "create"),
);
+ const showCreateSilcTransaction = Boolean(
+ authentication &&
+ authentication.authorize("silcTransactionOfOtherCitizen", "create"),
+ );
if (
!showCreateCitizen &&
@@ -46,7 +50,8 @@ export const Create = ({ className }: Props) => {
!showCreateOrganization &&
!showCreateRole &&
!showCreatePenaltyEntry &&
- !showCreateTask
+ !showCreateTask &&
+ !showCreateSilcTransaction
)
return null;
@@ -73,6 +78,7 @@ export const Create = ({ className }: Props) => {
showCreateRole={showCreateRole}
showCreatePenaltyEntry={showCreatePenaltyEntry}
showCreateTask={showCreateTask}
+ showCreateSilcTransaction={showCreateSilcTransaction}
/>
@@ -86,6 +92,7 @@ interface PopoverChildrenProps {
readonly showCreateRole: boolean;
readonly showCreatePenaltyEntry: boolean;
readonly showCreateTask: boolean;
+ readonly showCreateSilcTransaction: boolean;
}
const PopoverChildren = ({
@@ -95,6 +102,7 @@ const PopoverChildren = ({
showCreateRole,
showCreatePenaltyEntry,
showCreateTask,
+ showCreateSilcTransaction,
}: PopoverChildrenProps) => {
const { closePopover } = usePopover();
const { openCreateModal } = useCreateContext();
@@ -157,6 +165,12 @@ const PopoverChildren = ({
});
if (showCreateTask)
items.push({ label: "Task", type: "button", modalId: "task" });
+ if (showCreateSilcTransaction)
+ items.push({
+ label: "SILC-Transaktion",
+ type: "button",
+ modalId: "silcTransaction",
+ });
items = items.toSorted((a, b) => a.label.localeCompare(b.label));
diff --git a/app/src/modules/silc/components/CreateSilcTransactionForm.tsx b/app/src/modules/silc/components/CreateSilcTransactionForm.tsx
new file mode 100644
index 000000000..4773d343d
--- /dev/null
+++ b/app/src/modules/silc/components/CreateSilcTransactionForm.tsx
@@ -0,0 +1,106 @@
+"use client";
+
+import { CitizenInput } from "@/modules/citizen/components/CitizenInput";
+import Button from "@/modules/common/components/Button";
+import { Button2 } from "@/modules/common/components/Button2";
+import { NumberInput } from "@/modules/common/components/form/NumberInput";
+import { Textarea } from "@/modules/common/components/form/Textarea";
+import Note from "@/modules/common/components/Note";
+import { unstable_rethrow } from "next/navigation";
+import { useActionState } from "react";
+import toast from "react-hot-toast";
+import { FaSave, FaSpinner } from "react-icons/fa";
+import { createSilcTransaction } from "../actions/createSilcTransaction";
+
+interface Props {
+ readonly onSuccess?: () => void;
+}
+
+export const CreateSilcTransactionForm = ({ onSuccess }: Props) => {
+ const [state, formAction, isPending] = useActionState(
+ async (previousState: unknown, formData: FormData) => {
+ try {
+ const response = await createSilcTransaction(formData);
+
+ if (response.error) {
+ toast.error(response.error);
+ console.error(response);
+ return response;
+ }
+
+ toast.success(response.success!);
+ if (formData.has("createAnother")) {
+ return response;
+ }
+
+ onSuccess?.();
+ return response;
+ } catch (error) {
+ unstable_rethrow(error);
+ toast.error(
+ "Ein unbekannter Fehler ist aufgetreten. Bitte versuche es später erneut.",
+ );
+ console.error(error);
+ return {
+ error:
+ "Ein unbekannter Fehler ist aufgetreten. Bitte versuche es später erneut.",
+ requestPayload: formData,
+ };
+ }
+ },
+ null,
+ );
+
+ return (
+
+ );
+};