@plusscommunities/pluss-feature-builder-web-d 1.0.7 → 1.0.9-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/dist/{index.cjs.js → index.js} +3803 -3504
  2. package/dist/index.js.map +1 -0
  3. package/package.json +20 -27
  4. package/.babelrc +0 -4
  5. package/rollup.config.js +0 -69
  6. package/src/actions/featureBuilderStringsActions.js +0 -88
  7. package/src/actions/featureDefinitionsIndex.js +0 -258
  8. package/src/actions/formActions.js +0 -301
  9. package/src/actions/index.js +0 -12
  10. package/src/actions/listingActions.js +0 -352
  11. package/src/actions/wizardActions.js +0 -228
  12. package/src/components/ActivityCardExample.jsx +0 -86
  13. package/src/components/ActivityCardExample.module.css +0 -130
  14. package/src/components/BackgroundLoader.jsx +0 -33
  15. package/src/components/BackgroundLoader.module.css +0 -46
  16. package/src/components/BaseFieldConfig.jsx +0 -305
  17. package/src/components/BaseFieldConfig.module.css +0 -42
  18. package/src/components/CenteredContainer.jsx +0 -29
  19. package/src/components/CenteredContainer.module.css +0 -171
  20. package/src/components/DeleteConfirmationPopup.jsx +0 -95
  21. package/src/components/DeleteConfirmationPopup.module.css +0 -12
  22. package/src/components/ErrorBoundary.jsx +0 -134
  23. package/src/components/ErrorBoundary.module.css +0 -77
  24. package/src/components/ErrorMessage.jsx +0 -85
  25. package/src/components/ErrorMessage.module.css +0 -116
  26. package/src/components/ExampleDisplay.jsx +0 -26
  27. package/src/components/ExampleDisplay.module.css +0 -3
  28. package/src/components/FeatureBuilderSidebar.jsx +0 -84
  29. package/src/components/FeatureBuilderSuccessPopup.jsx +0 -49
  30. package/src/components/FeatureBuilderSuccessPopup.module.css +0 -41
  31. package/src/components/FeatureBuilderWelcomePopup.jsx +0 -51
  32. package/src/components/FeatureBuilderWelcomePopup.module.css +0 -21
  33. package/src/components/FeatureListingCard.jsx +0 -104
  34. package/src/components/FeatureListingCard.module.css +0 -62
  35. package/src/components/Fields.jsx +0 -423
  36. package/src/components/Fields.module.css +0 -159
  37. package/src/components/IconLoader.jsx +0 -153
  38. package/src/components/IconLoader.module.css +0 -92
  39. package/src/components/IconSelector.jsx +0 -111
  40. package/src/components/IconSelector.module.css +0 -197
  41. package/src/components/ListingEditor.jsx +0 -405
  42. package/src/components/ListingEditor.module.css +0 -14
  43. package/src/components/ListingSuccessPopup.jsx +0 -52
  44. package/src/components/LoadingScreen.jsx +0 -54
  45. package/src/components/LoadingScreen.module.css +0 -103
  46. package/src/components/LoadingState.jsx +0 -40
  47. package/src/components/LoadingState.module.css +0 -18
  48. package/src/components/PreviewFull.js +0 -24
  49. package/src/components/PreviewFull.module.css +0 -11
  50. package/src/components/PreviewGrid.js +0 -14
  51. package/src/components/PreviewWidget.js +0 -27
  52. package/src/components/PreviewWidget.module.css +0 -15
  53. package/src/components/SidebarLayout.jsx +0 -252
  54. package/src/components/SidebarLayout.module.css +0 -71
  55. package/src/components/SkeletonLoader.jsx +0 -128
  56. package/src/components/SkeletonLoader.module.css +0 -295
  57. package/src/components/SortButtonGroup.jsx +0 -34
  58. package/src/components/SortButtonGroup.module.css +0 -51
  59. package/src/components/ToastContainer.jsx +0 -98
  60. package/src/components/ToastContainer.module.css +0 -156
  61. package/src/components/ToggleSwitch.js +0 -40
  62. package/src/components/ToggleSwitch.module.css +0 -48
  63. package/src/components/TwoColumnInput.jsx +0 -29
  64. package/src/components/TwoColumnInput.module.css +0 -32
  65. package/src/components/ViewFull.js +0 -139
  66. package/src/components/ViewFull.module.css +0 -71
  67. package/src/components/ViewWidget.js +0 -62
  68. package/src/components/ViewWidget.module.css +0 -28
  69. package/src/components/iconCategories.js +0 -135
  70. package/src/components/iconImports.js +0 -409
  71. package/src/components/index.js +0 -59
  72. package/src/components/listing/FileListItem.jsx +0 -86
  73. package/src/components/listing/GalleryDisplay.jsx +0 -330
  74. package/src/components/listing/GalleryDisplay.module.css +0 -309
  75. package/src/components/listing/ListingCTAInput.jsx +0 -82
  76. package/src/components/listing/ListingDescriptionInput.jsx +0 -73
  77. package/src/components/listing/ListingField.jsx +0 -101
  78. package/src/components/listing/ListingField.module.css +0 -106
  79. package/src/components/listing/ListingFileInput.jsx +0 -273
  80. package/src/components/listing/ListingFileInput.module.css +0 -189
  81. package/src/components/listing/ListingForm.jsx +0 -90
  82. package/src/components/listing/ListingForm.module.css +0 -38
  83. package/src/components/listing/ListingGalleryInput.jsx +0 -239
  84. package/src/components/listing/ListingGalleryInput.module.css +0 -132
  85. package/src/components/listing/ListingImageInput.jsx +0 -153
  86. package/src/components/listing/ListingTextInput.jsx +0 -72
  87. package/src/feature.config.js +0 -130
  88. package/src/helper/index.js +0 -135
  89. package/src/hooks/useFeatureDefinitionLoader.js +0 -66
  90. package/src/images/full.png +0 -0
  91. package/src/images/fullNoTitle.png +0 -0
  92. package/src/images/previewWidget.png +0 -0
  93. package/src/images/widget.png +0 -0
  94. package/src/index.js +0 -38
  95. package/src/pages/CreateListingPage.jsx +0 -49
  96. package/src/pages/EditListingPage.jsx +0 -58
  97. package/src/reducers/featureBuilderReducer.js +0 -739
  98. package/src/screens/CreateListing.module.css +0 -45
  99. package/src/screens/Form.module.css +0 -744
  100. package/src/screens/FormFieldsStep.jsx +0 -626
  101. package/src/screens/FormLayoutStep.jsx +0 -405
  102. package/src/screens/FormOverviewStep.jsx +0 -389
  103. package/src/screens/ListingScreen.jsx +0 -477
  104. package/src/screens/ListingScreen.module.css +0 -333
  105. package/src/selectors/featureBuilderSelectors.js +0 -533
  106. package/src/types/index.js +0 -91
  107. package/src/utils/textUtils.js +0 -89
  108. package/src/validators/galleryValidators.js +0 -345
  109. package/src/values.config.a.js +0 -49
  110. package/src/values.config.b.js +0 -49
  111. package/src/values.config.c.js +0 -49
  112. package/src/values.config.d.js +0 -49
  113. package/src/values.config.default.js +0 -49
  114. package/src/values.config.js +0 -49
  115. package/src/webapi/featureDefinitionActions.js +0 -0
  116. package/src/webapi/featuresActions.js +0 -90
  117. package/src/webapi/helper.js +0 -4
  118. package/src/webapi/index.js +0 -12
  119. package/src/webapi/listingActions.js +0 -176
@@ -1,29 +0,0 @@
1
- import React from "react";
2
- import styles from "./TwoColumnInput.module.css";
3
-
4
- /**
5
- * Two Column Input layout component
6
- * Renders form inputs in a side-by-side layout with proper spacing and styling
7
- * Commonly used for label/placeholder pairs or related input fields
8
- *
9
- * @param {Object} props - Component props
10
- * @param {React.ReactNode} props.left - Content for the left column (typically a form input)
11
- * @param {React.ReactNode} props.right - Content for the right column (typically a form input)
12
- * @param {boolean} [props.leftRequired=false] - Whether left column content is required
13
- * @returns {React.ReactElement} Two-column layout wrapper
14
- *
15
- * @example
16
- * <TwoColumnInput
17
- * left={<GenericInput label="First Name" />}
18
- * right={<GenericInput label="Last Name" />}
19
- * leftRequired={true}
20
- * />
21
- */
22
- export const TwoColumnInput = ({ left, right, leftRequired = false }) => {
23
- return (
24
- <div className={styles.twoColumnInput}>
25
- <div className={`${styles.column} ${styles.leftColumn}`}>{left}</div>
26
- <div className={`${styles.column} ${styles.rightColumn}`}>{right}</div>
27
- </div>
28
- );
29
- };
@@ -1,32 +0,0 @@
1
- /* TwoColumnInput BEM CSS Module */
2
-
3
- .twoColumnInput {
4
- display: flex;
5
- gap: 20px;
6
- align-items: center;
7
- }
8
-
9
- .column {
10
- flex: 1;
11
- }
12
-
13
- .leftColumn {
14
- flex: 1.2; /* Slightly wider for required label */
15
- }
16
-
17
- .rightColumn {
18
- flex: 1;
19
- }
20
-
21
- /* Responsive adjustments */
22
- @media (max-width: 768px) {
23
- .twoColumnInput {
24
- flex-direction: column;
25
- gap: 12px;
26
- }
27
-
28
- .leftColumn,
29
- .rightColumn {
30
- flex: 1;
31
- }
32
- }
@@ -1,139 +0,0 @@
1
- import React from "react";
2
- import { PlussCore } from "../feature.config";
3
- const { Text, Button } = PlussCore.Components;
4
- import full from "../images/full.png";
5
- import styles from "./ViewFull.module.css";
6
-
7
- const ViewFull = ({ listing }) => {
8
- // If no listing data provided, show placeholder
9
- if (!listing || !listing.fields) {
10
- return <img className={styles.viewFull__image} src={full} alt="full" />;
11
- }
12
-
13
- // Get the title field
14
- const title = listing.fields["mandatory-title"] || "Untitled";
15
-
16
- // Find all CTA fields
17
- const ctaFields = Object.keys(listing.fields).filter((fieldId) => {
18
- const fieldValue = listing.fields[fieldId];
19
- return (
20
- fieldValue &&
21
- typeof fieldValue === "object" &&
22
- fieldValue.label &&
23
- fieldValue.url
24
- );
25
- });
26
-
27
- // Find all text fields
28
- const textFields = Object.keys(listing.fields)
29
- .filter((fieldId) => {
30
- const fieldValue = listing.fields[fieldId];
31
- return typeof fieldValue === "string" && fieldValue.length > 0;
32
- })
33
- .filter((fieldId) => fieldId !== "mandatory-title"); // Exclude title field
34
-
35
- // Find all image fields
36
- const imageFields = Object.keys(listing.fields).filter((fieldId) => {
37
- const fieldValue = listing.fields[fieldId];
38
- return typeof fieldValue === "string" && fieldValue.startsWith("https://");
39
- });
40
-
41
- // Find all file fields
42
- const fileFields = Object.keys(listing.fields).filter((fieldId) => {
43
- const fieldValue = listing.fields[fieldId];
44
- // Handle both single file object and array of files
45
- if (Array.isArray(fieldValue)) {
46
- return fieldValue.length > 0 && fieldValue.some((f) => f.url && !f.label);
47
- } else if (fieldValue && typeof fieldValue === "object") {
48
- return fieldValue.url && !fieldValue.label; // Not a CTA field (CTA has both url and label)
49
- }
50
- return false;
51
- });
52
-
53
- // Helper function to normalize file data
54
- const normalizeFiles = (fileData) => {
55
- if (Array.isArray(fileData)) {
56
- return fileData.filter((f) => f && f.url && !f.label);
57
- } else if (
58
- fileData &&
59
- typeof fileData === "object" &&
60
- fileData.url &&
61
- !fileData.label
62
- ) {
63
- return [fileData];
64
- }
65
- return [];
66
- };
67
-
68
- return (
69
- <div className={styles.viewFull}>
70
- {/* Title */}
71
- <Text type="h2" className={styles.viewFull__title}>
72
- {title}
73
- </Text>
74
-
75
- {/* Image fields */}
76
- {imageFields.map((fieldId) => (
77
- <div key={fieldId} className={styles.viewFull__imageContainer}>
78
- <img
79
- src={listing.fields[fieldId]}
80
- alt={fieldId}
81
- className={styles.viewFull__imageField}
82
- />
83
- </div>
84
- ))}
85
-
86
- {/* Text fields */}
87
- {textFields.map((fieldId) => (
88
- <Text key={fieldId} type="body" className={styles.viewFull__textField}>
89
- {listing.fields[fieldId]}
90
- </Text>
91
- ))}
92
-
93
- {/* File fields */}
94
- {fileFields.map((fieldId) => {
95
- const files = normalizeFiles(listing.fields[fieldId]);
96
- return (
97
- <div key={fieldId} className={styles.viewFull__fileSection}>
98
- {files.map((file, index) => (
99
- <div
100
- key={`${fieldId}-${index}`}
101
- className={styles.viewFull__fileItem}
102
- >
103
- <a
104
- href={file.url}
105
- target="_blank"
106
- rel="noopener noreferrer"
107
- className={styles.viewFull__fileLink}
108
- >
109
- <Text type="body" className={styles.viewFull__fileName}>
110
- {file.name || file.originalName}
111
- </Text>
112
- </a>
113
- </div>
114
- ))}
115
- </div>
116
- );
117
- })}
118
-
119
- {/* CTA fields */}
120
- {ctaFields.map((fieldId) => {
121
- const ctaField = listing.fields[fieldId];
122
- return (
123
- <Button
124
- key={fieldId}
125
- buttonType="primary"
126
- onClick={() => {
127
- window.open(ctaField.url, "_blank", "noopener,noreferrer");
128
- }}
129
- className={styles.viewFull__ctaButton}
130
- >
131
- {ctaField.label}
132
- </Button>
133
- );
134
- })}
135
- </div>
136
- );
137
- };
138
-
139
- export default ViewFull;
@@ -1,71 +0,0 @@
1
- /* ViewFull BEM CSS Module */
2
-
3
- /* Block */
4
- .viewFull {
5
- padding: 20px;
6
- }
7
-
8
- /* Elements */
9
- .viewFull__image {
10
- width: 100%;
11
- height: 100%;
12
- object-fit: contain;
13
- }
14
-
15
- .viewFull__title {
16
- margin-bottom: 20px;
17
- }
18
-
19
- .viewFull__imageContainer {
20
- margin-bottom: 20px;
21
- text-align: center;
22
- }
23
-
24
- .viewFull__imageField {
25
- max-width: 100%;
26
- max-height: 300px;
27
- object-fit: contain;
28
- }
29
-
30
- .viewFull__textField {
31
- margin-bottom: 12px;
32
- line-height: 1.4;
33
- }
34
-
35
- .viewFull__fileSection {
36
- margin-bottom: 20px;
37
- }
38
-
39
- .viewFull__fileItem {
40
- margin-bottom: 8px;
41
- padding: 12px;
42
- border: 1px solid var(--border-line-grey);
43
- border-radius: 4px;
44
- background-color: #fff;
45
- transition: all 0.2s ease-in-out;
46
- }
47
-
48
- .viewFull__fileItem:hover {
49
- border-color: var(--colour-branding-action);
50
- box-shadow: 0 0 4px var(--colour-branding-action-alpha20);
51
- }
52
-
53
- .viewFull__fileLink {
54
- text-decoration: none;
55
- color: var(--text-dark);
56
- display: flex;
57
- align-items: center;
58
- }
59
-
60
- .viewFull__fileLink:hover {
61
- color: var(--colour-branding-action);
62
- }
63
-
64
- .viewFull__fileName {
65
- font-weight: 500;
66
- }
67
-
68
- .viewFull__ctaButton {
69
- margin-top: 20px;
70
- margin-right: 10px;
71
- }
@@ -1,62 +0,0 @@
1
- import React from "react";
2
- import { PlussCore } from "../feature.config";
3
- const { Text, Button } = PlussCore.Components;
4
- import widget from "../images/widget.png";
5
- import styles from "./ViewWidget.module.css";
6
-
7
- const ViewWidget = ({ listing }) => {
8
- // If no listing data provided, show placeholder
9
- if (!listing || !listing.fields) {
10
- return <img className={styles.image} src={widget} alt="widget" />;
11
- }
12
-
13
- // Get the title field
14
- const title = listing.fields["mandatory-title"] || "Untitled";
15
-
16
- // Find all CTA fields and render the first one
17
- const ctaFields = Object.keys(listing.fields).filter((fieldId) => {
18
- // Check if field value has label and url (CTA structure)
19
- const fieldValue = listing.fields[fieldId];
20
- return (
21
- fieldValue &&
22
- typeof fieldValue === "object" &&
23
- fieldValue.label &&
24
- fieldValue.url
25
- );
26
- });
27
-
28
- // If no CTA fields, just show title
29
- if (ctaFields.length === 0) {
30
- return (
31
- <div className={styles.root}>
32
- <Text type="body" className={styles.title}>
33
- {title}
34
- </Text>
35
- </div>
36
- );
37
- }
38
-
39
- // Render CTA button
40
- const ctaFieldId = ctaFields[0];
41
- const ctaField = listing.fields[ctaFieldId];
42
-
43
- return (
44
- <div className={styles.root}>
45
- <Text type="body" className={styles.title}>
46
- {title}
47
- </Text>
48
- <Button
49
- buttonType="primary"
50
- onClick={() => {
51
- // Open URL in new window
52
- window.open(ctaField.url, "_blank", "noopener,noreferrer");
53
- }}
54
- className={styles.ctaButton}
55
- >
56
- {ctaField.label}
57
- </Button>
58
- </div>
59
- );
60
- };
61
-
62
- export default ViewWidget;
@@ -1,28 +0,0 @@
1
- /* ViewWidget CSS Module */
2
-
3
- /* Block */
4
- .root {
5
- padding: 8px;
6
- text-align: center;
7
- min-height: 80px;
8
- display: flex;
9
- flex-direction: column;
10
- justify-content: center;
11
- align-items: center;
12
- }
13
-
14
- /* Elements */
15
- .image {
16
- width: 80px;
17
- }
18
-
19
- .title {
20
- font-size: 12px;
21
- margin-bottom: 8px;
22
- }
23
-
24
- .ctaButton {
25
- font-size: 11px;
26
- padding: 4px 8px;
27
- min-width: auto;
28
- }
@@ -1,135 +0,0 @@
1
- /*
2
- * Icon categories and definitions for the feature builder
3
- * Curated for retirement village community management
4
- * All icons are compatible with Font Awesome 6.4.0 (plugin) and 4.7.0 (main app)
5
- */
6
- export const iconCategories = [
7
- {
8
- name: "Community & Living",
9
- icons: [
10
- "home",
11
- "users",
12
- "user",
13
- "heart",
14
- "star",
15
- "flag",
16
- "hands-helping",
17
- "handshake",
18
- "people-carry",
19
- "child",
20
- ],
21
- },
22
- {
23
- name: "Household & Comfort",
24
- icons: [
25
- "couch",
26
- "bed",
27
- "tv",
28
- "bath",
29
- "shower",
30
- "toilet",
31
- "sink",
32
- "chair",
33
- "table",
34
- "fire",
35
- "fan",
36
- "temperature-high",
37
- ],
38
- },
39
- {
40
- name: "Health & Wellness",
41
- icons: [
42
- "shield",
43
- "heart",
44
- "user-nurse",
45
- "stethoscope",
46
- "heart-pulse",
47
- "wheelchair",
48
- "crutch",
49
- "prescription-bottle",
50
- "pills",
51
- "syringe",
52
- "thermometer",
53
- ],
54
- },
55
- {
56
- name: "Activities & Events",
57
- icons: [
58
- "calendar",
59
- "clock",
60
- "bell",
61
- "music",
62
- "book",
63
- "image",
64
- "camera",
65
- "chess",
66
- "dice",
67
- "theater-masks",
68
- "palette",
69
- "graduation-cap",
70
- "trophy",
71
- ],
72
- },
73
- {
74
- name: "Sports & Recreation",
75
- icons: [
76
- "basketball-ball",
77
- "football-ball",
78
- "volleyball-ball",
79
- "table-tennis",
80
- "bowling-ball",
81
- "swimming-pool",
82
- "bicycle",
83
- "walking",
84
- "hiking",
85
- "umbrella-beach",
86
- ],
87
- },
88
- {
89
- name: "Dining & Food",
90
- icons: [
91
- "utensils",
92
- "coffee",
93
- "wine-glass",
94
- "glass-water",
95
- "pizza-slice",
96
- "apple-alt",
97
- "carrot",
98
- "bread-slice",
99
- "ice-cream",
100
- "cocktail",
101
- ],
102
- },
103
- {
104
- name: "Transportation",
105
- icons: ["car", "bus", "train", "bicycle", "truck"],
106
- },
107
- {
108
- name: "Files & Information",
109
- icons: ["file", "file-lines", "folder", "book-open", "clipboard"],
110
- },
111
- {
112
- name: "Communication",
113
- icons: ["phone", "envelope", "map-marker", "location-dot"],
114
- },
115
- {
116
- name: "Garden & Outdoor",
117
- icons: ["tree", "leaf", "seedling", "sun", "cloud-sun", "bug"],
118
- },
119
- {
120
- name: "Maintenance & Safety",
121
- icons: ["wrench", "hammer", "tools", "lock"],
122
- },
123
- ];
124
-
125
- // Flatten all icons for easy iteration, removing duplicates
126
- export const allIcons = [
127
- ...new Set(
128
- iconCategories.reduce((acc, category) => {
129
- return [...acc, ...category.icons];
130
- }, []),
131
- ),
132
- ];
133
-
134
- // Default icons for current selection
135
- export const defaultIcon = "star";