@accounter/client
Version:
Accounter client application
1 lines • 13.2 kB
JavaScript
import{s as e}from"./dist-ypP48_Ax.js";import{i as t,n,o as r,t as i}from"./utils-CbS-oR5I.js";import{r as a,t as o}from"./error-handling-CKe_iwSC.js";import{t as s}from"./createLucideIcon-BK8Z-P8J.js";import{a as c,c as l,d as u,f as d,i as f,l as p,n as m,o as h,p as g,r as _,s as v,t as y,u as b,ut as x}from"./select-DrAHsHyM.js";import{t as S}from"./chevron-right-B6x1sjCY.js";import{a as C,b as w,c as T,d as E,f as D,h as O,l as ee,n as k,r as A,s as j,x as te,y as ne}from"./separator-CQBUMn7G.js";import{t as re}from"./pencil-B2Xwvx_n.js";import{c as ie,t as M}from"./button-DUNsVBiu.js";import{a as ae,c as oe,i as se,o as ce,r as le,s as ue,t as N}from"./alert-dialog-zeNxWOJl.js";import{I as P,Jn as F,ls as I,m as L,us as R}from"./graphql-BIob9ctl.js";import{t as z}from"./page-layout-YKSXEkhJ.js";import{a as B,i as V,n as H,r as U,t as de}from"./empty-BJZb5Yi4.js";import{t as W}from"./spinner-4ZGZEynN.js";var fe=s(`tag`,[[`path`,{d:`M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z`,key:`vktsd0`}],[`circle`,{cx:`7.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`kqv944`}]]),G=e(r(),1),pe=`addTag`,K=()=>{let[{fetching:e},t]=I(L);return{fetching:e,addTag:(0,G.useCallback)(async e=>{let n=`Error adding new tag [${e.tagName}]`,r=`${pe}-${e.tagName}`;a.loading(`Adding tag`,{id:r});try{let i=await t(e);o(i,n,r)&&a.success(`Success`,{id:r,description:`"${e.tagName}" tag was successfully added`})}catch(e){console.error(`${n}: ${e}`),a.error(`Error`,{id:r,description:n,duration:1e5,closeButton:!0})}},[t])}},q=t();function me({className:e,...t}){return(0,q.jsx)(`div`,{"data-slot":`field-group`,className:i(`group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4`,e),...t})}var he=ie(`group/field data-[invalid=true]:text-red-500 flex w-full gap-3 dark:data-[invalid=true]:text-red-900`,{variants:{orientation:{vertical:[`flex-col [&>*]:w-full [&>.sr-only]:w-auto`],horizontal:[`flex-row items-center`,`[&>[data-slot=field-label]]:flex-auto`,`has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px has-[>[data-slot=field-content]]:items-start`],responsive:[`@md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto flex-col [&>*]:w-full [&>.sr-only]:w-auto`,`@md/field-group:[&>[data-slot=field-label]]:flex-auto`,`@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px`]}},defaultVariants:{orientation:`vertical`}});function J({className:e,orientation:t=`vertical`,...n}){return(0,q.jsx)(`div`,{role:`group`,"data-slot":`field`,"data-orientation":t,className:i(he({orientation:t}),e),...n})}function Y({className:e,...t}){return(0,q.jsx)(h,{"data-slot":`field-label`,className:i(`group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50`,`has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>[data-slot=field]]:p-4`,`has-data-[state=checked]:bg-gray-900/5 has-data-[state=checked]:border-gray-900 dark:has-data-[state=checked]:bg-gray-900/10 dark:has-data-[state=checked]:bg-gray-50/5 dark:has-data-[state=checked]:border-gray-50 dark:dark:has-data-[state=checked]:bg-gray-50/10`,e),...t})}function X({open:e,onOpenChange:t,tag:r,onSave:i,isSaving:a}){let[o,s]=(0,G.useState)(``),[h,x]=(0,G.useState)(null),[{data:S,fetching:C},w]=R({query:P,pause:!0});(0,G.useEffect)(()=>{e&&w()},[e,w]);let T=(0,G.useMemo)(()=>S?.allTags??[],[S]);(0,G.useEffect)(()=>{e&&(r?(s(r.name),x(r.parent?.id??null)):(s(``),x(null)))},[r,e]);let E=async()=>{o.trim()&&!a&&(await i(o.trim(),h),t(!1))},D=(0,G.useMemo)(()=>{if(!r)return T;let e=new Set,t=[r.id],n=T.reduce((e,t)=>{if(t.parent?.id){let n=e.get(t.parent.id)??[];n.push(t.id),e.set(t.parent.id,n)}return e},new Map);for(;t.length>0;){let r=t.shift();if(!e.has(r)){e.add(r);let i=n.get(r)??[];t.push(...i)}}return T.filter(t=>!e.has(t.id))},[T,r]),O=n(o);return(0,q.jsx)(l,{open:e,onOpenChange:a?void 0:t,children:(0,q.jsx)(p,{className:`max-w-[calc(100vw-2rem)] sm:max-w-lg`,children:C&&T.length===0?(0,q.jsxs)(`div`,{className:`flex flex-col items-center justify-center py-10 gap-3`,children:[(0,q.jsx)(W,{className:`size-8`}),(0,q.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:`Loading tags...`})]}):(0,q.jsxs)(q.Fragment,{children:[(0,q.jsxs)(d,{children:[(0,q.jsx)(g,{children:r?`Edit Tag`:`Create Tag`}),(0,q.jsx)(b,{children:r?`Update the tag name and parent category.`:`Add a new tag to organize your finances.`})]}),(0,q.jsxs)(me,{children:[(0,q.jsxs)(J,{children:[(0,q.jsx)(Y,{htmlFor:`tag-name`,children:`Name`}),(0,q.jsx)(v,{id:`tag-name`,value:o,onChange:e=>s(e.target.value),placeholder:`Enter tag name`,dir:O?`rtl`:`ltr`,disabled:a,onKeyDown:e=>{e.key===`Enter`&&E()}})]}),(0,q.jsxs)(J,{children:[(0,q.jsx)(Y,{htmlFor:`tag-parent`,children:`Parent Tag (optional)`}),(0,q.jsxs)(y,{value:h??`none`,onValueChange:e=>x(e===`none`?null:e),disabled:a,children:[(0,q.jsx)(f,{id:`tag-parent`,children:(0,q.jsx)(c,{placeholder:`Select parent tag`})}),(0,q.jsxs)(m,{children:[(0,q.jsx)(_,{value:`none`,children:`No Parent`}),D.map(e=>{let t=e.namePath&&e.namePath.length>0?`${e.namePath.join(` / `)} / ${e.name}`:e.name;return(0,q.jsx)(_,{value:e.id,dir:n(e.name)?`rtl`:`ltr`,children:t},e.id)})]})]})]})]}),(0,q.jsxs)(u,{className:`flex-col gap-2 sm:flex-row`,children:[(0,q.jsx)(M,{variant:`outline`,onClick:()=>t(!1),className:`w-full sm:w-auto`,disabled:a,children:`Cancel`}),(0,q.jsx)(M,{onClick:E,disabled:!o.trim()||a,className:`w-full sm:w-auto`,children:a?(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(W,{className:`size-4 me-2`}),`Saving...`]}):r?`Save Changes`:`Create Tag`})]})]})})})}function Z({onDone:e,children:t}){let[n,r]=(0,G.useState)(!1),[i,a]=(0,G.useState)(!1),{addTag:o}=K(),s=(0,G.useCallback)(async(t,n)=>{a(!0);try{await o({tagName:t,parentTag:n}),await e()}finally{a(!1)}},[o,e]);return(0,q.jsxs)(q.Fragment,{children:[t?(0,q.jsx)(M,{asChild:!0,onClick:()=>r(!0),children:t}):(0,q.jsxs)(M,{onClick:()=>r(!0),className:`w-full sm:w-auto`,children:[(0,q.jsx)(x,{className:`size-4 me-2`}),`Create Tag`]}),(0,q.jsx)(X,{open:n,onOpenChange:r,tag:null,onSave:s,isSaving:i})]})}var ge=`deleteTag`,_e=()=>{let[{fetching:e},t]=I(F);return{fetching:e,deleteTag:(0,G.useCallback)(async e=>{let n=`Error deleting new tag [${e.name}]`,r=`${ge}-${e.tagId}`;a.loading(`Deleting tag [${e.name}]`,{id:r});try{let i=await t(e);o(i,n,r)&&a.success(`Tag Deleted`,{id:r,description:`[${e.name}] tag was successfully removed`})}catch(e){console.error(`${n}: ${e}`),a.error(`Error`,{id:r,description:n,duration:1e5,closeButton:!0})}},[t])}};function Q({open:e,onOpenChange:t,tag:r,onConfirm:i,isDeleting:a}){if(!r)return null;let o=n(r.name);return(0,q.jsx)(N,{open:e,onOpenChange:a?void 0:t,children:(0,q.jsxs)(se,{className:`max-w-[calc(100vw-2rem)] sm:max-w-lg`,children:[(0,q.jsxs)(ue,{children:[(0,q.jsx)(oe,{children:`Delete Tag`}),(0,q.jsxs)(ae,{children:[`Are you sure you want to delete the tag`,` `,(0,q.jsxs)(`span`,{className:`font-semibold text-foreground`,dir:o?`rtl`:`ltr`,children:[`"`,r.name,`"`]}),`? This action cannot be undone.`]})]}),(0,q.jsxs)(ce,{className:`flex-col gap-2 sm:flex-row`,children:[(0,q.jsx)(le,{className:`w-full sm:w-auto`,disabled:a,children:`Cancel`}),(0,q.jsx)(M,{onClick:i,disabled:a,variant:`destructive`,className:`w-full sm:w-auto`,children:a?(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(W,{className:`size-4 me-2`}),`Deleting...`]}):`Delete`})]})]})})}function ve({tag:e,depth:t,hasChildren:r,isCollapsed:a,onToggleCollapse:o,onEdit:s,onDelete:c}){let l=n(e.name);return(0,q.jsxs)(`div`,{className:i(`group flex items-center justify-between gap-2 px-3 py-3 border-b border-border`,`hover:bg-secondary/50 transition-colors`,`sm:px-4`),children:[(0,q.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0 flex-1`,style:{paddingInlineStart:`${t*20}px`},children:[r?(0,q.jsx)(`button`,{type:`button`,onClick:()=>o(e.id),className:`p-0.5 rounded hover:bg-secondary transition-colors shrink-0`,"aria-expanded":!a,"aria-label":a?`Expand`:`Collapse`,children:(0,q.jsx)(S,{className:i(`size-4 text-muted-foreground transition-transform rtl:rotate-180`,!a&&`rotate-90 rtl:rotate-90`)})}):t>0?(0,q.jsx)(`span`,{className:`size-4 shrink-0`,"aria-hidden":`true`}):null,(0,q.jsx)(`span`,{className:i(`text-foreground font-medium truncate`,l&&`text-right`),dir:l?`rtl`:`ltr`,children:e.name}),e.namePath&&e.namePath.length>0&&(0,q.jsxs)(`span`,{className:`text-muted-foreground text-sm hidden sm:inline truncate shrink-0`,children:[`(`,e.namePath.join(` / `),`)`]})]}),(0,q.jsxs)(ee,{children:[(0,q.jsx)(O,{asChild:!0,children:(0,q.jsxs)(M,{variant:`ghost`,size:`sm`,className:`opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity shrink-0`,children:[(0,q.jsx)(te,{className:`size-4`}),(0,q.jsx)(`span`,{className:`sr-only`,children:`Actions`})]})}),(0,q.jsxs)(E,{align:`end`,children:[(0,q.jsxs)(D,{onClick:()=>s(e),children:[(0,q.jsx)(re,{className:`size-4 me-2`}),`Edit`]}),(0,q.jsxs)(D,{onClick:()=>c(e),className:`text-destructive focus:text-destructive`,children:[(0,q.jsx)(ne,{className:`size-4 me-2`}),`Delete`]})]})]})]})}function ye(e){let t=new Map,n=[];e.map(e=>{t.set(e.id,{tag:e,children:[]})}),e.map(e=>{let r=t.get(e.id);if(e.parent){let i=t.get(e.parent.id);i?i.children.push(r):n.push(r)}else n.push(r)});let r=e=>e.sort((e,t)=>e.tag.name.localeCompare(t.tag.name)).map(e=>({...e,children:r(e.children)}));return r(n)}function $(e,t,n=0){let r=[];return e.map(e=>{let i=e.children.length>0;r.push({tag:e.tag,depth:n,hasChildren:i}),i&&!t.has(e.tag.id)&&r.push(...$(e.children,t,n+1))}),r}function be({search:e,allTags:t,onChange:n}){let[r,i]=(0,G.useState)(new Set),[a,o]=(0,G.useState)(!1),[s,c]=(0,G.useState)(!1),[l,u]=(0,G.useState)(null),[d,f]=(0,G.useState)(!1),[p,m]=(0,G.useState)(!1),{addTag:h}=K(),{deleteTag:g}=_e(),{updateTag:_}=j(),v=(0,G.useMemo)(()=>{if(!e.trim())return t;let n=e.toLowerCase();return t.filter(e=>e.name.toLowerCase().includes(n)||e.namePath?.some(e=>e.toLowerCase().includes(n)))},[t,e]),y=(0,G.useMemo)(()=>$(ye(v),r),[v,r]);(0,G.useEffect)(()=>{e.trim()&&i(new Set)},[e]);let b=(0,G.useCallback)(e=>{i(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),S=(0,G.useCallback)(e=>{u(e),o(!0)},[]),C=(0,G.useCallback)(e=>{u(e),c(!0)},[]),w=(0,G.useCallback)(async(e,t)=>{f(!0);try{l?await _({tagId:l.id,fields:{name:e,parentId:t}}):await h({tagName:e,parentTag:t}),await n(),u(null)}finally{f(!1)}},[h,l,n,_]),T=(0,G.useCallback)(async()=>{if(l){m(!0);try{await g({tagId:l.id,name:l.name}),await n(),u(null),c(!1)}finally{m(!1)}}},[g,l,n]);return(0,q.jsxs)(`div`,{className:`min-h-screen bg-background`,children:[(0,q.jsxs)(`div`,{className:`max-w-4xl mx-auto px-4 py-6 sm:py-8`,children:[(0,q.jsx)(`div`,{className:`rounded-lg border border-border bg-card overflow-hidden`,children:y.length>0?y.map(({tag:e,depth:t,hasChildren:n})=>(0,q.jsx)(ve,{tag:e,depth:t,hasChildren:n,isCollapsed:r.has(e.id),onToggleCollapse:b,onEdit:S,onDelete:C},e.id)):(0,q.jsxs)(de,{className:`py-8 sm:py-12`,children:[(0,q.jsx)(V,{children:(0,q.jsx)(fe,{className:`size-8 sm:size-10 text-muted-foreground`})}),(0,q.jsx)(B,{children:e?`No tags found`:`No tags yet`}),(0,q.jsx)(U,{children:e?`Try adjusting your search query.`:`Create your first tag to start organizing your finances.`}),!e&&(0,q.jsx)(H,{children:(0,q.jsx)(Z,{onDone:n,children:(0,q.jsxs)(M,{children:[(0,q.jsx)(x,{className:`size-4 me-2`}),`Create Tag`]})})})]})}),t.length>0&&(0,q.jsxs)(`p`,{className:`text-muted-foreground text-sm mt-4 text-center`,children:[v.length,` of `,t.length,` tag`,t.length===1?``:`s`]})]}),(0,q.jsx)(X,{open:a,onOpenChange:o,tag:l,onSave:w,isSaving:d}),(0,q.jsx)(Q,{open:s,onOpenChange:c,tag:l,onConfirm:T,isDeleting:p})]})}var xe=()=>{let[e,t]=(0,G.useState)(``),{setFiltersContext:n}=(0,G.useContext)(T);(0,G.useEffect)(()=>{n(null)},[n]);let[{data:r,fetching:i},a]=R({query:P}),o=(0,G.useMemo)(()=>r?.allTags??[],[r]);return i&&o.length===0?(0,q.jsx)(`div`,{className:`min-h-screen bg-background flex items-center justify-center`,children:(0,q.jsxs)(`div`,{className:`flex flex-col items-center gap-3`,children:[(0,q.jsx)(W,{className:`size-8`}),(0,q.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:`Loading tags...`})]})}):(0,q.jsx)(z,{title:`Tags`,description:`Manage your charges tags.`,headerActions:(0,q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,q.jsxs)(k,{className:`max-w-xs`,children:[(0,q.jsx)(C,{placeholder:`Search tags...`,value:e,onChange:e=>t(e.target.value),className:`ps-10`}),(0,q.jsx)(A,{children:(0,q.jsx)(w,{})})]}),(0,q.jsx)(Z,{onDone:async()=>{await a()},children:(0,q.jsxs)(M,{className:`w-full sm:w-auto`,children:[(0,q.jsx)(x,{className:`size-4 me-2`}),`Create Tag`]})})]}),children:(0,q.jsx)(be,{search:e,allTags:o,onChange:async()=>{await a()}})})};export{xe as TagsManager};