web_lib

Common web application libraries
git clone https://radroots.dev/git/web_lib.git
Log | Files | Refs | LICENSE

profile.svelte (13406B)


      1 <script lang="ts">
      2     import { ImagePath, NavigationTabs, SelectMenu } from "$lib";
      3     import ButtonRoundNav from "$lib/components/button/button-round-nav.svelte";
      4     import FloatPage from "$lib/components/lib/float-page.svelte";
      5     import ImageUploadPhotoAdd from "$lib/components/media/image-upload-photo-add.svelte";
      6     import type { LibContext } from "$lib/types/context";
      7     import type { IViewBasis } from "$lib/types/views";
      8     import type {
      9         IViewProfileData,
     10         ViewProfileEditFieldKey,
     11     } from "$lib/types/views/profile";
     12     import { idb_kv_init_page } from "$lib/utils/keyval";
     13     import {
     14         get_context,
     15         Glyph,
     16         SYMBOLS,
     17         type IViewOnDestroy,
     18     } from "@radroots/apps-lib";
     19     import {
     20         handle_err,
     21         type CallbackPromise,
     22         type CallbackPromiseGeneric,
     23     } from "@radroots/utils";
     24     import { onDestroy, onMount } from "svelte";
     25 
     26     const { ls } = get_context<LibContext>(`lib`);
     27 
     28     let {
     29         basis,
     30         photo_path = $bindable(``),
     31     }: {
     32         basis: IViewBasis<{
     33             data?: IViewProfileData;
     34             loading_photo_upload: boolean;
     35             loading_photo_upload_open: boolean;
     36             on_handle_back: CallbackPromiseGeneric<{
     37                 is_photo_existing: boolean;
     38             }>;
     39             on_handle_photo_options: CallbackPromise;
     40             on_handle_edit_profile_field: CallbackPromiseGeneric<{
     41                 field: ViewProfileEditFieldKey;
     42             }>;
     43         }> &
     44             IViewOnDestroy<{ public_key: string }>;
     45         photo_path: string;
     46     } = $props();
     47 
     48     type ViewDisplay = `photos` | `following` | `followers`;
     49     let view_display: ViewDisplay = $state(`photos`);
     50 
     51     let val_sel_options_button = $state(``);
     52 
     53     $effect(() => {
     54         console.log(JSON.stringify(basis.data, null, 4), `data`);
     55     });
     56 
     57     onMount(async () => {
     58         try {
     59             if (!basis.kv_init_prevent) await idb_kv_init_page();
     60         } catch (e) {
     61             handle_err(e, `on_mount`);
     62         }
     63     });
     64 
     65     onDestroy(async () => {
     66         try {
     67             if (basis.data?.profile.public_key)
     68                 await basis.on_destroy({
     69                     public_key: basis.data.profile.public_key,
     70                 });
     71         } catch (e) {
     72             handle_err(e, `on_destroy`);
     73         }
     74     });
     75 
     76     const photo_overlay_visible = $derived(
     77         !!(basis.data?.profile.picture || photo_path),
     78     );
     79 
     80     const classes_photo_overlay_glyph = $derived(
     81         photo_overlay_visible ? `text-white` : `text-ly0-gl`,
     82     );
     83 
     84     const classes_photo_overlay_glyph_opt = $derived(
     85         photo_overlay_visible ? `text-gray-300` : `text-ly0-gl`,
     86     );
     87 
     88     const classes_photo_overlay_glyph_opt_selected = $derived(
     89         photo_overlay_visible ? `text-white` : `text-ly1-gl_d`,
     90     );
     91 </script>
     92 
     93 {#if basis.data}
     94     <div
     95         class={`relative flex flex-col min-h-[525px] h-[525px] w-full justify-center items-center bg-ly2 fade-in`}
     96     >
     97         <FloatPage
     98             basis={{
     99                 posx: `left`,
    100             }}
    101         >
    102             <ButtonRoundNav
    103                 basis={{
    104                     glyph: `arrow-left`,
    105                     loading: basis.loading_photo_upload,
    106                     callback: async () => {
    107                         await basis.on_handle_back({
    108                             is_photo_existing: photo_overlay_visible,
    109                         });
    110                     },
    111                 }}
    112             />
    113         </FloatPage>
    114         {#if photo_path}
    115             <button
    116                 class={`absolute top-12 flex flex-row h-7 px-6 justify-center items-center bg-ly1 active:bg-ly1-a rounded-full`}
    117                 onclick={async () => {}}
    118             >
    119                 <p class={`font-sans font-[400] text-sm text-ly0-gl`}>
    120                     {`Post Photo`}
    121                 </p>
    122             </button>
    123         {/if}
    124         <FloatPage
    125             basis={{
    126                 posx: `right`,
    127             }}
    128         >
    129             <SelectMenu
    130                 bind:value={val_sel_options_button}
    131                 basis={{
    132                     layer: 0,
    133                     options: [
    134                         {
    135                             entries: [
    136                                 {
    137                                     value: `*add-new`,
    138                                     label: `Add new photo`,
    139                                 },
    140                             ],
    141                         },
    142                     ],
    143                 }}
    144             >
    145                 <ButtonRoundNav
    146                     basis={{
    147                         glyph: `images-square`,
    148                         callback: basis.on_handle_photo_options,
    149                     }}
    150                 />
    151             </SelectMenu>
    152         </FloatPage>
    153         {#if basis.data.profile.picture || photo_path}
    154             {@const img_path = photo_path || basis.data.profile.picture || ``}
    155             <ImagePath basis={{ path: img_path }} />
    156         {:else}
    157             <div
    158                 class={`flex flex-row justify-start items-center -translate-y-8`}
    159             >
    160                 <ImageUploadPhotoAdd
    161                     bind:photo_path
    162                     basis={{
    163                         loading: basis.loading_photo_upload_open,
    164                     }}
    165                 />
    166             </div>
    167         {/if}
    168         <div
    169             class={`absolute bottom-0 left-0 flex flex-col h-[calc(100%-100%/1.618)] w-full px-6 gap-2 justify-end items-center`}
    170         >
    171             <div
    172                 class={`flex flex-col w-full gap-[2px] justify-center items-center`}
    173             >
    174                 <div
    175                     class={`flex flex-row h-10 w-full justify-start items-center`}
    176                 >
    177                     <button
    178                         class={`group flex flex-row justify-center items-center`}
    179                         onclick={async () => {
    180                             await basis.on_handle_edit_profile_field({
    181                                 field: `display_name`,
    182                             });
    183                         }}
    184                     >
    185                         <p
    186                             class={`font-sansd font-[600] text-[2rem] ${classes_photo_overlay_glyph} ${
    187                                 basis.data?.profile.name
    188                                     ? ``
    189                                     : `capitalize opacity-active`
    190                             } el-re`}
    191                         >
    192                             {#if basis.data?.profile.display_name}
    193                                 {`${basis.data?.profile.display_name}`}
    194                             {:else if basis.data?.profile.name}
    195                                 {`${
    196                                     basis.data?.profile.display_name ||
    197                                     basis.data?.profile.name ||
    198                                     ``
    199                                 }`}
    200                             {:else}
    201                                 {`+ ${`${$ls(`icu.add_*`, {
    202                                     value: `${$ls(`common.profile_name`)}`,
    203                                 })}`}`}
    204                             {/if}
    205                         </p>
    206                     </button>
    207                 </div>
    208                 <div
    209                     class={`flex flex-row w-full gap-[6px] justify-start items-center`}
    210                 >
    211                     <button
    212                         class={`group flex flex-row justify-center items-center`}
    213                         onclick={async () => {
    214                             await basis.on_handle_edit_profile_field({
    215                                 field: `name`,
    216                             });
    217                         }}
    218                     >
    219                         <p
    220                             class={`font-sansd font-[600] text-[1.1rem] ${classes_photo_overlay_glyph} ${
    221                                 basis.data?.profile.name
    222                                     ? ``
    223                                     : `capitalize opacity-active`
    224                             } el-re`}
    225                         >
    226                             {#if basis.data?.profile.name}
    227                                 {`@${basis.data.profile.name}`}
    228                             {:else}
    229                                 {`+ ${`${$ls(`icu.add_*`, {
    230                                     value: `${$ls(`common.username`)}`,
    231                                 })}`}`}
    232                             {/if}
    233                         </p>
    234                     </button>
    235                     <p
    236                         class={`font-sans font-[400] ${classes_photo_overlay_glyph}`}
    237                     >
    238                         {SYMBOLS.bullet}
    239                     </p>
    240                     <button
    241                         class={`flex flex-row justify-center items-center`}
    242                         onclick={async () => {
    243                             alert(`@todo!`);
    244                         }}
    245                     >
    246                         <Glyph
    247                             basis={{
    248                                 classes: `${classes_photo_overlay_glyph}`,
    249                                 dim: `xs`,
    250 
    251                                 key: `link-simple`,
    252                             }}
    253                         />
    254                     </button>
    255                 </div>
    256                 <div class={`flex flex-row w-full justify-start items-center`}>
    257                     <button
    258                         class={`group flex flex-row justify-center items-center`}
    259                         onclick={async () => {
    260                             await basis.on_handle_edit_profile_field({
    261                                 field: `about`,
    262                             });
    263                         }}
    264                     >
    265                         <p
    266                             class={`font-sansd font-[400] text-[1.1rem] ${classes_photo_overlay_glyph} ${
    267                                 basis.data?.profile.about
    268                                     ? ``
    269                                     : `capitalize opacity-active`
    270                             }`}
    271                         >
    272                             {#if basis.data?.profile.about}
    273                                 {`${basis.data.profile.about}`}
    274                             {:else}
    275                                 {`+ ${`${$ls(`icu.add_*`, {
    276                                     value: `${$ls(`common.bio`)}`,
    277                                 })}`}`}
    278                             {/if}
    279                         </p>
    280                     </button>
    281                 </div>
    282             </div>
    283             <div
    284                 class={`flex flex-row w-full pt-2 pb-6 gap-2 justify-start items-center`}
    285             >
    286                 <button
    287                     class={`flex flex-row justify-center items-center`}
    288                     onclick={async () => {
    289                         view_display = `photos`;
    290                     }}
    291                 >
    292                     <p
    293                         class={`font-sans text-[1.1rem] font-[600] capitalize ${
    294                             view_display === `photos`
    295                                 ? classes_photo_overlay_glyph_opt_selected
    296                                 : classes_photo_overlay_glyph_opt
    297                         } el-re`}
    298                     >
    299                         {`${$ls(`common.photos`)}`}
    300                     </p>
    301                 </button>
    302                 <button
    303                     class={`flex flex-row justify-center items-center`}
    304                     onclick={async () => {
    305                         view_display = `following`;
    306                     }}
    307                 >
    308                     <p
    309                         class={`font-sans text-[1.1rem] font-[600] capitalize ${
    310                             view_display === `following`
    311                                 ? classes_photo_overlay_glyph_opt_selected
    312                                 : classes_photo_overlay_glyph_opt
    313                         } el-re`}
    314                     >
    315                         {`${$ls(`common.following`)}`}
    316                     </p>
    317                 </button>
    318                 <button
    319                     class={`flex flex-row justify-center items-center`}
    320                     onclick={async () => {
    321                         view_display = `followers`;
    322                     }}
    323                 >
    324                     <p
    325                         class={`font-sans text-[1.1rem] font-[600] capitalize ${
    326                             view_display === `followers`
    327                                 ? classes_photo_overlay_glyph_opt_selected
    328                                 : classes_photo_overlay_glyph_opt
    329                         } el-re`}
    330                     >
    331                         {`${$ls(`common.followers`)}`}
    332                     </p>
    333                 </button>
    334             </div>
    335         </div>
    336     </div>
    337     <div
    338         class={`flex flex-col w-full min-h-[500px] justify-start items-center`}
    339     >
    340         {#if view_display === `photos`}
    341             <p class={`font-sans font-[400] text-ly0-gl`}>
    342                 {view_display}
    343             </p>
    344         {:else if view_display === `following`}
    345             <p class={`font-sans font-[400] text-ly0-gl`}>
    346                 {view_display}
    347             </p>
    348         {:else if view_display === `followers`}
    349             <p class={`font-sans font-[400] text-ly0-gl`}>
    350                 {view_display}
    351             </p>
    352         {/if}
    353     </div>
    354     <NavigationTabs />
    355 {/if}