fansunited-frontend-components 0.0.23-RC1 → 0.0.23-RC3

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 (3) hide show
  1. package/README.md +464 -81
  2. package/components.js +34681 -29499
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -152,7 +152,7 @@ const themeOptions: CustomThemeOptions = {
152
152
  softBg: "#042F04",
153
153
  },
154
154
  danger: {
155
- softBg: "#FEE4E2",
155
+ softBg: "#430A0A",
156
156
  plainColor: "#F44336",
157
157
  outlinedBorder: "#F44336",
158
158
  },
@@ -267,10 +267,11 @@ import { LeadsOptions } from "fansunited-frontend-core";
267
267
 
268
268
  const leads: LeadsOptions = {
269
269
  position: "before", // "before" | "after"
270
- fields: ["fullName"], // | "fullName" | "firstName" | "lastName" | "email" | "gender" | "country" | "phoneCountryCode" | "phoneNumber";
270
+ fields: ["fullName"], // Available: "fullName" | "firstName" | "lastName" | "email" | "gender" | "country" | "phoneCountryCode" | "phoneNumber"
271
271
  campaignId: "test-quizzes",
272
272
  campaignName: "Test Quizzes",
273
273
  phoneCountryCode: "359", // When not provided will set the phone country code from component language prop. So for example if the language is "bg" and phoneCountryCode is not provided, it will fallback to "359"
274
+ syncWithProfile: true, // Optional: sync form data to user profile after successful submission
274
275
  };
275
276
 
276
277
  <ClassicQuizPlay {...otherProps} leads={leads} />;
@@ -289,26 +290,26 @@ const signInCTA: SignInCTADetails = {
289
290
  onClick: () => {
290
291
  // Handle sign-in logic
291
292
  console.log("Sign in clicked");
292
- }
293
+ },
293
294
  };
294
295
 
295
296
  // Sign-in with URL navigation
296
297
  const signInCTA: SignInCTADetails = {
297
298
  defaultLabel: "Login",
298
299
  url: "https://your-auth-provider.com/login",
299
- target: "_blank" // or "_self"
300
+ target: "_blank", // or "_self"
300
301
  };
301
302
 
302
303
  // Custom sign-in component
303
304
  const signInCTA: SignInCTADetails = {
304
- component: <CustomSignInButton />
305
+ component: <CustomSignInButton />,
305
306
  };
306
307
 
307
308
  <ClassicQuizPlay
308
309
  {...otherProps}
309
310
  userIsLoggedIn={false}
310
311
  signInCTA={signInCTA}
311
- />
312
+ />;
312
313
  ```
313
314
 
314
315
  **Sign-in Priority Order:**
@@ -381,6 +382,7 @@ import { WidgetTemplate } from "fansunited-frontend-core";
381
382
  }}
382
383
  leads={{
383
384
  phoneCountryCode: "44",
385
+ syncWithProfile: true,
384
386
  }}
385
387
  />
386
388
  ```
@@ -390,6 +392,7 @@ import { WidgetTemplate } from "fansunited-frontend-core";
390
392
  Interactive poll voting component with real-time results, multiple choice support, and customizable templates. Perfect for engaging audiences with opinion polls, surveys, and voting campaigns.
391
393
 
392
394
  **Key Features:**
395
+
393
396
  - Single and multiple choice voting
394
397
  - Real-time vote results and percentages
395
398
  - Three responsive templates (Standard, Split, Overlay)
@@ -453,7 +456,7 @@ import { SignInCTADetails } from "fansunited-frontend-core";
453
456
 
454
457
  // Custom sign-in component
455
458
  const signInCTA: SignInCTADetails = {
456
- component: <CustomSignInButton />
459
+ component: <CustomSignInButton />,
457
460
  };
458
461
 
459
462
  // Basic sign-in with onClick handler
@@ -462,21 +465,17 @@ const signInCTA: SignInCTADetails = {
462
465
  onClick: () => {
463
466
  // Handle sign-in logic
464
467
  console.log("Sign in clicked");
465
- }
468
+ },
466
469
  };
467
470
 
468
471
  // Sign-in with URL navigation
469
472
  const signInCTA: SignInCTADetails = {
470
473
  defaultLabel: "Login to participate",
471
474
  url: "https://your-auth-provider.com/login",
472
- target: "_blank"
475
+ target: "_blank",
473
476
  };
474
477
 
475
- <PollVote
476
- {...otherProps}
477
- userIsLoggedIn={false}
478
- signInCTA={signInCTA}
479
- />
478
+ <PollVote {...otherProps} userIsLoggedIn={false} signInCTA={signInCTA} />;
480
479
  ```
481
480
 
482
481
  **Sign-in Priority Order:**
@@ -503,11 +502,44 @@ const leads: LeadsOptions = {
503
502
  campaignId: "poll-campaign-2024",
504
503
  campaignName: "User Opinion Poll",
505
504
  phoneCountryCode: "44", // Default country code for phone fields
505
+ syncWithProfile: true, // Optional: sync form data to user profile after successful submission
506
506
  };
507
507
 
508
508
  <PollVote {...otherProps} leads={leads} />;
509
509
  ```
510
510
 
511
+ #### Profile Sync
512
+
513
+ When `syncWithProfile` is enabled in the leads configuration, form data will be automatically synced to the user's profile after successful submission:
514
+
515
+ ```tsx
516
+ import { LeadsOptions } from "fansunited-frontend-core";
517
+
518
+ const leads: LeadsOptions = {
519
+ position: "after",
520
+ fields: ["firstName", "lastName", "email", "phoneNumber", "country"],
521
+ campaignId: "user-profile-sync",
522
+ campaignName: "Profile Sync Campaign",
523
+ syncWithProfile: true, // Enable profile synchronization
524
+ };
525
+
526
+ <PollVote {...otherProps} leads={leads} />
527
+ ```
528
+
529
+ **How it works:**
530
+
531
+ - Only fields that are both **included in the form configuration** AND **have non-empty values** will be synced
532
+ - Supported fields: `fullName`, `firstName`, `lastName`, `email`, `phoneNumber`, `phoneCountryCode`, `country`, `gender`
533
+ - Uses the SDK profile namespace: `sdk.profile.getOwn().setName().setEmail()...update()`
534
+ - Profile sync failures are logged but don't break the lead collection flow
535
+ - Sync happens automatically after successful lead form submission
536
+
537
+ **Name Field Priority:**
538
+ - If `fullName` is configured and has a value, it takes priority for the profile name
539
+ - If both `firstName` and `lastName` are configured and have values, they are combined: `"firstName lastName"`
540
+ - If only `firstName` is configured and has a value, it becomes the profile name
541
+ - If only `lastName` is configured and has a value, it becomes the profile name
542
+
511
543
  #### Examples
512
544
 
513
545
  ##### Basic Poll
@@ -543,6 +575,7 @@ import { WidgetTemplate } from "fansunited-frontend-core";
543
575
  campaignId: "poll-campaign",
544
576
  campaignName: "User Survey 2024",
545
577
  phoneCountryCode: "44",
578
+ syncWithProfile: true,
546
579
  }}
547
580
  themeOptions={{
548
581
  mode: "dark",
@@ -555,6 +588,7 @@ import { WidgetTemplate } from "fansunited-frontend-core";
555
588
  Lead collection component for capturing user information with customizable forms, branding, and success actions. Perfect for newsletter signups, contact forms, and user registration flows.
556
589
 
557
590
  **Key Features:**
591
+
558
592
  - Customizable form fields (name, email, phone, country, gender, custom fields)
559
593
  - Consent management and privacy policy integration
560
594
  - Custom branding and theming support
@@ -565,30 +599,31 @@ Lead collection component for capturing user information with customizable forms
565
599
 
566
600
  #### Required Props
567
601
 
568
- | Prop | Type | Description |
569
- | ---------- | -------------------- | ------------------------------ |
602
+ | Prop | Type | Description |
603
+ | ---------- | -------------------- | ------------------------------- |
570
604
  | `entityId` | `string` | Lead collection form identifier |
571
- | `sdk` | `FansUnitedSDKModel` | SDK instance |
572
- | `template` | `WidgetTemplate` | Layout template |
573
- | `language` | `LanguageType` | Display language |
605
+ | `sdk` | `FansUnitedSDKModel` | SDK instance |
606
+ | `template` | `WidgetTemplate` | Layout template |
607
+ | `language` | `LanguageType` | Display language |
574
608
 
575
609
  #### Optional Props
576
610
 
577
- | Prop | Type | Description |
578
- | ---------------------------- | ----------------------- | ------------------------------------------- |
579
- | `themeOptions` | `CustomThemeOptions` | Theme configuration |
580
- | `fields` | `LeadField[]` | Form fields to display |
581
- | `labels` | `LeadLabels` | Custom labels for form elements |
582
- | `imagePosition` | `"left" \| "right"` | Image position (STANDARD template only) |
583
- | `defaultImagePlaceholderUrl` | `string` | URL for default image placeholder |
584
- | `phoneCountryCode` | `string` | Default country code for phone fields |
585
- | `onSuccessCTA` | `OnSuccessCTADetails` | Success page call to action configuration |
586
- | `customFields` | `LeadCustomField[]` | Additional custom form fields |
587
- | `consents` | `LeadConsent[]` | Consent checkboxes for privacy compliance |
588
- | `content` | `ContentInfo` | Content metadata |
589
- | `campaign` | `CampaignInfo` | Campaign information |
590
- | `branding` | `BrandingInfo` | Branding configuration |
591
- | `images` | `ImagesModel` | Image assets |
611
+ | Prop | Type | Description |
612
+ | ---------------------------- | --------------------- | ----------------------------------------- |
613
+ | `themeOptions` | `CustomThemeOptions` | Theme configuration |
614
+ | `fields` | `LeadField[]` | Form fields to display |
615
+ | `labels` | `LeadLabels` | Custom labels for form elements |
616
+ | `imagePosition` | `"left" \| "right"` | Image position (STANDARD template only) |
617
+ | `defaultImagePlaceholderUrl` | `string` | URL for default image placeholder |
618
+ | `phoneCountryCode` | `string` | Default country code for phone fields |
619
+ | `syncWithProfile` | `boolean` | Sync form data to user profile after successful submission |
620
+ | `onSuccessCTA` | `OnSuccessCTADetails` | Success page call to action configuration |
621
+ | `customFields` | `LeadCustomField[]` | Additional custom form fields |
622
+ | `consents` | `LeadConsent[]` | Consent checkboxes for privacy compliance |
623
+ | `content` | `ContentInfo` | Content metadata |
624
+ | `campaign` | `CampaignInfo` | Campaign information |
625
+ | `branding` | `BrandingInfo` | Branding configuration |
626
+ | `images` | `ImagesModel` | Image assets |
592
627
 
593
628
  #### Templates
594
629
 
@@ -621,7 +656,11 @@ const overlayProps: CollectLeadProps = {
621
656
  Configure which fields to display and their behavior:
622
657
 
623
658
  ```tsx
624
- import { LeadField, LeadCustomField, LeadConsent } from "fansunited-frontend-core";
659
+ import {
660
+ LeadField,
661
+ LeadCustomField,
662
+ LeadConsent,
663
+ } from "fansunited-frontend-core";
625
664
 
626
665
  // Standard form fields
627
666
  const fields: LeadField[] = [
@@ -629,7 +668,7 @@ const fields: LeadField[] = [
629
668
  "email",
630
669
  "phoneNumber",
631
670
  "country",
632
- "gender"
671
+ "gender",
633
672
  ];
634
673
 
635
674
  // Custom fields for additional data collection
@@ -639,27 +678,27 @@ const customFields: LeadCustomField[] = [
639
678
  label: "Company Name",
640
679
  type: "input",
641
680
  required: true,
642
- placeholder: "Enter your company name"
681
+ placeholder: "Enter your company name",
643
682
  },
644
683
  {
645
684
  key: "message",
646
685
  label: "Message",
647
686
  type: "textarea",
648
687
  required: false,
649
- placeholder: "Tell us about your needs..."
650
- }
688
+ placeholder: "Tell us about your needs...",
689
+ },
651
690
  ];
652
691
 
653
692
  // Consent checkboxes for privacy compliance
654
693
  const consents: LeadConsent[] = [
655
694
  {
656
695
  id: "marketing",
657
- label: "I agree to receive marketing communications"
696
+ label: "I agree to receive marketing communications",
658
697
  },
659
698
  {
660
699
  id: "newsletter",
661
- label: "Subscribe to our newsletter"
662
- }
700
+ label: "Subscribe to our newsletter",
701
+ },
663
702
  ];
664
703
 
665
704
  <CollectLead
@@ -667,7 +706,7 @@ const consents: LeadConsent[] = [
667
706
  fields={fields}
668
707
  customFields={customFields}
669
708
  consents={consents}
670
- />
709
+ />;
671
710
  ```
672
711
 
673
712
  #### Custom Labels
@@ -693,13 +732,14 @@ const labels: LeadLabels = {
693
732
  formPhoneNumberPlaceholder: "Enter your phone number",
694
733
  submitButtonLabel: "Subscribe Now",
695
734
  successTitle: "Welcome Aboard!",
696
- successDescription: "Thank you for joining our community. Check your email for next steps.",
735
+ successDescription:
736
+ "Thank you for joining our community. Check your email for next steps.",
697
737
  privacyPolicyUrlLabel: "Privacy Policy",
698
738
  termsAndConditionsUrlLabel: "Terms & Conditions",
699
- presentedByLabel: "Powered by"
739
+ presentedByLabel: "Powered by",
700
740
  };
701
741
 
702
- <CollectLead {...otherProps} labels={labels} />
742
+ <CollectLead {...otherProps} labels={labels} />;
703
743
  ```
704
744
 
705
745
  #### Success Actions
@@ -715,24 +755,65 @@ const onSuccessCTA: OnSuccessCTADetails = {
715
755
  onClick: () => {
716
756
  // Handle post-submission logic
717
757
  window.location.href = "/dashboard";
718
- }
758
+ },
719
759
  };
720
760
 
721
761
  // Success action with URL navigation
722
762
  const onSuccessCTA: OnSuccessCTADetails = {
723
763
  defaultLabel: "Visit Our Website",
724
764
  url: "https://your-website.com",
725
- target: "_blank"
765
+ target: "_blank",
726
766
  };
727
767
 
728
768
  // Custom success component
729
769
  const onSuccessCTA: OnSuccessCTADetails = {
730
- component: <CustomSuccessButton />
770
+ component: <CustomSuccessButton />,
731
771
  };
732
772
 
733
- <CollectLead {...otherProps} onSuccessCTA={onSuccessCTA} />
773
+ <CollectLead {...otherProps} onSuccessCTA={onSuccessCTA} />;
734
774
  ```
735
775
 
776
+ #### Profile Sync
777
+
778
+ Enable automatic profile synchronization to update user profiles with form data:
779
+
780
+ ```tsx
781
+ <CollectLead
782
+ entityId="lead-form-123"
783
+ sdk={sdkInstance}
784
+ template={WidgetTemplate.STANDARD}
785
+ language="en"
786
+ fields={["firstName", "lastName", "email", "phoneNumber", "country", "gender"]}
787
+ syncWithProfile={true} // Enable profile synchronization
788
+ labels={{
789
+ title: "Update Your Profile",
790
+ submitButtonLabel: "Save & Update Profile",
791
+ }}
792
+ />
793
+ ```
794
+
795
+ **Profile Sync Features:**
796
+
797
+ - **Automatic Sync**: Form data is automatically synced to the user's profile after successful submission
798
+ - **Field Mapping**: Only configured fields with non-empty values are synced to the profile
799
+ - **Supported Fields**: `fullName`, `firstName`, `lastName`, `email`, `phoneNumber`, `phoneCountryCode`, `country`, `gender`
800
+ - **SDK Integration**: Uses the profile builder pattern: `sdk.profile.getOwn().setName().setEmail()...update()`
801
+ - **Error Handling**: Profile sync failures are logged but don't prevent lead collection
802
+ - **Optional**: Defaults to `false`, completely opt-in behavior
803
+
804
+ **Name Field Handling:**
805
+ - **Priority 1**: `fullName` (if configured and has value) → sets profile name directly
806
+ - **Priority 2**: `firstName` + `lastName` (if both configured and have values) → combined as `"firstName lastName"`
807
+ - **Priority 3**: `firstName` only (if configured and has value) → sets profile name
808
+ - **Priority 4**: `lastName` only (if configured and has value) → sets profile name
809
+
810
+ **Use Cases:**
811
+
812
+ - User registration forms that also update profiles
813
+ - Newsletter signups that capture additional profile information
814
+ - Contact forms that enhance user profiles with new data
815
+ - Profile update forms with lead tracking
816
+
736
817
  #### Examples
737
818
 
738
819
  ##### Basic Lead Form
@@ -747,7 +828,7 @@ import { WidgetTemplate } from "fansunited-frontend-core";
747
828
  template={WidgetTemplate.STANDARD}
748
829
  language="en"
749
830
  fields={["fullName", "email"]}
750
- />
831
+ />;
751
832
  ```
752
833
 
753
834
  ##### Advanced Lead Form
@@ -760,33 +841,34 @@ import { WidgetTemplate } from "fansunited-frontend-core";
760
841
  language="en"
761
842
  fields={["fullName", "email", "phoneNumber", "country"]}
762
843
  phoneCountryCode="44"
844
+ syncWithProfile={true}
763
845
  customFields={[
764
846
  {
765
847
  key: "company",
766
848
  label: "Company",
767
849
  type: "input",
768
- required: true
769
- }
850
+ required: true,
851
+ },
770
852
  ]}
771
853
  consents={[
772
854
  {
773
855
  id: "marketing",
774
- label: "I agree to receive marketing emails"
775
- }
856
+ label: "I agree to receive marketing emails",
857
+ },
776
858
  ]}
777
859
  labels={{
778
860
  title: "Get Early Access",
779
861
  submitButtonLabel: "Join Waitlist",
780
862
  successTitle: "You're In!",
781
- successDescription: "We'll notify you when we launch."
863
+ successDescription: "We'll notify you when we launch.",
782
864
  }}
783
865
  onSuccessCTA={{
784
866
  defaultLabel: "Learn More",
785
867
  url: "https://example.com/learn-more",
786
- target: "_blank"
868
+ target: "_blank",
787
869
  }}
788
870
  themeOptions={{
789
- mode: "dark"
871
+ mode: "dark",
790
872
  }}
791
873
  />
792
874
  ```
@@ -796,6 +878,7 @@ import { WidgetTemplate } from "fansunited-frontend-core";
796
878
  Interactive personality quiz component that matches users with personas based on their answers. Features comprehensive result displays with persona matching, detailed explanations, and customizable templates.
797
879
 
798
880
  **Key Features:**
881
+
799
882
  - Personality matching algorithm with percentage scores
800
883
  - Multiple persona results with detailed descriptions
801
884
  - Tabbed result interface with top match highlighting
@@ -808,12 +891,12 @@ Interactive personality quiz component that matches users with personas based on
808
891
 
809
892
  #### Required Props
810
893
 
811
- | Prop | Type | Description |
812
- | ---------- | -------------------- | ---------------------------------- |
813
- | `entityId` | `string` | Personality Quiz identifier |
814
- | `sdk` | `FansUnitedSDKModel` | SDK instance |
815
- | `template` | `WidgetTemplate` | Layout template |
816
- | `language` | `LanguageType` | Display language |
894
+ | Prop | Type | Description |
895
+ | ---------- | -------------------- | --------------------------- |
896
+ | `entityId` | `string` | Personality Quiz identifier |
897
+ | `sdk` | `FansUnitedSDKModel` | SDK instance |
898
+ | `template` | `WidgetTemplate` | Layout template |
899
+ | `language` | `LanguageType` | Display language |
817
900
 
818
901
  #### Optional Props
819
902
 
@@ -831,7 +914,10 @@ Interactive personality quiz component that matches users with personas based on
831
914
  #### Templates
832
915
 
833
916
  ```tsx
834
- import { WidgetTemplate, PersonalityQuizPlayProps } from "fansunited-frontend-core";
917
+ import {
918
+ WidgetTemplate,
919
+ PersonalityQuizPlayProps,
920
+ } from "fansunited-frontend-core";
835
921
 
836
922
  // Standard template with optional image positioning
837
923
  const standardProps: PersonalityQuizPlayProps = {
@@ -889,7 +975,7 @@ import { SignInCTADetails } from "fansunited-frontend-core";
889
975
 
890
976
  // Custom sign-in component
891
977
  const signInCTA: SignInCTADetails = {
892
- component: <CustomSignInButton />
978
+ component: <CustomSignInButton />,
893
979
  };
894
980
 
895
981
  // Basic sign-in with onClick handler
@@ -898,21 +984,21 @@ const signInCTA: SignInCTADetails = {
898
984
  onClick: () => {
899
985
  // Handle sign-in logic
900
986
  console.log("Sign in clicked");
901
- }
987
+ },
902
988
  };
903
989
 
904
990
  // Sign-in with URL navigation
905
991
  const signInCTA: SignInCTADetails = {
906
992
  defaultLabel: "Login to discover your personality",
907
993
  url: "https://your-auth-provider.com/login",
908
- target: "_blank"
994
+ target: "_blank",
909
995
  };
910
996
 
911
997
  <PersonalityQuizPlay
912
998
  {...otherProps}
913
999
  userIsLoggedIn={false}
914
1000
  signInCTA={signInCTA}
915
- />
1001
+ />;
916
1002
  ```
917
1003
 
918
1004
  **Sign-in Priority Order:**
@@ -939,9 +1025,10 @@ const leads: LeadsOptions = {
939
1025
  campaignId: "personality-quiz-2024",
940
1026
  campaignName: "Personality Assessment Campaign",
941
1027
  phoneCountryCode: "1", // Default country code for phone fields
1028
+ syncWithProfile: true, // Optional: sync form data to user profile after successful submission
942
1029
  };
943
1030
 
944
- <PersonalityQuizPlay {...otherProps} leads={leads} />
1031
+ <PersonalityQuizPlay {...otherProps} leads={leads} />;
945
1032
  ```
946
1033
 
947
1034
  #### Answer Explanations
@@ -949,13 +1036,11 @@ const leads: LeadsOptions = {
949
1036
  Enable detailed explanations for quiz answers and persona matching:
950
1037
 
951
1038
  ```tsx
952
- <PersonalityQuizPlay
953
- {...otherProps}
954
- showAnswerExplanations={true}
955
- />
1039
+ <PersonalityQuizPlay {...otherProps} showAnswerExplanations={true} />
956
1040
  ```
957
1041
 
958
1042
  When enabled, users will see:
1043
+
959
1044
  - Explanations for each answer choice
960
1045
  - Detailed persona descriptions
961
1046
  - Matching algorithm insights
@@ -974,7 +1059,7 @@ import { WidgetTemplate } from "fansunited-frontend-core";
974
1059
  sdk={sdkInstance}
975
1060
  template={WidgetTemplate.STANDARD}
976
1061
  language="en"
977
- />
1062
+ />;
978
1063
  ```
979
1064
 
980
1065
  ##### Advanced Personality Quiz
@@ -998,15 +1083,16 @@ import { WidgetTemplate } from "fansunited-frontend-core";
998
1083
  campaignId: "personality-campaign",
999
1084
  campaignName: "Personality Assessment 2024",
1000
1085
  phoneCountryCode: "44",
1086
+ syncWithProfile: true,
1001
1087
  }}
1002
1088
  themeOptions={{
1003
1089
  mode: "dark",
1004
1090
  colorSchemes: {
1005
1091
  dark: {
1006
1092
  textPrimary: "#ffffff",
1007
- surface: "#1a1a1a"
1008
- }
1009
- }
1093
+ surface: "#1a1a1a",
1094
+ },
1095
+ },
1010
1096
  }}
1011
1097
  />
1012
1098
  ```
@@ -1027,9 +1113,305 @@ import { WidgetTemplate } from "fansunited-frontend-core";
1027
1113
  customFontFamily: {
1028
1114
  light: {
1029
1115
  primary: "Inter, sans-serif",
1030
- secondary: "Roboto, sans-serif"
1031
- }
1032
- }
1116
+ secondary: "Roboto, sans-serif",
1117
+ },
1118
+ },
1119
+ }}
1120
+ />
1121
+ ```
1122
+
1123
+ ### MatchQuizPlay
1124
+
1125
+ Interactive match prediction quiz component that allows users to make predictions on various football match markets. Features multiple fixture types, real-time countdown timers, points system, and comprehensive result tracking with leaderboards.
1126
+
1127
+ **Key Features:**
1128
+
1129
+ - Multiple prediction markets (1X2, Correct Score, Player Markets, Over/Under Goals, Corners, etc.)
1130
+ - Real-time countdown timer for prediction cutoff
1131
+ - Points system with loyalty integration
1132
+ - Leaderboard and ranking system
1133
+ - Prediction summary and editing capabilities
1134
+ - Three responsive templates (Standard, Split, Overlay)
1135
+ - Lead collection integration
1136
+ - Authentication support
1137
+ - Custom theming and branding
1138
+ - Detailed prediction results and explanations
1139
+
1140
+ #### Required Props
1141
+
1142
+ | Prop | Type | Description |
1143
+ | ---------- | -------------------- | --------------------- |
1144
+ | `entityId` | `string` | Match Quiz identifier |
1145
+ | `sdk` | `FansUnitedSDKModel` | SDK instance |
1146
+ | `template` | `WidgetTemplate` | Layout template |
1147
+ | `language` | `LanguageType` | Display language |
1148
+
1149
+ #### Optional Props
1150
+
1151
+ | Prop | Type | Description |
1152
+ | ---------------------------- | -------------------- | ------------------------------------------------- |
1153
+ | `themeOptions` | `CustomThemeOptions` | Theme configuration |
1154
+ | `leads` | `LeadsOptions` | Lead collection settings |
1155
+ | `imagePosition` | `"left" \| "right"` | Image position (STANDARD template only) |
1156
+ | `defaultImagePlaceholderUrl` | `string` | URL for default image placeholder |
1157
+ | `userIsLoggedIn` | `boolean` | Determine if the user is logged in |
1158
+ | `signInCTA` | `SignInCTADetails` | Sign in call to action button configuration |
1159
+ | `showCountdown` | `boolean` | Show countdown timer when Match Quiz is open |
1160
+ | `showTeamLabels` | `boolean` | Show team name labels in fixture components |
1161
+ | `showPoints` | `boolean` | Show points display for each fixture |
1162
+ | `showPredictionDetails` | `boolean` | Show detailed prediction results after completion |
1163
+
1164
+ #### Templates
1165
+
1166
+ ```tsx
1167
+ import { WidgetTemplate, MatchQuizPlayProps } from "fansunited-frontend-core";
1168
+
1169
+ // Standard template with optional image positioning
1170
+ const standardProps: MatchQuizPlayProps = {
1171
+ template: WidgetTemplate.STANDARD,
1172
+ imagePosition: "left", // or 'right'
1173
+ // ... other props
1174
+ };
1175
+
1176
+ // Split template - side-by-side layout
1177
+ const splitProps: MatchQuizPlayProps = {
1178
+ template: WidgetTemplate.SPLIT,
1179
+ // imagePosition not available for non-standard templates
1180
+ // ... other props
1181
+ };
1182
+
1183
+ // Overlay template - full-screen immersive experience
1184
+ const overlayProps: MatchQuizPlayProps = {
1185
+ template: WidgetTemplate.OVERLAY,
1186
+ // ... other props
1187
+ };
1188
+ ```
1189
+
1190
+ #### Supported Markets
1191
+
1192
+ MatchQuizPlay supports a wide variety of football prediction markets:
1193
+
1194
+ **Match Result Markets:**
1195
+
1196
+ - `FT_1X2` - Full Time 1X2 (Home Win, Draw, Away Win)
1197
+ - `HT_1X2` - Half Time 1X2
1198
+
1199
+ **Score Markets:**
1200
+
1201
+ - `CORRECT_SCORE` - Exact final score prediction
1202
+ - `CORRECT_SCORE_HT` - Exact half-time score prediction
1203
+ - `CORRECT_SCORE_ADVANCED` - Advanced correct score with alternative points
1204
+
1205
+ **Player Markets:**
1206
+
1207
+ - `PLAYER_SCORE_FIRST_GOAL` - First goalscorer prediction
1208
+ - `PLAYER_SCORE` - Anytime goalscorer
1209
+ - `PLAYER_YELLOW_CARD` - Player to receive yellow card
1210
+ - `PLAYER_RED_CARD` - Player to receive red card
1211
+ - `PLAYER_SCORE_HATTRICK` - Player to score hat-trick
1212
+ - `PLAYER_SCORE_TWICE` - Player to score twice
1213
+
1214
+ **Over/Under Markets:**
1215
+
1216
+ - `OVER_GOALS_0_5` to `OVER_GOALS_6_5` - Total goals over/under
1217
+ - `OVER_CORNERS_6_5` to `OVER_CORNERS_13_5` - Total corners over/under
1218
+
1219
+ **Special Markets:**
1220
+
1221
+ - `CORNERS_MATCH` - Total corners in the match
1222
+ - `PENALTY_MATCH` - Penalty awarded in the match
1223
+ - `RED_CARD_MATCH` - Red card shown in the match
1224
+
1225
+ #### Game Status States
1226
+
1227
+ Match quizzes have 5 distinct status states:
1228
+
1229
+ - **`PENDING`** - Not yet open for predictions
1230
+ - **`OPEN`** - Ready for predictions (default state)
1231
+ - **`LIVE`** - Match has started, no new predictions accepted
1232
+ - **`CLOSED`** - Match finished, backend resolving predictions
1233
+ - **`SETTLED`** - Predictions resolved, leaderboard available
1234
+
1235
+ #### Countdown Timer
1236
+
1237
+ Enable countdown timer to show time remaining for predictions:
1238
+
1239
+ ```tsx
1240
+ <MatchQuizPlay {...otherProps} showCountdown={true} />
1241
+ ```
1242
+
1243
+ The countdown timer:
1244
+
1245
+ - Displays when Match Quiz status is `OPEN`
1246
+ - Shows days, hours, minutes, and seconds remaining
1247
+ - Uses `predictionsCutoffTime` from the Match Quiz data
1248
+ - Automatically hides when cutoff time is reached
1249
+
1250
+ #### Points System
1251
+
1252
+ Enable points display to show potential rewards:
1253
+
1254
+ ```tsx
1255
+ <MatchQuizPlay {...otherProps} showPoints={true} />
1256
+ ```
1257
+
1258
+ Points system features:
1259
+
1260
+ - Shows potential points for each fixture
1261
+ - Displays earned vs possible points
1262
+ - Integrates with loyalty system configuration
1263
+ - Supports alternative point structures for advanced markets
1264
+ - Mobile-friendly tooltip display
1265
+
1266
+ #### Prediction Details
1267
+
1268
+ Show detailed prediction results and explanations:
1269
+
1270
+ ```tsx
1271
+ <MatchQuizPlay {...otherProps} showPredictionDetails={true} />
1272
+ ```
1273
+
1274
+ When enabled, users see:
1275
+
1276
+ - Tabulated interface
1277
+ - Correct vs incorrect prediction highlighting
1278
+ - Detailed market results
1279
+ - Points breakdown per fixture
1280
+
1281
+ #### Sign in Configuration
1282
+
1283
+ Control user authentication and quiz access using the `userIsLoggedIn` and `signInCTA` props.
1284
+
1285
+ ```tsx
1286
+ import { SignInCTADetails } from "fansunited-frontend-core";
1287
+
1288
+ // Custom sign-in component
1289
+ const signInCTA: SignInCTADetails = {
1290
+ component: <CustomSignInButton />,
1291
+ };
1292
+
1293
+ // Basic sign-in with onClick handler
1294
+ const signInCTA: SignInCTADetails = {
1295
+ defaultLabel: "Sign in to predict",
1296
+ onClick: () => {
1297
+ // Handle sign-in logic
1298
+ console.log("Sign in clicked");
1299
+ },
1300
+ };
1301
+
1302
+ // Sign-in with URL navigation
1303
+ const signInCTA: SignInCTADetails = {
1304
+ defaultLabel: "Login to join the competition",
1305
+ url: "https://your-auth-provider.com/login",
1306
+ target: "_blank",
1307
+ };
1308
+
1309
+ <MatchQuizPlay {...otherProps} userIsLoggedIn={false} signInCTA={signInCTA} />;
1310
+ ```
1311
+
1312
+ **Sign-in Priority Order:**
1313
+
1314
+ 1. **Custom Component** - If `signInCTA.component` is provided, it will be rendered
1315
+ 2. **Click Handler** - If `signInCTA.onClick` is provided, a button with the handler will be rendered
1316
+ 3. **URL Navigation** - If `signInCTA.url` is provided, a button will be rendered and clicking will navigate to the URL
1317
+ 4. **Disabled** - If no `signInCTA` is provided, a disabled button will be shown
1318
+
1319
+ **Behavior:**
1320
+
1321
+ - When `userIsLoggedIn` is `false` and the quiz requires authentication (`authRequirement: "REGISTERED"`), the sign-in screen will be displayed instead of the quiz
1322
+
1323
+ #### Lead Collection
1324
+
1325
+ Capture user information before or after making predictions:
1326
+
1327
+ ```tsx
1328
+ import { LeadsOptions } from "fansunited-frontend-core";
1329
+
1330
+ const leads: LeadsOptions = {
1331
+ position: "before", // "before" | "after"
1332
+ fields: ["fullName", "email"], // Available: "fullName" | "firstName" | "lastName" | "email" | "gender" | "country" | "phoneCountryCode" | "phoneNumber"
1333
+ campaignId: "match-quiz-2024",
1334
+ campaignName: "Football Prediction Campaign",
1335
+ phoneCountryCode: "44", // Default country code for phone fields
1336
+ syncWithProfile: true, // Optional: sync form data to user profile after successful submission
1337
+ };
1338
+
1339
+ <MatchQuizPlay {...otherProps} leads={leads} />;
1340
+ ```
1341
+
1342
+ #### Examples
1343
+
1344
+ ##### Basic Match Quiz
1345
+
1346
+ ```tsx
1347
+ import { MatchQuizPlay } from "fansunited-frontend-components";
1348
+ import { WidgetTemplate } from "fansunited-frontend-core";
1349
+
1350
+ <MatchQuizPlay
1351
+ entityId="match-quiz-123"
1352
+ sdk={sdkInstance}
1353
+ template={WidgetTemplate.STANDARD}
1354
+ language="en"
1355
+ />;
1356
+ ```
1357
+
1358
+ ##### Advanced Match Quiz
1359
+
1360
+ ```tsx
1361
+ <MatchQuizPlay
1362
+ entityId="match-quiz-123"
1363
+ sdk={sdkInstance}
1364
+ template={WidgetTemplate.OVERLAY}
1365
+ language="en"
1366
+ showCountdown={true}
1367
+ showTeamLabels={true}
1368
+ showPoints={true}
1369
+ showPredictionDetails={true}
1370
+ userIsLoggedIn={false}
1371
+ signInCTA={{
1372
+ defaultLabel: "Sign in to compete",
1373
+ onClick: () => handleSignIn(),
1374
+ }}
1375
+ leads={{
1376
+ position: "after",
1377
+ fields: ["fullName", "email"],
1378
+ campaignId: "match-prediction-campaign",
1379
+ campaignName: "Football Predictions 2024",
1380
+ phoneCountryCode: "44",
1381
+ syncWithProfile: true,
1382
+ }}
1383
+ themeOptions={{
1384
+ mode: "dark",
1385
+ colorSchemes: {
1386
+ dark: {
1387
+ textPrimary: "#ffffff",
1388
+ surface: "#1a1a1a",
1389
+ },
1390
+ },
1391
+ }}
1392
+ />
1393
+ ```
1394
+
1395
+ ##### Customized Layout
1396
+
1397
+ ```tsx
1398
+ <MatchQuizPlay
1399
+ entityId="match-quiz-123"
1400
+ sdk={sdkInstance}
1401
+ template={WidgetTemplate.STANDARD}
1402
+ imagePosition="right"
1403
+ language="en"
1404
+ showCountdown={true}
1405
+ showTeamLabels={false}
1406
+ showPoints={true}
1407
+ themeOptions={{
1408
+ mode: "light",
1409
+ customFontFamily: {
1410
+ light: {
1411
+ primary: "Inter, sans-serif",
1412
+ secondary: "Roboto, sans-serif",
1413
+ },
1414
+ },
1033
1415
  }}
1034
1416
  />
1035
1417
  ```
@@ -1042,6 +1424,7 @@ This package exports the following components:
1042
1424
  - **`PollVote`** - Interactive polling with real-time results
1043
1425
  - **`CollectLead`** - Lead collection forms with custom fields
1044
1426
  - **`PersonalityQuizPlay`** - Personality assessment with persona matching
1427
+ - **`MatchQuizPlay`** - Football match prediction quiz with multiple markets
1045
1428
 
1046
1429
  ## Related Packages
1047
1430