+ A mobile coach that helps you enjoy solo and partnered connection. Coral is a one-of-a-kind app that
+ provides guided exercises to increase your confidence and reduce performance anxiety through games and
+ fun!
+
+
+
+
+
+
+
+
+
+
+
+
Background
+
+
+
+
+
+ Coral is a science-backed app that helps couples and individuals improve their connections. Its
+ engineers, who have been using the app for some time, know it better than anyone. With their
+ exceptional knowledge and supervision, you won't be alone on your intimate journey. Coral gets to
+ know you better and offers valuable insights from professors and practitioners
+
+
+ We started working with Lewis when his team already had a functional mobile app and web version.
+ However, the current version went outdated a year after it saw the world. Valor took on the task of
+ bug fixing. Eventually, we were up to server reconsideration when the real story begins :)
+
+
+ What we had there was a Cordova-based app built more than a year before we took it over and the web
+ version using Vue.js. The main challenge we faced was with the admin system and its controls. We
+ also worked on the web and mobile versions from time to time before releasing them on the App Store
+ and Google Play Android Store.
+
+
+
+
+
+
+
+
Solutions
+
+
+
+
+ {{drawbacks.title}}
+
+
+
+
{{role}}
+
+
+
+
+
+ {{drawbacks.subtitle}}
+
+ {{description}}
+
+
+
+
+
+
Deliverables
+
+
+
+
+ {{deliverable.title}}
+
+ {{description}}
+
+
+
+
+
+
{{role}}
+
+
+
+
+
+
+
+
+
+
+ Technologies:
+
+
+
+
+
+
+
Features
+
+
+
+ The onboarding process is a breeze – just download the app, register, and take a quick survey (8-10
+ questions) that will help us create custom content for you based on your preferences, gender, and any
+ possible sexual traumas you may have experienced.
+
+
+
+ After that, you'll get personalized lessons, practices, and tasks. These "journeys" consist of a series
+ of steps, with texts, audio, and questionnaires to help you learn and grow. And the best part is, you
+ can either pay for a subscription (60 bucks a year) or stick with the free version of the app. The free
+ version doesn't have all the content, but it's still pretty cool.
+
+
+
+
+
+
+
+
+
+
Feedback
+
+
+
+ Hi! I'm Max, an engineer that solved the caching issue, and I just wanted to share some feedback on the
+ development process. This is the best team I have ever worked with! We all worked together seamlessly,
+ and no one was too opinionated or egotistical. Everyone's experience and knowledge was valued and
+ helpful.
+
+
+
+ We were able to solve problems quickly and efficiently, and it was always encouraged to ask questions.We
+ had great communication and the team was chosen based on their soft skills, which I think is the secret
+ to our success. Special shoutout to Denis, Alex Bolshakov, Max, Alexandra Nadtochiy, and Slava Chub –
+ amazing team on the Valor side!
+
+
+
+
+
+ Impact
+
+
+ Coral's initial goal is to educate and promote knowledge sharing, which sets us apart from the
+ competition, and makes us a unique and safe app for years to come. Our forums are filled with
+ sexologists and experts from various fields and universities, so you can get reliable advice and
+ information. Plus, you can connect with your partner in the app, which offers a different
+ experience and content.
+
+
+ And if you buy a subscription, your partner gets access for free – sharing deepens connections,
+ and that's what Coral aims to do for you! :)
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/route-pages/coral-page/src/coral-page.component.ts b/libs/route-pages/coral-page/src/coral-page.component.ts
new file mode 100644
index 000000000..ba2ca9e7c
--- /dev/null
+++ b/libs/route-pages/coral-page/src/coral-page.component.ts
@@ -0,0 +1,118 @@
+import { Component } from '@angular/core';
+import { DeliverableCard, ITechnologiesCard } from '@valor-software/common-docs';
+import { IFeaturesCard } from './features-card.component';
+
+@Component({
+ // eslint-disable-next-line @angular-eslint/component-selector
+ selector: 'coral-page',
+ templateUrl: './coral-page.component.html'
+})
+
+export class CoralPageComponent {
+
+
+
+ technologiesCard: ITechnologiesCard[] = [
+ {
+ smJustify: 'evenly',
+ lgJustify: 'start',
+ technologies: [
+ {
+ src: "assets/img/technologies/svg/react_clean.svg",
+ title: "React Native"
+ },
+ {
+ src: "assets/img/technologies/svg/nest_js.svg",
+ title: "Nest.js"
+ },
+ {
+ src: "assets/img/technologies/svg/graph_ql.svg",
+ title: "GraphQL"
+ }
+ ]
+ }
+ ];
+
+ changeBreadCrumbTitle: { path: string, title: string, excludePath?: boolean }[] = [
+ {
+ path: 'projects',
+ title: 'Portfolio',
+ },
+ {
+ path: 'coral',
+ title: 'coral'
+ }
+ ];
+
+ deliverable: { title: string, descriptions: string[], roles: string[] } =
+ {
+ title: "Coral V 2. A new reconsidered and blossoming cross-platform mobile app.",
+ descriptions: [
+ `We used Nest.js and GraphQL to create a new server that acts as an intermediary between the frontend and the existing server. We kept the old server for two reasons: the admin panel was tightly connected to it, and it was also used for the web part. Later on, we gave the admin panel independence from this "construction" but still kept the old server for the web. This made sense because we needed to prioritize value for our users and provide them with the features they needed, just as the client has been doing it since Coral was created.`,
+ `Max and Denis started from scratch on this project. They were the ones doing the heavy lifting, while Valor provided some tech solutions and suggestions, the client's team made the final call.`
+ ],
+ roles:
+ [
+ 'Backend - Maxim Ugnichenko',
+ 'Frontend - Alexander Bolshakov',
+ 'Design - mostly Coral Team, then - Alexandra Nadtochiy',
+ ]
+ };
+
+ // drawbacks: string[] = [
+ // 'Tricky code',
+ // 'Lack of functionality and code docs',
+ // 'Admin panel, web, and mobile parts needed help'
+ // ];
+
+ // drawbacksSolution: string[] = [
+ // 'The chat prompts were a big hit with users because they provided helpful suggestions. We also added analytics to provide even deeper assistance. These suggestions covered a wide range of topics, not just sex. At one point, we had 30,000 partners and the system crashed because we tried to send all the messages at once.',
+ // 'To fix this issue, we had to look at caching. Caches can be different, almost unchangeable, changeable, and 100% static. So we used caching mostly instead of the server and protected the distances (PD(t)) of each thread. This greatly reduced the time it took to send messages from two hours to just 10 minutes. Max was the one who came up with the new logic and flow that made this possible.',
+ // 'In the end, it was all worth it because our users were thrilled with the improvements. As they say, "Good things come to those who wait... and have a good cache system in place!" And, as always, huge thanks to Max for being a coding wizard and making it all happen.'
+ // ];
+
+ drawbacks: { title: string, subtitle: string; solutions: string[], drawbacks: string[] } =
+ {
+ title: "Drawbacks",
+ subtitle: "Solutions",
+ solutions: [
+ 'The chat prompts were a big hit with users because they provided helpful suggestions. We also added analytics to provide even deeper assistance. These suggestions covered a wide range of topics, not just sex. At one point, we had 30,000 partners and the system crashed because we tried to send all the messages at once.',
+ 'To fix this issue, we had to look at caching. Caches can be different, almost unchangeable, changeable, and 100% static. So we used caching mostly instead of the server and protected the distances (PD(t)) of each thread. This greatly reduced the time it took to send messages from two hours to just 10 minutes. Max was the one who came up with the new logic and flow that made this possible.',
+ 'In the end, it was all worth it because our users were thrilled with the improvements. As they say, "Good things come to those who wait... and have a good cache system in place!" And, as always, huge thanks to Max for being a coding wizard and making it all happen.'
+ ],
+ drawbacks:
+ [
+ 'Tricky code',
+ 'Lack of functionality and code docs',
+ 'Admin panel, web, and mobile parts needed help'
+ ]
+ };
+
+
+ features: IFeaturesCard[] = [
+ {
+ title: 'Join our forum and get social!',
+ description: `In addition to our app that analyzes your answers and gives advice, we've also created a blog and social platform where people can share, support, and help each other through discussions.`,
+ img: 'assets/img/bg-img/coral_page/onboarding_1.png',
+ },
+ {
+ title: 'Chat',
+ description: `We've also added a chat feature for partners, complete with photos and audio messages (scripting coming soon)."`,
+ img: 'assets/img/bg-img/coral_page/onboarding_2.png',
+ },
+ {
+ title: 'Gifts – merch!',
+ description: `We also offer gifts and badges to users who have completed certain achievements or shown bravery in sharing their experiences on the forum.`
+ },
+ {
+ title: 'Survey',
+ description: `Once a month, we ask users what they like and what they would like to see improved. This is how we came up with chat prompts. We also have plans to add gamification features like badges, but we need to secure the necessary budget first.`
+ },
+ {
+ title: 'Analytics',
+ description: `A designated person reviews all forum comments using a Slack integration, so the Coral team knows which users are happy and which ones are not. A lot of analytics goes into the app to the extent that the frontend is 75% analytics.`
+ }
+ ];
+
+
+}
\ No newline at end of file
diff --git a/libs/route-pages/coral-page/src/coral-page.module.spec.ts b/libs/route-pages/coral-page/src/coral-page.module.spec.ts
new file mode 100644
index 000000000..a1563ad61
--- /dev/null
+++ b/libs/route-pages/coral-page/src/coral-page.module.spec.ts
@@ -0,0 +1,21 @@
+
+ import { async, TestBed } from '@angular/core/testing';
+ import { CoralPageModule } from './coral-page.module';
+
+ describe('CoralPageModule', () => {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [ CoralPageModule ]
+ })
+ .compileComponents();
+ }));
+
+ // TODO: Add real tests here.
+ //
+ // NB: This particular test does not do anything useful.
+ // It does NOT check for correct instantiation of the module.
+ it('should have a module definition', () => {
+ expect(CoralPageModule).toBeDefined();
+ });
+ });
+
\ No newline at end of file
diff --git a/libs/route-pages/coral-page/src/coral-page.module.ts b/libs/route-pages/coral-page/src/coral-page.module.ts
new file mode 100644
index 000000000..37b2f52e9
--- /dev/null
+++ b/libs/route-pages/coral-page/src/coral-page.module.ts
@@ -0,0 +1,25 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { CoralPageComponent } from "./coral-page.component";
+import { routes } from "./routes";
+import { RouterModule, Routes } from "@angular/router";
+import { CommonDocsModule } from '@valor-software/common-docs';
+import { SwiperModule } from "swiper/angular";
+import { FeedbackModule } from '@valor-software/feedback';
+import { FeaturesCardComponent } from './features-card.component';
+
+export { CoralPageComponent } from "./coral-page.component";
+
+@NgModule({
+ declarations: [CoralPageComponent, FeaturesCardComponent],
+ imports: [
+ CommonModule,
+ RouterModule.forChild(routes),
+ CommonDocsModule,
+ SwiperModule,
+ FeedbackModule
+ ]
+})
+export class CoralPageModule {
+ static routes: Routes = routes;
+}
diff --git a/libs/route-pages/coral-page/src/features-card.component.html b/libs/route-pages/coral-page/src/features-card.component.html
new file mode 100644
index 000000000..bc7870767
--- /dev/null
+++ b/libs/route-pages/coral-page/src/features-card.component.html
@@ -0,0 +1,24 @@
+ 0">
+