-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Growth Fullstack Challenge First Commit
- Loading branch information
0 parents
commit 93ef1c1
Showing
38 changed files
with
14,917 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Ignore Metals files | ||
scala-backend/project/metals.sbt | ||
|
||
# Ignore other unnecessary development files | ||
.idea/ | ||
.vscode/ | ||
target/ | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# Scala-specific | ||
*.class | ||
*.log | ||
|
||
|
||
# SBT-specific | ||
dist/* | ||
target/ | ||
lib_managed/ | ||
src_managed/ | ||
project/boot/ | ||
project/plugins/project/ | ||
.history | ||
.cache | ||
.lib/ | ||
|
||
# IntelliJ IDEA-specific | ||
.idea/ | ||
*.iml | ||
*.iws | ||
*.ipr | ||
out/ | ||
|
||
# VS Code-specific | ||
.vscode/ | ||
|
||
# macOS-specific | ||
.DS_Store | ||
|
||
# Windows-specific | ||
Thumbs.db | ||
|
||
# Metals (Scala language server) specific | ||
.metals/ | ||
.bloop/ | ||
|
||
# Scala Worksheet | ||
*.sc | ||
|
||
# Temporary files | ||
*~ | ||
*.swp | ||
*.swo | ||
|
||
# Application-specific | ||
application.conf | ||
|
||
# Logs | ||
logs/ | ||
|
||
# Database | ||
*.db | ||
*.sqlite | ||
|
||
# Environment variables | ||
.env | ||
|
||
# Frontend-specific | ||
frontend/node_modules/ | ||
frontend/build/ | ||
frontend/dist/ | ||
frontend/.cache/ | ||
frontend/.env.local | ||
frontend/.env.development.local | ||
frontend/.env.test.local | ||
frontend/.env.production.local | ||
|
||
nodejs-backend/node_modules | ||
|
||
# Backend-specific | ||
backend/target/ | ||
backend/project/target/ | ||
|
||
# Dependency directories | ||
project/project/ | ||
project/target/ | ||
|
||
# Scala 3 specific | ||
.tasty | ||
|
||
# Bloop specific | ||
.bsp/ | ||
|
||
# npm/yarn debug logs | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
# Famly technical challenge: Fullstack Engineer in Growth | ||
|
||
TODO | ||
|
||
- [ ] Hot reloading Scala project not working | ||
|
||
Hi :wave: | ||
|
||
This repository contains a technical challenge for a full-stack engineering | ||
role in the Growth department at Famly. | ||
|
||
## Expectations | ||
|
||
We don't expect you to spend a lot of time on this - no more than 2-3 hours. | ||
If you get stuck on a question or don't manage to finish it within that time limit, | ||
please don't sweat it. | ||
|
||
The main purpose of this technical assignment is for us to get a feeling for: | ||
|
||
- Your technical abilities | ||
- Your problem solving skills | ||
- Your product sense | ||
|
||
In the follow up interview we'll ask you to walk us through your solution, | ||
asking questions along the way. If there are pieces missing, we'll use the | ||
time to discuss potential solutions or potentially do some light | ||
pair programming together. The main purpose here is for us to get a sense | ||
for whether we're a good collaboration match - both for us and for you. We're | ||
also interested in understanding your ability to communicate your ideas while | ||
you're walking us through your solution and potential improvements you'd make | ||
if you'd have more time. | ||
|
||
## Instructions | ||
|
||
1. Start by forking this repository | ||
2. Decide whether you want to solve the backend parts of this challenge in Scala | ||
or in NodeJS | ||
3. Solve the [exercises](#exercises) below. | ||
4. If you want to write something about your solutions to the exercise, | ||
please do so in the [answers.md](answers.md) file. | ||
5. For each question you answer, please create a commit and push them | ||
to the main branch. Remember to include a helpful commit message. | ||
6. When you're done, send us an email with the link to the forked repository | ||
|
||
Feel free to reach out with any questions before starting the challenge via email: <bis@famly.co> | ||
|
||
## About this project | ||
|
||
This project is a simple web application meant to represent a tiny use case of Famly: The Bill Payer profile. In Famly, a parent that pays for the kids tuition is called a Bill Payer. | ||
In this project, the Bill Payer profile includes some helpful features such as: | ||
|
||
- Invoices: List all invoices that the nursery has sent to this parent. | ||
- Payment methods: A bill payer can have 0 or more payment methods. An active payment method is what the nursery uses to charge the | ||
parent. | ||
|
||
The data in this web app is meant to be very simple - in real life it's a _little bit more complex than that_. | ||
|
||
## How to run this project | ||
|
||
This project consists of: | ||
|
||
- A Scala backend | ||
- A NodeJS backend | ||
- A React + TypeScript Frontend | ||
- A MySQL database | ||
|
||
We've included both a Scala backend and a NodeJS backend so that you can | ||
choose which you prefer to work with. | ||
|
||
You can of course run the application any way you want, but if you want to | ||
avoid the hassle of getting all the tools/dependencies installed on your | ||
system, we've prepared a [docker-compose.yml](docker-compose.yml) | ||
file for you so you can simply run the app via: | ||
|
||
```sh | ||
# Using the Scala backend | ||
docker-compose --profile scala up --build | ||
|
||
# Using the NodeJS backend | ||
docker-compose --profile nodejs up --build | ||
|
||
``` | ||
|
||
> In order for this to work, we recommend installing [Docker Desktop](https://www.docker.com/products/docker-desktop/). | ||
Once everything is up-and-running via docker-compose you can access | ||
|
||
**The database at:** | ||
|
||
- Host: 127.0.0.1 | ||
- Port: 3308 | ||
- Username: root | ||
- Password: root | ||
|
||
**The frontend at:** | ||
|
||
- <http://localhost:3000> | ||
|
||
**The backend at:** | ||
|
||
- <http://localhost:9000> | ||
|
||
When making changes to the code the servers running in Docker will pick up those changes. Once everything is done re-building you should be able to | ||
see your changes by refreshing the page. | ||
|
||
**Making changes to the database** | ||
|
||
If you need to make changes to the database tables, | ||
you can add migrations in the [migrations](migrations) directory and they will be picked up when running docker-compose. You can also just apply the migrations to the database directly, but if you do, please make sure to | ||
note down the SQL statements in the [answers.md](answers.md) file. | ||
|
||
## Exercises | ||
|
||
### 1 | ||
|
||
When a user interacts with the Payment Methods widget, something seems off. | ||
When adding or deleting or activating a payment method the changes are not | ||
reflected until the user refreshes the page. | ||
|
||
Please fix this issue, so that updates are reflected right away without | ||
needing to refresh the page. | ||
|
||
### 2 | ||
|
||
A user has reported that when they delete a payment method, sometimes | ||
multiple payment methods are deleted (instead of just the one). | ||
|
||
Please debug and fix the underlying issue. | ||
|
||
### 3 | ||
|
||
The Payment Methods widget is missing a critical feature: A parent should | ||
always have at least one active payment method. Otherwise, the nursery cannot | ||
charge the parent for the care. | ||
|
||
Unfortunately this is not the case right now. If you delete an active payment method, | ||
you end up with no active payment methods. | ||
|
||
Please implement this missing feature to ensure that the nursery can always | ||
charge all their parents. | ||
|
||
### 4 | ||
|
||
A parent has requested to be able to see _when_ each payment method was created | ||
in the Payment Methods widget. This is useful in cases where you have multiple | ||
payment methods with the same name. | ||
|
||
Please implement this missing feature. | ||
|
||
### 5 | ||
|
||
For audit reasons, it's important to capture any updates that are made to payment | ||
methods for each parent. We need to capture exactly what changed, when it occurred, | ||
and who made the change. | ||
|
||
Please implement this critical missing functionality, so that we'll stay in business! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Expercises - Answers | ||
|
||
## Question 1 | ||
|
||
## Question 2 | ||
|
||
## Question 3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
version: "3.8" | ||
|
||
services: | ||
scala-backend: | ||
build: ./scala-backend | ||
ports: | ||
- "9000:9000" | ||
volumes: | ||
- ./scala-backend:/app | ||
depends_on: | ||
- db | ||
profiles: | ||
- scala | ||
environment: | ||
- CHOKIDAR_USEPOLLING=true # Enable polling for file changes | ||
|
||
nodejs-backend: | ||
build: ./nodejs-backend | ||
ports: | ||
- "9000:9000" | ||
depends_on: | ||
- db | ||
profiles: | ||
- nodejs | ||
volumes: | ||
- ./nodejs-backend/:/app | ||
- /app/node_modules | ||
environment: | ||
- CHOKIDAR_USEPOLLING=true | ||
- MYSQL_HOST=db | ||
- MYSQL_USER=root | ||
- MYSQL_PASSWORD=root | ||
- MYSQL_DATABASE=parent_profile | ||
|
||
frontend: | ||
build: ./frontend | ||
ports: | ||
- "3000:3000" | ||
volumes: | ||
- ./frontend:/app | ||
- /app/node_modules | ||
environment: | ||
- CHOKIDAR_USEPOLLING=true | ||
|
||
db: | ||
image: mysql:8.0 | ||
environment: | ||
MYSQL_ROOT_PASSWORD: root | ||
MYSQL_DATABASE: parent_profile | ||
ports: | ||
- "3308:3306" | ||
volumes: | ||
- db_data:/var/lib/mysql | ||
|
||
migrate: | ||
image: mysql:8.0 | ||
command: > | ||
sh -c " | ||
until mysql -h db -uroot -proot -e 'select 1'; do | ||
echo 'Waiting for MySQL to be ready...'; | ||
sleep 2; | ||
done; | ||
mysql -h db -uroot -proot parent_profile < /migrations/01-init.sql | ||
" | ||
volumes: | ||
- ./migrations:/migrations | ||
depends_on: | ||
- db | ||
|
||
volumes: | ||
db_data: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# TODO: Use a never version of NodeJS | ||
FROM node:18-alpine | ||
|
||
WORKDIR /app | ||
|
||
COPY package.json yarn.lock ./ | ||
RUN yarn install | ||
|
||
COPY . . | ||
|
||
RUN yarn build | ||
|
||
EXPOSE 3000 | ||
|
||
CMD ["yarn", "start"] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
{ | ||
"name": "parent-profile-frontend", | ||
"version": "0.1.0", | ||
"private": true, | ||
"dependencies": { | ||
"@apollo/client": "^3.5.5", | ||
"@material-ui/core": "^4.12.3", | ||
"@material-ui/icons": "^4.11.2", | ||
"@types/react": "^18.3.4", | ||
"@types/react-dom": "^18.3.0", | ||
"graphql": "^15.5.3", | ||
"react": "18.2.0", | ||
"react-dom": "18.2.0", | ||
"react-router-dom": "^6.0.2", | ||
"react-scripts": "^5.0.1", | ||
"typescript": "^5.5.4" | ||
}, | ||
"scripts": { | ||
"start": "react-scripts start", | ||
"build": "react-scripts build", | ||
"test": "react-scripts test", | ||
"eject": "react-scripts eject" | ||
}, | ||
"eslintConfig": { | ||
"extends": [ | ||
"react-app", | ||
"react-app/jest" | ||
] | ||
}, | ||
"browserslist": { | ||
"production": [ | ||
">0.2%", | ||
"not dead", | ||
"not op_mini all" | ||
], | ||
"development": [ | ||
"last 1 chrome version", | ||
"last 1 firefox version", | ||
"last 1 safari version" | ||
] | ||
}, | ||
"devDependencies": {} | ||
} |
Oops, something went wrong.