Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions client-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Quote of the Day

A react application showing how to load a **variant feature flag** from **Azure App Configuration** via **Azure Front Door** and use it to experiment with a personalized greeting in a classic Quote of the Day UI.

## Prerequisites
* Node.js 18+
* Azure App Configuration instance with a Front Door endpoint exposing it
* Application Insights resource

## Get Started

- Replace the placeholders in `src/pages/AppContext.jsx`:
```js
const appInsightsConnectionString = "YOUR-APP-INSIGHTS-CONNECTION-STRING";
await loadFromAzureFrontDoor("YOUR-AZURE-FRONT-DOOR-ENDPOINT");
```

- Create a variant feature flag named `Greeting` in your App Configuration store with the below configuration:

```json
{
"id": "Greeting",
"enabled": true,
"variants": [
{
"name": "Off",
"configuration_value": false
},
{
"name": "On",
"configuration_value": true
}
],
"allocation": {
"percentile": [
{
"variant": "Off",
"from": 0,
"to": 50
},
{
"variant": "On",
"from": 50,
"to": 100
}
],
"user": [
{
"variant": "On",
"users": [
"admin"
]
}
],
"default_when_enabled": "Off",
"default_when_disabled": "Off"
},
"telemetry": {
"enabled": true
}
}
```
- Run the following command:

```powershell
cd client-app
npm install
npm run build
npm run preview
```

13 changes: 13 additions & 0 deletions client-app/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Quote of the Day</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/index.jsx"></script>
</body>
</html>
22 changes: 22 additions & 0 deletions client-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "quote-of-the-day",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@azure/app-configuration-provider": "2.3.0-preview",
"@microsoft/feature-management": "latest",
"@microsoft/feature-management-applicationinsights-browser": "latest",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "5.3.0",
"react-router-dom": "^6.27.0"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.3.1",
"vite": "^7.2.2"
}
}
1 change: 1 addition & 0 deletions client-app/public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
198 changes: 198 additions & 0 deletions client-app/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
body {
margin: 0;
font-family: 'Georgia', serif;
}

.quote-page {
display: flex;
flex-direction: column;
min-height: 100vh;
background-color: #f4f4f4;
}

.navbar {
background-color: white;
border-bottom: 1px solid #eaeaea;
display: flex;
justify-content: space-between;
padding: 10px 20px;
align-items: center;
font-family: 'Arial', sans-serif;
font-size: 16px;
}

.navbar-left {
display: flex;
align-items: center;
margin-left: 40px;
}

.logo {
font-size: 1.25em;
text-decoration: none;
color: black;
margin-right: 20px;
}

.navbar-left nav a {
margin-right: 20px;
text-decoration: none;
color: black;
font-weight: 500;
font-family: 'Arial', sans-serif;
}

.navbar-right a {
margin-left: 20px;
text-decoration: none;
color: black;
font-weight: 500;
font-family: 'Arial', sans-serif;
}

.quote-container {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
}

.quote-card {
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
max-width: 700px;
position: relative;
text-align: left;
}

.quote-card h2 {
font-weight: normal;
}

.quote-card blockquote {
font-size: 2em;
font-family: 'Georgia', serif;
font-style: italic;
color: #4EC2F7;
margin: 0 0 20px 0;
line-height: 1.4;
text-align: left;
}

.quote-card footer {
font-size: 0.55em;
color: black;
font-family: 'Arial', sans-serif;
font-style: normal;
text-align: left;
font-weight: bold;
}

.vote-container {
position: absolute;
top: 10px;
right: 10px;
display: flex;
gap: 0em;
}

.heart-button {
background-color: transparent;
border: none;
cursor: pointer;
padding: 5px;
font-size: 24px;
}

.heart-button:hover {
background-color: #F0F0F0;
}

.heart-button:focus {
outline: none;
box-shadow: none;
}

footer {
background-color: white;
padding-top: 10px;
text-align: center;
border-top: 1px solid #eaeaea;
}

footer a {
color: #4EC2F7;
text-decoration: none;
}

.register-login-card {
width: 300px;
margin: 50px auto;
padding: 20px;
border-radius: 8px;
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);
background-color: #ffffff;
text-align: center;
}

h2 {
margin-bottom: 20px;
color: #333;
}

.input-container {
margin-bottom: 15px;
text-align: left;
width: 100%; /* Ensure the container takes the full width */
}

label {
display: block;
margin-bottom: 5px;
font-size: 14px;
color: #555;
}

input {
width: calc(100%); /* Add padding for both left and right */
padding: 10px;
border-radius: 4px;
border: 1px solid #ccc;
font-size: 14px;
box-sizing: border-box; /* Ensure padding doesn't affect the width */
}

input:focus {
outline: none;
border-color: #007bff;
}

.register-login-button {
width: 100%;
padding: 10px;
background-color: #007bff;
border: none;
border-radius: 4px;
color: white;
font-size: 16px;
cursor: pointer;
margin-top: 10px;
}

.register-login-button:hover {
background-color: #0056b3;
}

.error-message {
color: red;
}

.logout-btn {
margin-left: 20px;
background-color: transparent;
border: none;
cursor: pointer;
font-size: 16px;
}
28 changes: 28 additions & 0 deletions client-app/src/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import { ContextProvider } from "./pages/AppContext";
import Layout from "./Layout";
import Home from "./pages/Home";
import Register from "./pages/Register";
import Login from "./pages/Login";


function App() {
return (
<ContextProvider>
<Router>
<Layout>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Routes>
</Layout>
</Router>
</ContextProvider>
);
}

export default App;
Loading