# Anlegen und Bearbeiten

Anlegen und Bearbeiten sind zentrale Interaktionen im mStudio. Sie dienen dazu,
neue Elemente zur Benutzeroberfläche hinzuzufügen oder bestehende Inhalte
anzupassen. Damit jeder Prozess von überall aufgerufen werden kann, werden sie
in einem Modal platziert.

---

# Best Practices

- Anlegen und Bearbeiten finden immer in einem
  [Modal](/04-components/overlays/modal) oder OffCanvas statt – so können User
  Prozesse überall starten, ohne den Workflow zu unterbrechen.
- Halte den Anlegeprozess schlank und versuche, auf Defaults zu setzen. Details
  können vom User später auf der Detailseite angepasst werden.
- Gliedere komplizierte Prozesse in
  [Sections](/04-components/structure/section/overview), um die Übersicht zu
  erhalten. Jede Section kann über die
  [SectionAction](/04-components/structure/section/overview#sectionaction)
  Teilprozesse ansteuern.
- Nutze die
  [IllustratedMessage](/04-components/content/illustrated-message/overview),
  wenn noch keine Inhalte existieren.

---

# Grundlagen

## Modal vs. OffCanvas

Anlege- und Bearbeitungsprozesse werden im mStudio grundsätzlich in einem
[Modal](/04-components/overlays/modal/overview) ausgeführt. So kann der User
jederzeit den passenden Prozess starten, ohne seinen Workflow zu unterbrechen.
Das Modal gibt es in der klassischen Modal Darstellung und als
[Off-Canvas](/04-components/overlays/modal/overview#variants)-Variant:

- Modal: Für kurze, fokussierte Prozesse – etwa einfache Formulare oder schnelle
  Einstellungen, die der User direkt erledigt.
- OffCanvas: Für komplexere Abläufe mit mehreren Schritten oder umfangreichen
  Eingaben. Eine flexible Breite sowie die Möglichkeit, zu scrollen, sorgen für
  Übersichtlichkeit und bessere Orientierung.

## Abhängige Information

Viele Anlege- bzw. Bearbeitungsprozesse benötigen Informationen aus anderen
Prozessen. Diese Informationen können entweder fehlen oder bereits vorhanden
sein:

**Fehlende Informationen**: Manche Prozesse lassen sich erst abschließen, wenn
bestimmte Voraussetzungen erfüllt sind. So können z. B. Buchungsprozesse nur
abgeschlossen werden, wenn bereits ein Vertragspartner existiert. Zum Beispiel:

- Eine Extension kann nur installiert werden, wenn in der gewählten Organisation
  bereits ein Vertragspartner existiert. Fehlt dieser, erscheint ein
  [Alert](/04-components/status/alert/overview) mit einer Erklärung und der
  Möglichkeit, direkt in den „Vertragspartner anlegen“-Prozess zu starten – ohne
  den aktuellen Kontext zu verlassen.

```tsx
import {
  Action,
  ActionGroup,
  Alert,
  Button,
  CheckboxButton,
  ColumnLayout,
  Content,
  Heading,
  IconCheck,
  IconClose,
  Label,
  Link,
  Modal,
  ModalTrigger,
  Option,
  Section,
  Select,
  Table,
  TableBody,
  TableCell,
  TableColumn,
  TableHeader,
  TableRow,
  Text,
} from "@mittwald/flow-react-components";

<ModalTrigger>
  <Button color="accent">Beispiel öffnen</Button>
  <Modal offCanvas>
    <Heading>Passwortschutz installieren</Heading>
    <Content>
      <Section>
        <Text>
          Wähle das Projekt aus, in das die Extension
          installiert werden soll. Die Extension wird dort
          integriert und bereitgestellt.
        </Text>
        <ColumnLayout m={[2, 1]}>
          <Select isRequired defaultSelectedKey="1">
            <Label>Organisation</Label>
            <Option value="1">Meine Organisation</Option>
            <Option value="2">
              Noch eine Organisation
            </Option>
          </Select>
        </ColumnLayout>
        <Alert status="warning">
          <Heading>Kein Vertragspartner hinterlegt</Heading>
          <Content>
            <Text>
              Die gewählte Organisation hat derzeit keinen
              Vertragspartner hinterlegt. Um mit der
              Installation fortzufahren, lege bitte einen
              Vertragspartner an.
            </Text>
            <Button color="accent">
              Vertragspartner anlegen
            </Button>
          </Content>
        </Alert>
        <Heading>Berechtigungen </Heading>
        <Text>
          Extensions brauchen Zugriffsberechtigungen, um
          bestimmte Bereiche im mStudio verwalten und/oder
          bearbeiten zu können. Bitte bestätige, dass diese
          Extension auf die folgenden Bereiche zugreifen
          darf:
        </Text>
        <Table>
          <TableHeader>
            <TableColumn>Bereich</TableColumn>
            <TableColumn>Lesen</TableColumn>
            <TableColumn>Schreiben</TableColumn>
            <TableColumn>Löschen</TableColumn>
          </TableHeader>
          <TableBody>
            <TableRow>
              <TableCell>Projekt</TableCell>
              <TableCell>
                <IconCheck status="success" />
              </TableCell>
              <TableCell>
                <IconClose status="danger" />
              </TableCell>
              <TableCell>
                <IconClose status="danger" />
              </TableCell>
            </TableRow>
            <TableRow>
              <TableCell>App</TableCell>
              <TableCell>
                <IconCheck status="success" />
              </TableCell>
              <TableCell>
                <IconClose status="danger" />
              </TableCell>
              <TableCell>
                <IconClose status="danger" />
              </TableCell>
            </TableRow>
            <TableRow>
              <TableCell>SSH-Benutzer</TableCell>
              <TableCell>
                <IconCheck status="success" />
              </TableCell>
              <TableCell>
                <IconCheck status="success" />
              </TableCell>
              <TableCell>
                <IconCheck status="success" />
              </TableCell>
            </TableRow>
          </TableBody>
        </Table>
        <CheckboxButton>
          <Text>
            Ich habe die{" "}
            <Link target="_blank">
              Vereinbarung zur Auftragsdatenverarbeitung
            </Link>{" "}
            gelesen und akzeptiere diese.
          </Text>
        </CheckboxButton>
      </Section>
    </Content>
    <ActionGroup>
      <Button isDisabled>Zur Bestellübersicht</Button>
      <Action closeModal>
        <Button color="secondary" variant="soft">
          Abbrechen
        </Button>
      </Action>
    </ActionGroup>
  </Modal>
</ModalTrigger>
```

**Vorhandene Informationen**: In anderen Prozessen können bestehende Inhalte
direkt genutzt werden – mit der Option, bei Bedarf neue anzulegen.

**Beispiel**: Bei der Installation einer App wählt der User eine vorhandene
Domain aus. Falls nötig, kann er an dieser Stelle auch eine neue Subdomain
anlegen.

```tsx
import {
  Action,
  ActionGroup,
  Button,
  ColumnLayout,
  Content,
  FieldDescription,
  Header,
  Heading,
  InlineCode,
  Label,
  Modal,
  ModalTrigger,
  Option,
  PasswordCreationField,
  Section,
  Select,
  TextField,
} from "@mittwald/flow-react-components";

<ModalTrigger>
  <Button color="accent">Beispiel öffnen</Button>
  <Modal offCanvas>
    <Heading>WordPress anlegen</Heading>
    <Content>
      <Section>
        <ColumnLayout m={[2, 1]}>
          <TextField isRequired>
            <Label>Name</Label>
          </TextField>
          <Select isRequired defaultSelectedKey="6.5.3">
            <Label>Version</Label>
            <Option value="6.5.3">6.5.3 (Neueste)</Option>
            <Option value="6.5.2">6.5.2</Option>
            <Option value="6.5.1">6.5.1</Option>
          </Select>
        </ColumnLayout>
        <TextField isRequired>
          <Label>Installationsverzeichnis</Label>
          <FieldDescription>
            Deine App wird unter{" "}
            <InlineCode>{`/html/<installationsverzeichnis>`}</InlineCode>{" "}
            installiert
          </FieldDescription>
        </TextField>
        <Header>
          <Heading>Hauptdomain zuweisen</Heading>
          <Button color="accent">Subdomain anlegen</Button>
        </Header>
        <Select isRequired placeholder="Domain wählen">
          <Label>Domain</Label>
          <Option>meine-domain.de</Option>
          <Option>noch-eine-domain.de</Option>
        </Select>
        <Heading>Admin anlegen</Heading>
        <TextField isRequired defaultValue="WordPress">
          <Label>E-Mail-Adresse</Label>
        </TextField>
        <TextField
          isRequired
          defaultValue="meinname@meinedomain.de"
        >
          <Label>Benutzername</Label>
        </TextField>
        <PasswordCreationField isRequired>
          <Label>Passwort</Label>
        </PasswordCreationField>
      </Section>
    </Content>
    <ActionGroup>
      <Button color="accent">Anlegen</Button>
      <Button
        slot="secondary"
        color="secondary"
        variant="soft"
      >
        Zurück
      </Button>
      <Action closeModal>
        <Button color="secondary" variant="soft">
          Abbrechen
        </Button>
      </Action>
    </ActionGroup>
  </Modal>
</ModalTrigger>
```

## Komplexe Prozesse

Umfangreiche Anlege- oder Bearbeitungsprozesse werden in einzelne
[Sections](/04-components/structure/section/overview) gegliedert. In jeder
Section kann die
[SectionAction](/04-components/structure/section/overview#sectionaction) genutzt
werden. Damit kann der User Teilprozesse direkt innerhalb des Gesamtprozesses
erledigen.

**Beispiel**: Das Anlegen eines Containers ist ein umfangreicher Prozess.
Sections im OffCanvas sorgen dafür, dass der Ablauf trotzdem strukturiert und
übersichtlich bleibt.

```tsx
import {
  Action,
  ActionGroup,
  Align,
  Button,
  ColumnLayout,
  Content,
  CopyButton,
  Header,
  Heading,
  IconAI,
  IconClose,
  InlineCode,
  Label,
  LabeledValue,
  ListItemView,
  Modal,
  ModalTrigger,
  Section,
  Table,
  TableBody,
  TableCell,
  TableColumn,
  TableHeader,
  TableRow,
  Text,
  typedList,
} from "@mittwald/flow-react-components";

export default () => {
  const VolumeList = typedList<{
    id: string;
    name: string;
    path: string;
    ai?: string;
  }>();

  return (
    <ModalTrigger>
      <Button color="accent">Beispiel öffnen</Button>
      <Modal offCanvas>
        <Heading>Container anlegen</Heading>
        <Content>
          <Section>
            <Header>
              <Heading>Entrypoint</Heading>
              <Button variant="soft" color="secondary">
                Bearbeiten
              </Button>
            </Header>
            <Text>
              Der Entrypoint definiert den primären Prozess,
              der in deinem Container gestartet werden soll.
              Der Command gibt an, mit welchen Parametern
              der Entrypoint gestartet wird.
            </Text>
            <ColumnLayout>
              <LabeledValue>
                <Label>Entrypoint</Label>
                <InlineCode>
                  docker-entrypoint.sh
                </InlineCode>
                <CopyButton value="docker-entrypoint.sh" />
              </LabeledValue>
              <LabeledValue>
                <Label>Command</Label>
                <InlineCode>mongod</InlineCode>
                <CopyButton value="mongod" />
              </LabeledValue>
            </ColumnLayout>

            <Header>
              <Heading>Volumes</Heading>
              <Button>Hinzufügen</Button>
            </Header>
            <Text>
              Volumes stellen Speicherplatz für deinem
              Container bereit. Alternativ kannst du einen
              Pfad innerhalb deines Projekts auswählen, um
              auf die Dateien zuzugreifen.
            </Text>
            <VolumeList.List
              hidePagination
              getItemId={(volume) => volume.id}
            >
              <VolumeList.StaticData
                data={[
                  {
                    id: "1",
                    name: "mongo-data-configdb-Rrku",
                    path: "/data/configdb",
                  },
                  {
                    id: "2",
                    name: "mongo-data-db-CnnD",
                    path: "/data/db",
                    ai: "Ein Verzeichnis für die Speicherung von MongoDB-Daten.",
                  },
                ]}
              />
              <VolumeList.Item>
                {(volume) => (
                  <ListItemView>
                    <Heading>{volume.name}</Heading>
                    <Text>{volume.path}</Text>
                    <Button
                      variant="plain"
                      color="secondary"
                    >
                      <IconClose />
                    </Button>
                    {volume.ai && (
                      <Content slot="bottom">
                        <Align>
                          <IconAI />
                          <Text>
                            <small>{volume.ai}</small>
                          </Text>
                        </Align>
                      </Content>
                    )}
                  </ListItemView>
                )}
              </VolumeList.Item>
            </VolumeList.List>

            <Header>
              <Heading>Umgebungsvariablen</Heading>
              <Button color="secondary" variant="soft">
                Bearbeiten
              </Button>
            </Header>
            <Table>
              <TableHeader>
                <TableColumn>Key</TableColumn>
                <TableColumn>Value</TableColumn>
                <TableColumn>KI-Unterstützung</TableColumn>
              </TableHeader>
              <TableBody>
                <TableRow>
                  <TableCell
                    colSpan={3}
                    horizontalAlign="center"
                  >
                    Keine Variablen hinterlegt
                  </TableCell>
                </TableRow>
              </TableBody>
            </Table>
          </Section>
        </Content>
        <ActionGroup>
          <Button color="accent">Anlegen</Button>
          <Button
            slot="secondary"
            color="secondary"
            variant="soft"
          >
            Zurück
          </Button>
          <Action closeModal>
            <Button color="secondary" variant="soft">
              Abbrechen
            </Button>
          </Action>
        </ActionGroup>
      </Modal>
    </ModalTrigger>
  );
}
```

---

# Anlegen

Anlegeprozesse sollen den Einstieg so einfach und schnell wie möglich machen.
Darum sollte der User nicht jedes Detail sofort konfigurieren müssen.
Stattdessen empfiehlt es sich, wo sinnvoll, Default-Werte zu setzen. Diese
lassen sich nach dem Anlegen jederzeit auf der Detailseite anpassen.

## Leerer Zustand vs. vorhandener Inhalt

Ein leerer Zustand bedeutet: Es wurden noch keine Elemente angelegt. In diesem
Fall ersetzt die
[IllustratedMessage](/04-components/content/illustrated-message/overview) die
[List](/04-components/structure/list/overview) und bietet einen großen CTA zum
Anlegen des ersten Elements.

**Beispiel**: Sind noch keine Projekte angelegt, wird in der Projektübersicht
eine [IllustratedMessage](/04-components/content/illustrated-message/overview)
angezeigt.

```tsx
import {
  ActionGroup,
  Button,
  Heading,
  IconProject,
  IllustratedMessage,
  Text,
  LayoutCard,
} from "@mittwald/flow-react-components";

<LayoutCard>
  <IllustratedMessage>
    <IconProject />
    <Heading>Erstes Projekt anlegen</Heading>
    <Text>
      Du hast noch keine Projekte angelegt! Lege ein Projekt
      an und schon kannst du mit dem Entwickeln loslegen.
    </Text>

    <ActionGroup>
      <Button color="secondary" variant="soft">
        Tarif bestellen
      </Button>
      <Button color="accent">Anlegen</Button>
    </ActionGroup>
  </IllustratedMessage>
</LayoutCard>
```

Sobald Inhalte vorhanden sind, rückt die Navigation über die
[List](/04-components/structure/list/overview) in den Vordergrund. Die
[ActionGroup](/04-components/actions/action-group/overview) im Header der List
übernimmt dann die Funktion, den Anlegeprozess für neue Elemente zu starten.

**Beispiel**: Sind Projekte angelegt, werden diese in einer List dargestellt.

```tsx
import {
  ActionGroup,
  Avatar,
  Button,
  ContextMenu,
  Heading,
  IconInfo,
  IconProject,
  ListItemView,
  MenuItem,
  Text,
  typedList,
  LayoutCard,
} from "@mittwald/flow-react-components";

export default () => {
  const ProjectList = typedList<{
    id: string;
    name: string;
    type: string;
  }>();

  return (
    <LayoutCard>
      <ProjectList.List
        aria-label="Projekte"
        getItemId={(project) => project.id}
      >
        <ProjectList.StaticData
          data={[
            {
              id: "1",
              name: "Café-Gebäck-Haus",
              type: "vServer: Mein Server",
            },
            {
              id: "2",
              name: "Steelwork",
              type: "Webhosting",
            },
            {
              id: "3",
              name: "UtopiaVRSchule",
              type: "Dedicated Server: Mein Server",
            },
            {
              id: "4",
              name: "IT-Profis-Website",
              type: "vServer: Mein Server",
            },
          ]}
        />
        <ProjectList.Search />
        <ProjectList.Item
          textValue={(project) => project.name}
          showTiles
        >
          {(project) => (
            <ListItemView>
              <Avatar>
                <IconProject />
              </Avatar>
              <Heading>{project.name}</Heading>
              <Text>{project.type}</Text>
              <ContextMenu>
                <MenuItem>
                  <IconInfo />
                  <Text>Details anzeigen</Text>
                </MenuItem>
              </ContextMenu>
            </ListItemView>
          )}
        </ProjectList.Item>
        <ActionGroup>
          <Button color="secondary" variant="soft">
            Tarif bestellen
          </Button>
          <Button color="accent">Anlegen</Button>
        </ActionGroup>
      </ProjectList.List>
    </LayoutCard>
  );
}
```

## Gleiche und unterschiedliche Elemente

Wenn die List ausschließlich aus Elementen des gleichen Typs besteht, z. B.
Cronjobs oder Mitgliedern, ist der Ablauf besonders einfach: Ein Klick auf den
Anlege-[Button](/04-components/actions/button/overview) öffnet sofort das
[Modal](/04-components/overlays/modal/overview) zum Anlegen. Wenn verschiedene
Elementtypen in einer Liste stehen (z. B. Domain, Subdomain, vHost), öffnet der
Anlege-[Button](/04-components/actions/button/overview) zunächst ein
[ContextMenu](/04-components/actions/context-menu/overview), in dem der User den
gewünschten Typ auswählt. Danach startet der passende Prozess.

**Beispiel**: Beim Anlegen einer Domain wird über ein ContextMenu zunächst
abgefragt, um welche Art von Domain es sich handelt.

```tsx
import {
  ActionGroup,
  Avatar,
  Button,
  Content,
  ContextMenu,
  ContextMenuTrigger,
  Heading,
  IconChevronDown,
  IconDomain,
  IconHome,
  IconInfo,
  IconMove,
  IconSubdomain,
  IconVhost,
  LayoutCard,
  ListItemView,
  MenuItem,
  Text,
  typedList,
} from "@mittwald/flow-react-components";

export default () => {
  const DomainList = typedList<{
    id: string;
    domain: string;
    type: string;
    target?: string;
  }>();

  return (
    <LayoutCard>
      <DomainList.List
        aria-label="Domains"
        getItemId={(domain) => domain.id}
      >
        <DomainList.StaticData
          data={[
            {
              id: "1",
              domain: "mjaofd6.project.space",
              type: "Projekt-Domain",
            },
            {
              id: "2",
              domain: "formel1.de",
              type: "Domain",
              target: "Mein WordPress",
            },
            {
              id: "3",
              domain: "schumi-fanclub.de",
              type: "Virtual Host",
              target: "Mein WordPress",
            },
            {
              id: "4",
              domain: "www.formel1.de",
              type: "Subdomain",
              target: "/home/xyz/ordner/tollerpfad",
            },
          ]}
        />
        <DomainList.Search />
        <DomainList.Item
          textValue={(domain) => domain.domain}
          showTiles
        >
          {(domain) => (
            <ListItemView>
              <Avatar
                color={
                  domain.type === "Projekt-Domain"
                    ? "violet"
                    : domain.type === "Subdomain"
                      ? "green"
                      : domain.type === "Domain"
                        ? "blue"
                        : "teal"
                }
              >
                {domain.type === "Projekt-Domain" ? (
                  <IconHome />
                ) : domain.type === "Subdomain" ? (
                  <IconSubdomain />
                ) : domain.type === "Domain" ? (
                  <IconDomain />
                ) : (
                  <IconVhost />
                )}
              </Avatar>
              <Heading>{domain.domain}</Heading>
              <Text>{domain.type}</Text>
              <Content>
                <small>
                  {domain.target
                    ? domain.target
                    : "Kein Ziel"}
                </small>
              </Content>
              <ContextMenu>
                <MenuItem>
                  <IconInfo />
                  <Text>Details anzeigen</Text>
                </MenuItem>
              </ContextMenu>
            </ListItemView>
          )}
        </DomainList.Item>
        <ActionGroup>
          <ContextMenuTrigger>
            <Button color="accent">
              <Text>Hinzufügen</Text>
              <IconChevronDown />
            </Button>
            <ContextMenu>
              <MenuItem>
                <IconDomain />
                <Text>Domain bestellen</Text>
              </MenuItem>
              <MenuItem>
                <IconMove />
                <Text>Domain umziehen</Text>
              </MenuItem>
              <MenuItem>
                <IconVhost />
                <Text>vHost einrichten</Text>
              </MenuItem>
              <MenuItem>
                <IconSubdomain />
                <Text>Subdomain anlegen</Text>
              </MenuItem>
            </ContextMenu>
          </ContextMenuTrigger>
        </ActionGroup>
      </DomainList.List>
    </LayoutCard>
  );
}
```

## Mehr als 5 oder erklärungsbedürftige Elemente

Viele oder erklärungsbedürftige Optionen gibt es z. B. beim Installieren eines
CMS. Um den User in einer solchen Situation gut zu leiten, öffnet der
Anlege-[Button](/04-components/actions/button/overview) zunächst ein
Auswahl-[Modal](/04-components/overlays/modal/overview) im OffCanvas. Dort kann
der User filtern, suchen und sich über jedes Element kurz informieren. Danach
genügt ein Klick auf das gewünschte Element, um den Prozess zu starten.

**Beispiel**: Beim Anlegen einer App öffnet sich zunächst ein OffCanvas, um alle
zur Verfügung stehenden Optionen übersichtlich darzustellen.

```tsx
import {
  ActionGroup,
  Button,
  Heading,
  IconApp,
  IllustratedMessage,
  Text,
  LayoutCard,
  ModalTrigger,
  Modal,
  typedList,
  Content,
  ListItemView,
  Avatar,
  Action,
} from "@mittwald/flow-react-components";

export default () => {
  const AppList = typedList<{
    id: string;
    name: string;
  }>();

  return (
    <LayoutCard>
      <IllustratedMessage>
        <IconApp />
        <Heading>App anlegen</Heading>
        <Text>
          Lege deine erste App an, um mit der Arbeit an
          deiner Website loszulegen.
        </Text>

        <ActionGroup>
          <ModalTrigger>
            <Button color="accent">Anlegen</Button>
            <Modal offCanvas>
              <Heading>App anlegen</Heading>
              <Content>
                <AppList.List defaultViewMode="tiles">
                  <AppList.Search />
                  <AppList.StaticData
                    data={[
                      { id: "1", name: "PHP" },
                      { id: "2", name: "TYPO3" },
                      { id: "1", name: "WordPress" },
                    ]}
                  />
                  <AppList.Item showTiles showList={false}>
                    {(app) => (
                      <ListItemView>
                        <Avatar>
                          <IconApp />
                        </Avatar>
                        <Heading>{app.name}</Heading>
                      </ListItemView>
                    )}
                  </AppList.Item>
                </AppList.List>
              </Content>
              <ActionGroup>
                <Action closeModal>
                  <Button color="secondary" variant="soft">
                    Abbrechen
                  </Button>
                </Action>
              </ActionGroup>
            </Modal>
          </ModalTrigger>
        </ActionGroup>
      </IllustratedMessage>
    </LayoutCard>
  );
}
```

---

# Bearbeiten

Angelegte Elemente verfügen meist über eine Detailseite. Diese kann aus mehreren
[Sections](/04-components/structure/section/overview) (vgl.
[Content strukturieren](/03-patterns/01-patterns/detail-page)) bestehen.
Innerhalb einer Section kann über die
[SectionAction](/04-components/structure/section/overview#sectionaction) ein
„Bearbeiten“-[Button](/04-components/actions/button/overview) platziert werden,
mit dem der User Inhalte direkt dort ändern kann, wo sie angezeigt werden.

**Beispiel**: Die Detailseite einer App ist in mehrere Sections aufgeteilt. Jede
Section stellt Informationen oder Konfigurationen zu einem bestimmten Inhalt
dar. Über die SectionAction lassen sich die angezeigten Inhalte bearbeiten oder
neue Prozesse starten.

```tsx
import {
  Align,
  Button,
  ColumnLayout,
  CopyButton,
  Header,
  Heading,
  InlineCode,
  Label,
  LabeledValue,
  LayoutCard,
  Link,
  Option,
  Section,
  Select,
  Table,
  TableBody,
  TableCell,
  TableColumn,
  TableHeader,
  TableRow,
  Text,
} from "@mittwald/flow-react-components";

<LayoutCard>
  <Section>
    <Header>
      <Heading>WordPress 6.5.3 App</Heading>
      <Button color="secondary" variant="soft">
        PHP Version anpassen
      </Button>
    </Header>
    <ColumnLayout>
      <LabeledValue>
        <Label>Installationsverzeichnis</Label>
        <Text>
          <InlineCode>/f1-blog-th6v8</InlineCode>
        </Text>
        <CopyButton value="/f1-blog-th6v8" />
      </LabeledValue>
      <LabeledValue>
        <Label>PHP-Version</Label>
        <Text>PHP 8.5.3</Text>
      </LabeledValue>
    </ColumnLayout>
  </Section>
  <Section>
    <Header>
      <Heading>Domain</Heading>
      <Button color="secondary" variant="soft">
        Bearbeiten
      </Button>
    </Header>
    <ColumnLayout>
      <LabeledValue>
        <Label>Frontend</Label>
        <Link target="_blank">
          p-xy1z2.project.frontend
        </Link>
      </LabeledValue>
      <LabeledValue>
        <Label>Backend</Label>
        <Link target="_blank">p-xy1z2.project.backend</Link>
      </LabeledValue>
    </ColumnLayout>
  </Section>
  <Section>
    <Heading>SSH-Zugangsdaten</Heading>
    <ColumnLayout l={[2, 1]} m={[2, 1]}>
      <Select defaultSelectedKey="1">
        <Label>SSH-Benutzer</Label>
        <Option value="1">
          mStudio Benutzer (m.muster@mittwald.de)
        </Option>
      </Select>
    </ColumnLayout>
    <Table aria-label="SSH-Zugangsdaten">
      <TableHeader>
        <TableColumn />
        <TableColumn />
      </TableHeader>
      <TableBody>
        <TableRow>
          <TableCell rowHeader>Benutzername</TableCell>
          <TableCell>
            <Align>
              <Text>j.eimertenbrink</Text>
              <CopyButton value="m.muster" />
            </Align>
          </TableCell>
        </TableRow>
        <TableRow>
          <TableCell rowHeader>Hostname</TableCell>
          <TableCell>
            <Align>
              <Text>ssh.mittwald.host</Text>
              <CopyButton value="ssh.mittwald.host" />
            </Align>
          </TableCell>
        </TableRow>
        <TableRow>
          <TableCell rowHeader>URL</TableCell>
          <TableCell>
            <Align>
              <Text>j.eimertenbrink@ssh.mittwald.host</Text>
              <CopyButton value="m.muster@ssh.mittwald.host" />
            </Align>
          </TableCell>
        </TableRow>
      </TableBody>
    </Table>
  </Section>
</LayoutCard>
```
