<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Frontend (Mantine) on Palmyra</title>
    <link>https://palmyra.dev/docs/employee-app/frontend/</link>
    <description>Recent content in Frontend (Mantine) on Palmyra</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <atom:link href="https://palmyra.dev/docs/employee-app/frontend/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>1. Project setup</title>
      <link>https://palmyra.dev/docs/employee-app/frontend/01-setup/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://palmyra.dev/docs/employee-app/frontend/01-setup/</guid>
      <description>&lt;h1 id=&#34;1-project-setup&#34;&gt;1. Project setup&lt;a class=&#34;anchor&#34; href=&#34;#1-project-setup&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;&lt;strong&gt;What this step does.&lt;/strong&gt; Scaffolds a plain Vite + React + TypeScript app, adds Mantine and the three Palmyra frontend libraries, configures a dev-server proxy so &lt;code&gt;/api&lt;/code&gt; lands on the SpringBoot backend, and sets up routing.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm create vite@latest empmgmt-web -- --template react-ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd empmgmt-web&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;install&#34;&gt;Install&lt;a class=&#34;anchor&#34; href=&#34;#install&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm install react@19 react-dom@19 &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            @mantine/core@8 @mantine/hooks@8 @mantine/dates@8 &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            react-router-dom@7 react-toastify dayjs &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            @palmyralabs/palmyra-wire &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            @palmyralabs/rt-forms &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            @palmyralabs/rt-forms-mantine &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            @palmyralabs/template-tribble&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;@palmyralabs/template-tribble&lt;/code&gt; supplies &lt;code&gt;SummaryGrid&lt;/code&gt;, &lt;code&gt;DialogNewForm&lt;/code&gt;, and &lt;code&gt;DialogEditForm&lt;/code&gt; — prebuilt templates that cut the repetitive grid / modal plumbing out of each page. This is the same pattern the &lt;a href=&#34;https://github.com/thinxar/clinic/tree/main/web/src/pages/masterdata/product&#34;&gt;&lt;code&gt;thinxar/clinic&lt;/code&gt;&lt;/a&gt; reference uses.&lt;/p&gt;</description>
    </item>
    <item>
      <title>2. Store factory &#43; endpoints</title>
      <link>https://palmyra.dev/docs/employee-app/frontend/02-api-wiring/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://palmyra.dev/docs/employee-app/frontend/02-api-wiring/</guid>
      <description>&lt;h1 id=&#34;2-store-factory--endpoints&#34;&gt;2. Store factory + endpoints&lt;a class=&#34;anchor&#34; href=&#34;#2-store-factory--endpoints&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;&lt;strong&gt;What this step does.&lt;/strong&gt; Configures the &lt;strong&gt;single source of truth&lt;/strong&gt; for network calls — every grid, form, and lookup on the frontend goes through this factory. Pages never import axios or fetch.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;p&gt;One factory, one error handler, one central endpoint config. Every page fetches through this.&lt;/p&gt;&#xA;&lt;h2 id=&#34;store-factory&#34;&gt;Store factory&lt;a class=&#34;anchor&#34; href=&#34;#store-factory&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// src/wire/StoreFactory.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;PalmyraStoreFactory&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;@palmyralabs/palmyra-wire&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;toast&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;react-toastify&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;errorHandler&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; () &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;any&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;status&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;response&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;status&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;status&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;===&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;401&lt;/span&gt;) { window.&lt;span style=&#34;color:#a6e22e&#34;&gt;location&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;assign&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/login&amp;#39;&lt;/span&gt;); &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;status&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;===&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;403&lt;/span&gt;) { &lt;span style=&#34;color:#a6e22e&#34;&gt;toast&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;You don&amp;#39;t have permission for this action.&amp;#34;&lt;/span&gt;); &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;status&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;)  { &lt;span style=&#34;color:#a6e22e&#34;&gt;toast&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Server error. Please retry.&amp;#39;&lt;/span&gt;); &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AppStoreFactory&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;PalmyraStoreFactory&lt;/span&gt;({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;baseUrl&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/api&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;errorHandlerFactory&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;errorHandler&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AppStoreFactory&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;baseUrl: &#39;/api&#39;&lt;/code&gt; matches the SpringBoot context path set in the &lt;a href=&#34;https://palmyra.dev/docs/employee-app/backend/01-setup/&#34;&gt;backend setup&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>3. Department screens</title>
      <link>https://palmyra.dev/docs/employee-app/frontend/03-department-pages/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://palmyra.dev/docs/employee-app/frontend/03-department-pages/</guid>
      <description>&lt;h1 id=&#34;3-department-screens&#34;&gt;3. Department screens&lt;a class=&#34;anchor&#34; href=&#34;#3-department-screens&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;&lt;strong&gt;What this step does.&lt;/strong&gt; Builds the first entity&amp;rsquo;s full UX with &lt;strong&gt;five small files&lt;/strong&gt; — a list grid, a &amp;ldquo;New&amp;rdquo; modal, a detail page, a read-only view form, and an &amp;ldquo;Edit&amp;rdquo; modal. Nothing touches axios; the grid and forms resolve endpoints on their own through the store factory context from step 2.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;p&gt;Five files per entity, following the clinic&amp;rsquo;s masterdata layout: grid page + new-form dialog at the top level; detail page + view form + edit dialog under &lt;code&gt;view/&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>4. Employee screens</title>
      <link>https://palmyra.dev/docs/employee-app/frontend/04-employee-pages/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://palmyra.dev/docs/employee-app/frontend/04-employee-pages/</guid>
      <description>&lt;h1 id=&#34;4-employee-screens&#34;&gt;4. Employee screens&lt;a class=&#34;anchor&#34; href=&#34;#4-employee-screens&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;&lt;strong&gt;What this step does.&lt;/strong&gt; Repeats the Department five-file pattern for Employees, plus two idioms the first entity didn&amp;rsquo;t need: a &lt;strong&gt;dotted &lt;code&gt;department.code&lt;/code&gt; column&lt;/strong&gt; that reads the FK join inline, and a &lt;strong&gt;&lt;code&gt;MantineServerLookup&lt;/code&gt;&lt;/strong&gt; against &lt;code&gt;/department&lt;/code&gt; that turns the Department dropdown into a live server query.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;p&gt;Same five-file layout as Department — grid + new-form at the top level, view subfolder for the detail page and its edit dialog. The interesting bits here are the &lt;strong&gt;flattened FK column&lt;/strong&gt; in the grid and the &lt;strong&gt;&lt;code&gt;MantineServerLookup&lt;/code&gt;&lt;/strong&gt; against &lt;code&gt;/department&lt;/code&gt; inside the form.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
