-
Notifications
You must be signed in to change notification settings - Fork 238
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #118 from Azure-Samples/gk/generative-usecases
- Loading branch information
Showing
3 changed files
with
184 additions
and
87 deletions.
There are no files selected for viewing
61 changes: 61 additions & 0 deletions
61
typescript/frontend/src/components/modal-views/generated-sql-modal.tsx
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,61 @@ | ||
import React from "react"; | ||
|
||
interface ModalProps { | ||
isOpen: boolean; | ||
closeModal: () => void; | ||
} | ||
|
||
export default function SqlModal({ isOpen, closeModal }: ModalProps) { | ||
if (!isOpen) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<div className="fixed z-10 inset-0 overflow-y-auto"> | ||
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"> | ||
<div className="fixed inset-0 transition-opacity" aria-hidden="true"> | ||
<div className="absolute inset-0 bg-gray-500 opacity-50"></div> | ||
</div> | ||
<span className="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span> | ||
<div className="inline-block align-bottom bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"> | ||
<div className="px-4 pt-5 pb-4 sm:p-6 sm:pb-4"> | ||
{/* TODO: Fetch generated SQL */} | ||
<div className="text-center"> | ||
<h4 className="text-lg leading-6 font-medium text-white" id="modal-title"> | ||
GPT Generated SQL from prompt: | ||
</h4> | ||
<div className="mt-2"> | ||
<p className="text-sm text-gray-300"> | ||
"What is the most expensive purchase made by the user in the last year?" | ||
</p> | ||
</div> | ||
<h4 className="text-lg leading-6 font-medium text-white mt-4" id="modal-title"> | ||
Generated SQL: | ||
</h4> | ||
<p className="mt-2 mb-1 text-xs font-medium text-white sm:text-sm"> | ||
SELECT | ||
u.user_id, | ||
u.first_name, | ||
u.last_name, | ||
MAX(t.transaction_amount) AS most_expensive_purchase | ||
FROM | ||
users u | ||
JOIN | ||
transactions t ON u.user_id = t.user_id | ||
WHERE | ||
t.transaction_date {'>'}= DATE_TRUNC('year', CURRENT_DATE - INTERVAL '1 year') | ||
GROUP BY | ||
u.user_id, u.first_name, u.last_name; | ||
</p> | ||
</div> | ||
</div> | ||
<div className="px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> | ||
<button onClick={closeModal} type="button" className="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"> | ||
Close | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
15 changes: 15 additions & 0 deletions
15
typescript/frontend/src/components/transaction/custom-axis.tsx
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,15 @@ | ||
import {format} from "date-fns"; | ||
|
||
export default function CustomAxis({ x, y, payload }: any) { | ||
const date = format(new Date(payload.value * 1000), 'MMM'); | ||
return ( | ||
<g | ||
transform={`translate(${x},${y})`} | ||
className="text-xs text-gray-500 md:text-sm" | ||
> | ||
<text x={0} y={0} dy={10} textAnchor="end" fill="currentColor"> | ||
{date} | ||
</text> | ||
</g> | ||
); | ||
} |
195 changes: 108 additions & 87 deletions
195
typescript/frontend/src/components/ui/chats/spending-chart.tsx
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 |
---|---|---|
@@ -1,91 +1,112 @@ | ||
import {useState} from 'react'; | ||
import {format} from 'date-fns'; | ||
import {Area, AreaChart, ResponsiveContainer, Tooltip, XAxis} from 'recharts'; | ||
import {SpendingData} from '@/data/static/spending'; | ||
|
||
function CustomAxis({ x, y, payload }: any) { | ||
const date = format(new Date(payload.value * 1000), 'MMM'); | ||
return ( | ||
<g | ||
transform={`translate(${x},${y})`} | ||
className="text-xs text-gray-500 md:text-sm" | ||
> | ||
<text x={0} y={0} dy={10} textAnchor="end" fill="currentColor"> | ||
{date} | ||
</text> | ||
</g> | ||
); | ||
} | ||
|
||
import {useState} from "react"; | ||
import {format} from "date-fns"; | ||
import SqlModal from "@/components/modal-views/generated-sql-modal"; | ||
import {Area, AreaChart, ResponsiveContainer, Tooltip, XAxis} from "recharts"; | ||
import {SpendingData} from "@/data/static/spending"; | ||
import Button from "@/components/ui/button"; | ||
import CustomAxis from "@/components/transaction/custom-axis"; | ||
|
||
export default function SpendingChart() { | ||
let [date, setDate] = useState(Date.now()); | ||
let [spending, setSpending] = useState('34,500'); | ||
let [date, setDate] = useState(Date.now()); | ||
let [spending, setSpending] = useState('34,500'); | ||
let [isModalOpen, setIsModalOpen] = useState(false); // state variable for modal open status | ||
const formattedDate = format(new Date(date * 1000), 'MMMM d, yyyy'); | ||
return ( | ||
<div className="rounded-lg bg-white p-6 shadow-card dark:bg-light-dark sm:p-8"> | ||
<h3 className="mb-1.5 text-sm uppercase tracking-wider text-gray-600 dark:text-gray-400 sm:mb-2 sm:text-base"> | ||
Spending | ||
</h3> | ||
<div className="mb-1 text-base font-medium text-gray-900 dark:text-white sm:text-xl"> | ||
${spending} / YTD | ||
</div> | ||
<div className="text-xs text-gray-600 dark:text-gray-400 sm:text-sm"> | ||
{formattedDate} | ||
</div> | ||
<div className="mt-5 h-64 sm:mt-8 2xl:h-72 3xl:h-[340px] 4xl:h-[480px]"> | ||
<ResponsiveContainer width="100%" height="100%"> | ||
<AreaChart | ||
data={SpendingData} | ||
margin={{ | ||
top: 0, | ||
right: 0, | ||
left: 0, | ||
bottom: 0, | ||
}} | ||
onMouseMove={(data) => { | ||
if (data.isTooltipActive) { | ||
setDate( | ||
data.activePayload && data.activePayload[0].payload.date | ||
); | ||
setSpending( | ||
data.activePayload && | ||
data.activePayload[0].payload.monthlyExpense | ||
); | ||
} | ||
}} | ||
> | ||
<defs> | ||
<linearGradient | ||
id="spending-gradient" | ||
x1="0" | ||
y1="0" | ||
x2="0" | ||
y2="1" | ||
> | ||
<stop offset="5%" stopColor="#bc9aff" stopOpacity={0.5} /> | ||
<stop offset="100%" stopColor="#7645D9" stopOpacity={0} /> | ||
</linearGradient> | ||
</defs> | ||
<XAxis | ||
dataKey="date" | ||
tickLine={false} | ||
axisLine={false} | ||
tick={<CustomAxis />} | ||
interval={0} | ||
tickMargin={5} | ||
/> | ||
<Tooltip content={<></>} cursor={{ stroke: '#7645D9' }} /> | ||
<Area | ||
type="linear" | ||
dataKey="monthlyExpense" | ||
stroke="#7645D9" | ||
strokeWidth={1.5} | ||
fill="url(#spending-gradient)" | ||
/> | ||
</AreaChart> | ||
</ResponsiveContainer> | ||
</div> | ||
</div> | ||
); | ||
|
||
const closeModal = () => { // function to close the modal | ||
setIsModalOpen(false); | ||
}; | ||
|
||
const openModal = () => { // function to open the modal | ||
setIsModalOpen(true); | ||
}; | ||
|
||
return ( | ||
<div className="rounded-lg bg-white p-6 shadow-card dark:bg-light-dark sm:p-8"> | ||
<div className="rounded-lg bg-white p-6 shadow-card dark:bg-light-dark sm:p-8"> | ||
<h3 className="mb-1.5 text-sm uppercase tracking-wider text-gray-600 dark:text-gray-400 sm:mb-2 sm:text-base"> | ||
Spending | ||
</h3> | ||
<div className="mb-1 text-base font-medium text-gray-900 dark:text-white sm:text-xl"> | ||
${spending} / YTD | ||
</div> | ||
<div className="text-xs text-gray-600 dark:text-gray-400 sm:text-sm"> | ||
{formattedDate} | ||
</div> | ||
<div className="mt-5 h-64 sm:mt-8 2xl:h-72 3xl:h-[340px] 4xl:h-[480px]"> | ||
<ResponsiveContainer width="100%" height="100%"> | ||
<AreaChart | ||
data={SpendingData} | ||
margin={{ | ||
top: 0, | ||
right: 0, | ||
left: 0, | ||
bottom: 0, | ||
}} | ||
onMouseMove={(data) => { | ||
if (data.isTooltipActive) { | ||
setDate( | ||
data.activePayload && data.activePayload[0].payload.date | ||
); | ||
setSpending( | ||
data.activePayload && | ||
data.activePayload[0].payload.monthlyExpense | ||
); | ||
} | ||
}} | ||
> | ||
<defs> | ||
<linearGradient | ||
id="spending-gradient" | ||
x1="0" | ||
y1="0" | ||
x2="0" | ||
y2="1" | ||
> | ||
<stop offset="5%" stopColor="#bc9aff" stopOpacity={0.5}/> | ||
<stop offset="100%" stopColor="#7645D9" stopOpacity={0}/> | ||
</linearGradient> | ||
</defs> | ||
<XAxis | ||
dataKey="date" | ||
tickLine={false} | ||
axisLine={false} | ||
tick={<CustomAxis/>} | ||
interval={0} | ||
tickMargin={5} | ||
/> | ||
<Tooltip content={<></>} cursor={{stroke: '#7645D9'}}/> | ||
<Area | ||
type="linear" | ||
dataKey="monthlyExpense" | ||
stroke="#7645D9" | ||
strokeWidth={1.5} | ||
fill="url(#spending-gradient)" | ||
/> | ||
</AreaChart> | ||
</ResponsiveContainer> | ||
|
||
<div className="text-center mt-4"> | ||
<h3 className="text-xl font-medium tracking-tighter text-white sm:text-blue-600"> | ||
Most expensive month | ||
</h3> | ||
<p className="mt-2 mb-1 text-xs font-medium text-gray-400 sm:text-sm"> | ||
June 2023 (SQL generated by GPT) | ||
</p> | ||
<Button | ||
color="white" | ||
variant="transparent" | ||
size="mini" | ||
shape="rounded" | ||
onClick={openModal} // use openModal function here | ||
> | ||
<span className="text-xs tracking-tighter">View generated SQL</span> | ||
</Button> | ||
</div> | ||
|
||
{/* Render the SqlModal */} | ||
<SqlModal isOpen={isModalOpen} closeModal={closeModal}/> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |