From d335e4694e5d45f6b273410664622ea1891073c8 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 20 May 2024 15:10:54 -0400
Subject: fixing flash card carousel code organization.  lint fixes.

---
 .../views/collections/CollectionCarouselView.tsx   | 130 ++++++++-------------
 1 file changed, 50 insertions(+), 80 deletions(-)

(limited to 'src/client/views/collections/CollectionCarouselView.tsx')

diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index c3ba04aa8..282ac90fe 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -6,7 +6,7 @@ import { computed, makeObservable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { emptyFunction } from '../../../Utils';
-import { StopEvent, returnFalse, returnOne, returnZero } from '../../../ClientUtils';
+import { StopEvent, returnFalse, returnOne, returnTrue, returnZero } from '../../../ClientUtils';
 import { Doc, Opt } from '../../../fields/Doc';
 import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { DocumentType } from '../../documents/DocumentTypes';
@@ -17,6 +17,8 @@ import { FieldViewProps } from '../nodes/FieldView';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
 import './CollectionCarouselView.scss';
 import { CollectionSubView } from './CollectionSubView';
+import { ContextMenu } from '../ContextMenu';
+import { ContextMenuProps } from '../ContextMenuItem';
 
 @observer
 export class CollectionCarouselView extends CollectionSubView() {
@@ -42,91 +44,49 @@ export class CollectionCarouselView extends CollectionSubView() {
         return this.childLayoutPairs.filter(pair => pair.layout.type !== DocumentType.LINK);
     }
 
+    move = (dir: number) => {
+        const moveToCardWithField = (match: (doc: Doc) => boolean): boolean => {
+            let startInd = (NumCast(this.layoutDoc._carousel_index) + dir) % this.carouselItems.length;
+            while (!match(this.carouselItems?.[startInd].layout) && (startInd + dir + this.carouselItems.length) % this.carouselItems.length !== this.layoutDoc._carousel_index) {
+                startInd = (startInd + dir + this.carouselItems.length) % this.carouselItems.length;
+            }
+            this.layoutDoc._carousel_index = startInd;
+            return match(this.carouselItems?.[startInd].layout);
+        };
+        switch (StrCast(this.layoutDoc.filterOp)) {
+            case 'star':  // go to a flashcard that is starred, skip the ones that aren't
+                if (!moveToCardWithField((doc: Doc) => !!doc[`${this.fieldKey}_star`])) {
+                    this.layoutDoc.filterOp = undefined;  // if there aren't any starred, show all cards
+                }
+                break;
+            case 'practice': // go to a new index that is missed, skip the ones that are correct
+                if (!moveToCardWithField((doc: Doc) => doc[`${this.fieldKey}_missed`] !== 'correct')) {
+                    this.layoutDoc.filterOp = undefined;  // if all of the cards are correct, show all cards and exit practice mode
+
+                    // set all the cards to missed
+                    this.carouselItems.forEach(item => {
+                        item.layout[`${this.fieldKey}_missed`] = undefined;
+                    });
+                }
+                break;
+            default: moveToCardWithField( returnTrue);
+        } // prettier-ignore
+    };
+
     /**
-     * Goes to the next flashcard in the stack and filters
-     * based on the the currently selected option.
+     * Goes to the next Doc in the stack subject to the currently selected filter option.
      */
     advance = (e: React.MouseEvent) => {
         e.stopPropagation();
-        this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) + 1) % this.carouselItems.length;
-        let startInd = this.layoutDoc._carousel_index;
-
-        // if the star filter is selected
-        if (this.layoutDoc.filterOp === 'star') {
-            // go to a flashcard that is starred, skip the ones that aren't
-            while (!this.carouselItems?.[NumCast(startInd)].layout[`${this.fieldKey}_star`] && (startInd + 1) % this.carouselItems.length !== this.layoutDoc._carousel_index) {
-                startInd = (startInd + 1) % this.carouselItems.length;
-            }
-            this.layoutDoc._carousel_index = startInd;
-            // if there aren't any starred, show all cards
-            if (!this.carouselItems?.[NumCast(startInd)].layout[`${this.fieldKey}_star`]) {
-                this.layoutDoc.filterOp = 'all';
-            }
-        }
-
-        // if the practice filter is selected
-        if (this.layoutDoc.filterOp === 'practice') {
-            // go to a new index that is missed, skip the ones that are correct
-            while (this.carouselItems?.[NumCast(startInd)].layout[`${this.fieldKey}_missed`] === 'correct' && (startInd + 1) % this.carouselItems.length !== this.layoutDoc._carousel_index) {
-                startInd = (startInd + 1) % this.carouselItems.length;
-            }
-            this.layoutDoc._carousel_index = startInd;
-
-            // if the user has gone through all of the cards and gotten them all correct, show all cards and exit practice mode
-            if (this.carouselItems?.[NumCast(startInd)].layout[`${this.fieldKey}_missed`] === 'correct') {
-                this.layoutDoc.filterOp = 'all';
-
-                // set all the cards to missed
-                for (let i = 0; i < this.carouselItems.length; i++) {
-                    const curDoc = this.carouselItems?.[NumCast(i)];
-                    curDoc.layout[`${this.fieldKey}_missed`] = undefined;
-                }
-            }
-        }
+        this.move(1);
     };
 
     /**
-     * Goes to the previous flashcard in the stack and filters
-     * based on the the currently selected option.
+     * Goes to the previous Doc in the stack subject to the currently selected filter option.
      */
     goback = (e: React.MouseEvent) => {
         e.stopPropagation();
-        this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) - 1 + this.carouselItems.length) % this.carouselItems.length;
-
-        let startInd = this.layoutDoc._carousel_index;
-
-        // if the star filter is selected
-        if (this.layoutDoc.filterOp === 'star') {
-            // go to a new index that is starred, skip the ones that aren't
-            while (!this.carouselItems?.[NumCast(startInd)].layout[`${this.fieldKey}_star`] && (startInd - 1 + this.carouselItems.length) % this.carouselItems.length !== this.layoutDoc._carousel_index) {
-                startInd = (startInd - 1 + this.carouselItems.length) % this.carouselItems.length;
-            }
-            this.layoutDoc._carousel_index = startInd;
-            // if there aren't any starred, show all cards
-            if (!this.carouselItems?.[NumCast(startInd)].layout[`${this.fieldKey}_star`]) {
-                this.layoutDoc.filterOp = 'all';
-            }
-        }
-
-        // if the practice filter is selected
-        if (this.layoutDoc.filterOp === 'practice') {
-            // go to a new index that is missed, skip the ones that are correct
-            while (this.carouselItems?.[NumCast(startInd)].layout[`${this.fieldKey}_missed`] === 'correct' && (startInd - 1 + this.carouselItems.length) % this.carouselItems.length !== this.layoutDoc._carousel_index) {
-                startInd = (startInd - 1 + this.carouselItems.length) % this.carouselItems.length;
-            }
-
-            this.layoutDoc._carousel_index = startInd;
-
-            // See all flashcards when finish going through practice mode and set all of the flashcards back to
-            if (this.carouselItems?.[NumCast(startInd)].layout[`${this.fieldKey}_missed`] === 'correct') {
-                this.layoutDoc.filterOp = 'all';
-
-                for (let i = 0; i < this.carouselItems.length; i++) {
-                    const curDoc = this.carouselItems?.[NumCast(i)];
-                    curDoc.layout[`${this.fieldKey}_missed`] = undefined;
-                }
-            }
-        }
+        this.move(-1);
     };
 
     /*
@@ -134,10 +94,8 @@ export class CollectionCarouselView extends CollectionSubView() {
      */
     star = (e: React.MouseEvent) => {
         e.stopPropagation();
-        const curDoc = this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)];
-        if (!curDoc) return;
-        if (curDoc.layout[`${this.fieldKey}_star`] === undefined) curDoc.layout[`${this.fieldKey}_star`] = true;
-        else curDoc.layout[`${this.fieldKey}_star`] = !curDoc.layout[`${this.fieldKey}_star`];
+        const curDoc = this.carouselItems[NumCast(this.layoutDoc._carousel_index)];
+        curDoc.layout[`${this.fieldKey}_star`] = curDoc.layout[`${this.fieldKey}_star`] ? undefined : true;
     };
 
     /*
@@ -228,12 +186,24 @@ export class CollectionCarouselView extends CollectionSubView() {
             </>
         );
     }
+    specificMenu = (): void => {
+        const cm = ContextMenu.Instance;
+
+        const revealOptions = cm.findByDescription('Filter Flashcards');
+        const revealItems: ContextMenuProps[] = revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : [];
+        revealItems.push({description: 'All',           event: () => {this.layoutDoc.filterOp = undefined;},  icon: 'layer-group',}); // prettier-ignore
+        revealItems.push({description: 'Star',          event: () => {this.layoutDoc.filterOp = 'star';},     icon: 'star',}); // prettier-ignore
+        revealItems.push({description: 'Practice Mode', event: () => {this.layoutDoc.filterOp = 'practice';}, icon: 'check',}); // prettier-ignore
+        revealItems.push({description: 'Quiz Cards',    event: () => {this.layoutDoc.filterOp = 'quiz';},     icon: 'pencil',}); // prettier-ignore
+        !revealOptions && cm.addItem({ description: 'Filter Flashcards', addDivider: false, noexpand: true, subitems: revealItems, icon: 'layer-group' });
+    };
 
     render() {
         return (
             <div
                 className="collectionCarouselView-outer"
                 ref={this.createDashEventsTarget}
+                onContextMenu={this.specificMenu}
                 style={{
                     background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor),
                     color: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color),
-- 
cgit v1.2.3-70-g09d2

