Notes on enhancements and bugfixes to Bhagavad Gita v1.2 Next.js web app

Last updated on 18th Aug. 2024

Quick Info

Github repo of app: https://github.com/ravisiyer/gita
App deployed at: https://gita-rsi.vercel.app/

Details

Based on responses in above page by nullpromise and drcmda:
Node is used to transpile JSX to (plain) React. One can do React apps. without Node if we don't use JSX. 
'You don't "need" it, but then again, without Node there is no web dev as it is understood today.'
Node Package Manager (npm) is (a popular platform) for developers to share code.

---------

As per above, Chrome limits size of a cookie to 4096 bytes. Typically 300 cookies and 20 cookies per domain.


Should I use one large cookie or few small cookies? I did not get a clear answer from the net.
I think software design wise different cookies for verse page, chapter page and overall app. seems to be logical. Perhaps I should try that approach. ... But it is simpler to store everything in one cookie. So have used that approach at least for the time being.

-----------------

Chapter & Home page settings:
Done: Chapter only: Translator
[Home page and chapter page] Language of title and summary: English, Hindi or both
----
App level:
Consider: Last visited page
Consider: Max. width of chapter and verse pages contents or should it be whole app. excluding home page.

===============
Query to get chapter 1 authorId 16 data.
{
  allGitaChapters(condition: {chapterNumber: 1}) {
    nodes {
      gitaVersesByChapterId {
        nodes {
          gitaTranslationsByVerseId(condition: {authorId: 16}) {
            nodes {
              authorName
              authorId
              description
            }
          }
          text
          transliteration
          wordMeanings
          verseNumber
        }
      }
    }
  }
}

==========
Based on above, I used below code which worked:
export async function getChapter(
  chapterNumber: string,
  authorId: string = "16"
) {
  const client = createApolloClient();
...
--------
I could not get uncontrolled ListBox to work properly for Chapter Translator. The selections made were not in sync with what was highlighted. ... Even regular ListBox with state did not work ... Figured out that using ListboxButton fixed it. Hmm.

=======================

Suggested solutions (checked that it works): 
Use display: inline-block
width: fit-content;
...
Tailwind class: w-fit maps to width: fit-content;
===================

To Do: Fix cursor in author list boxes.
=============

Production app now has chapter page translator selection setting. Version number is changed to Post version 1.2.

=============

How should I store boolean values in cookie? Not sure what the reccommended way is. I decided to simply use boolean data type in the Cookie object which is stringified for saving and parsed when read. It works.

Keyboard up/down in static listbox (AL listboxes) does not seem to work properly ... This post may be related to it: [react] Static Option on Listbox breaks keyboard accessibility #148, https://github.com/tailwindlabs/headlessui/issues/148

===================
Done

Verse page setting:
Done: Added ? to , replacement checkbox option.

Chapter & Home page settings:
Done: Chapter only: Translator
Done:[Home page, chapter summaries and chapter page] Language of title and summary: English, Hindi or both
Note Sanskrit chapter titles are not affected by above as it is Sanskrit and not Hindi.
----

Done: Default Settings needs to include new settings. I think I will be forced to use state variables for all the new settings:
"chapterPageTranslatorAuthorId = DEFAULT_CHAPTER_PAGE_TRANSLATOR_AUTHOR_ID,
  qMarkToCommaChecked = DEFAULT_QMARK_TO_COMMA_VALUE,
  englishLTSChecked = DEFAULT_ENGLISH_LTS_CHECKED,
  hindiLTSChecked = DEFAULT_HINDI_LTS_CHECKED,".
These are passed as props to Settings component by Settings page (which reads it from cookie or uses default) and these props are directly passed as (initial) values for associated props of components like LTS or CPT. The components use state variables to hold these values and intialize it to prop value.

Props (in this case, of Settings component) cannot be changed by event handlers like "Default Settings" button click.

If I use state variables in Settings component for the above, then I should pass that state variable (incl. set method) to underlying components which can use them instead of their own state components.

===========

How to force a component to reset all its state when a prop to the component changes? That is explained in:

I tried it (unique key has to be specified for the component) and it works. My code:
In settings.tsx:
        <ChapterPageTranslatorSelection
            allLanguageTranslatorAuthors={allLanguageTranslatorAuthors}
            selectedAuthorIndex={selectedAuthorIndex}
            name={CHAPTER_PAGE_TRANSLATOR_FIELD_NAME}
            setSelectionChanged={setFormDataModified}
            // Below key results in reset of state of ChapterPageTranslatorSelection component
            // when selectedAuthorIndex changes.
            // Ref: https://react.dev/learn/you-might-not-need-an-effect#resetting-all-state-when-a-prop-changes
            key={selectedAuthorIndex}
          />
----
In ChapterPageTranslatorSelection.tsx:
function ChapterPageTranslatorSelection({
  allLanguageTranslatorAuthors,
  selectedAuthorIndex = 0,
  name,
  setSelectionChanged,
}: {
  allLanguageTranslatorAuthors: languageTranslatorAuthorT[];
  selectedAuthorIndex: number;
  name: string;
  setSelectionChanged: (selectionChanged: boolean) => void;
}) {
  const [
    selectedLanguageTranslatorAuthor,
    setSelectedLanguageTranslatorAuthor,
  ] = useState(allLanguageTranslatorAuthors[selectedAuthorIndex]);
------

Without the key statement in settings.tsx, (it seems) the selectedLanguageTranslatorAuthor state variable does NOT change when a changed selectedAuthorIndex prop is passed to it (after user chooses 'Use default settings'), as the selected entry in the listbox in Settings page does not change. The key statement seems to result in selectedLanguageTranslatorAuthor state variable getting reset and initialized to entry corresponding to selectedAuthorIndex prop, as the selected entry in the listbox in Settings page changes to entry corresponding to selectedAuthorIndex prop.
=========================

I used below code to count number of elements in array that satisfy a condition using filter. It worked:
  const onlyOneLanguageChecked =
    allLanguageOptions.filter(
      (languageOption) => languageOption.languageChecked
    ).length === 1;
===============

When the window is maximized on my desktop and full-width is specified in class (max-w-full) for main element in layout, the hero image was not getting centered. Solution was to wrap the image in a div which uses flex centering. Code I used:
In app/layout.tsx:
        <main
          className={clsx(
            "mx-auto p-2 scroll-mt-16 min-h-[calc(100vh-45px)] bg-yellow-100",
            useFullWidth ? " max-w-full" : " max-w-4xl"
          )}
        >
----
In app/page.tsx:
      <div className="flex justify-center ">
        <Image
          src="/hero-desktop.jpg"
          alt="Hero Image"
          width={896}
          height={538}
          className="hidden md:block"
...
----
Ref: How to centering next/image's <Image>? #18375, https://github.com/vercel/next.js/discussions/18375

Done: Use full width of window option provided in Settings (for whole app).
================

Looked up what is considered good default max-width for app. I am using max-w-4xl (896px, 56rem) (in layout.tsx).

bg-io (gita-frontend-v2) gita app uses max-w-5xl (1024px, 64rem) for 11 page and component files including src\app\chapter\[chapterNumber]\(chapter)\[[...locale]]\ChapterPage.tsx, src\components\Verse\index.tsx . It uses max-w-4xl only for one file: src\components\Headers\ContentModal.tsx .

My-Gita app. uses max-w-5xl for 6 page and component files including chapter and verse related pages/components. It does not use max-w-4xl for any file.

Hmm. I don't know how I decided on using max-w-4xl for my app.
...
In the context of the following articles, it should be noted that my app is a text-heavy content app.
From: Max-Content Width and Other Good Ways to Improve the UX, https://www.newtarget.com/web-insights-blog/max-content-width : "For text-heavy pages, a common maximum width for the main content area is between 800px and 1200px."

What's the recommended max width for the main container and for the main column, for large screens?, https://ux.stackexchange.com/questions/104745/whats-the-recommended-max-width-for-the-main-container-and-for-the-main-column : scunliffe response in Feb. 2017 states that some historical research indicated that content too wide became hard to read, leading to "a standard of 960px". But this is for "reading" width implying that it is for text-heavy content.
...
Decided to use 960px (... earlier code with 4xl is commented ... size is picked up from a constant:
export const MAIN_CONTAINER_MAX_WIDTH_TAILWIND = " max-w-[960px]";
---
... Tested with 960px max-width. Desktop hero image was smaller than 960px width due to 896px related width setting in code. Eventually decided to move to orig res images as I had read somewhere that hero images less than 1 MB were OK to use and the orig res images are < 1 MB. Now width and height settings in code for the hero images are the original res images width and height. App. seems to be working OK.
======

App level:
Considered and decided against, as of now: Last visited page ... If app was having a user registration mechanism and storing data on server, it could have been implemented easily. Storing/updating a cookie on very page visit does not seem to be a good thing to do though I have not searched on this topic. Cookie can be stored on user choosing to save a visited page but that would be similar to browser bookmark with browser bookmark facility being sophisticated. ... Decided to drop this, at least as of now.

Done: Consider home page using full width at all times. Rest of app. can use full width based on Settings selection. ... Solution may need separate layout pages for home page and rest of app.

=======================

VSCode - Show Intellisense shortcut key: Ctrl+Space
VSCode - To automatically enable word wrap: Setting: editor.wordwrap has to be set to "on" instead of default "off". Tried it and it seems to have worked. Ref: How do I turn on text wrapping by default in VS Code, https://stackoverflow.com/questions/38561881/how-do-i-turn-on-text-wrapping-by-default-in-vs-code .

=======

Low priority, to do: Consider having a single base component for QMarkIssueHack and FullWindowWidth (both are single checkboxes).

============
Version 1.3 released. See: Gita web app (Next.js, open source) v1.3: More settings provided and hi-res hero images; Notes for students & self-learners, https://raviswdev.blogspot.com/2024/08/gita-web-app-nextjs-open-source-v13.html .

Comments