From f6b6a0aefe08a92645a645da4230407c43ad5f8d Mon Sep 17 00:00:00 2001 From: BagusCodeStudio <60974759+baguscodestudio@users.noreply.github.com> Date: Wed, 1 Feb 2023 14:41:10 +0700 Subject: [PATCH] feat: Add instruction, revise & add new UI style Add second style for the UI Add Instruction feature for alternative of HelpNotification --- client.lua | 2 + web/index.html | 14 +- web/src/App.tsx | 6 +- web/src/components/Alert.tsx | 210 ++++++++++++++++++--------- web/src/components/InputKeyboard.tsx | 145 +++++++++++++----- web/src/components/Instruction.tsx | 118 +++++++++++++++ web/src/components/Modal.tsx | 23 ++- web/src/index.css | 13 ++ web/src/types.tsx | 15 ++ web/tailwind.config.js | 14 ++ 10 files changed, 434 insertions(+), 126 deletions(-) create mode 100644 web/src/components/Instruction.tsx diff --git a/client.lua b/client.lua index eb01835..ef58b08 100644 --- a/client.lua +++ b/client.lua @@ -1,6 +1,7 @@ local Settings = { HelpPosition = 'top-left', HelpAudio = true, + NotificationStyle = 'clean', -- clean or transparent NotificationPosition = 'top-right', NotificationAudio = true, Volume = 1 @@ -38,6 +39,7 @@ function SendAlert(title, message, type, duration, position) type=type, play=Settings.NotificationAudio, volume=Settings.Volume, + style=Settings.NotificationStyle, position=position or Settings.NotificationPosition, duration=duration } diff --git a/web/index.html b/web/index.html index 829bad1..f548347 100644 --- a/web/index.html +++ b/web/index.html @@ -4,7 +4,19 @@ - + + + + BCS HUD diff --git a/web/src/App.tsx b/web/src/App.tsx index 54befe8..ed913c8 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -8,6 +8,7 @@ import Modal from './components/Modal'; import InputKeyboard from './components/InputKeyboard'; import { fetchNui } from './utils/fetchNui'; import { locale } from './store/locale'; +import Instruction from './components/Instruction'; function App() { useEffect(() => { @@ -17,13 +18,14 @@ function App() { }, []); return ( - <> +
+ - +
); } diff --git a/web/src/components/Alert.tsx b/web/src/components/Alert.tsx index a1dc652..502c276 100644 --- a/web/src/components/Alert.tsx +++ b/web/src/components/Alert.tsx @@ -10,30 +10,61 @@ import { Check } from '@styled-icons/bootstrap/Check'; import { Times } from '@styled-icons/fa-solid/Times'; import { Info } from '@styled-icons/bootstrap/Info'; -const AlertTypes: AlertType = { - warning: { - color: 'bg-yellow-500', - text: 'text-yellow-600', - background: 'bg-slate-200', - icon: , +const AlertTypes: { + clean: AlertType; + transparent: AlertType; +} = { + clean: { + warning: { + color: 'bg-yellow-500', + text: 'text-yellow-600', + background: 'bg-slate-200', + icon: , + }, + success: { + color: 'bg-lime-500', + text: 'text-lime-700', + background: 'bg-slate-150', + icon: , + }, + error: { + color: 'bg-red-500', + text: 'text-red-700', + background: 'bg-slate-200', + icon: , + }, + info: { + color: 'bg-blue-500', + text: 'text-blue-700', + background: 'bg-slate-150', + icon: , + }, }, - success: { - color: 'bg-lime-500', - text: 'text-lime-700', - background: 'bg-slate-150', - icon: , - }, - error: { - color: 'bg-red-500', - text: 'text-red-700', - background: 'bg-slate-200', - icon: , - }, - info: { - color: 'bg-blue-500', - text: 'text-blue-700', - background: 'bg-slate-150', - icon: , + transparent: { + warning: { + color: 'bg-warning', + text: 'text-warning', + background: 'from-warning to-warning/15', + icon: , + }, + success: { + color: 'bg-success', + text: 'text-success', + background: 'from-success to-success/15', + icon: , + }, + error: { + color: 'bg-error', + text: 'text-error', + background: 'from-error to-error/15', + icon: , + }, + info: { + color: 'bg-blue-500', + text: 'text-blue-700', + background: 'bg-slate-150', + icon: , + }, }, }; @@ -69,10 +100,10 @@ const POSITIONS: { [key: string]: { from: string; to: string } } = { // action: 'sendAlert', // data: { // title: 'Test', -// message: -// "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.", -// type: 'success', -// duration: 3000, +// message: "Lorem Ipsum has been the industry's standard ", +// type: 'error', +// style: 'transparent', +// duration: 300000, // play: true, // position: 'top-left', // }, @@ -84,51 +115,90 @@ export const Alert = () => { useNuiEvent('sendAlert', (data) => { if (data.volume) notification.volume = data.volume; if (data.play) notification.play(); - toast.custom( - (t) => ( - -
-
( + -   -
-
+
+ {AlertTypes[data.style][data.type].icon} +
+
+
{data.title}
+

{data.message}

+
+
+ + ), + { + position: data.position + ? (data.position as ToastPosition) + : 'top-right', + duration: data.duration ? data.duration : 4000, + } + ) + : toast.custom( + (t) => ( + - {AlertTypes[data.type].icon} -
-
-
{data.title}
-

{data.message}

-
- -
- ), - { - position: data.position - ? (data.position as ToastPosition) - : 'top-right', - duration: data.duration ? data.duration : 4000, - } - ); +
+
+   +
+
+ {AlertTypes[data.style][data.type].icon} +
+
+
{data.title}
+

{data.message}

+
+
+ + ), + { + position: data.position + ? (data.position as ToastPosition) + : 'top-right', + duration: data.duration ? data.duration : 4000, + } + ); }); return ; diff --git a/web/src/components/InputKeyboard.tsx b/web/src/components/InputKeyboard.tsx index 3b7fcd6..0ecc53c 100644 --- a/web/src/components/InputKeyboard.tsx +++ b/web/src/components/InputKeyboard.tsx @@ -5,21 +5,77 @@ import { KeyboardData, KeyboardRow } from '../types'; import { debugData } from '../utils/debugData'; import { fetchNui } from '../utils/fetchNui'; -// debugData([ -// { -// action: 'openInputKeyboard', -// data: { -// title: 'Titlenya nih', -// rows: [ -// { -// title: 'what', -// placeholder: 'isinya begini', -// icon: 'fa-brands fa-cc-mastercard' -// }, -// ], -// }, -// }, -// ]); +debugData([ + { + action: 'openInputKeyboard', + data: { + title: 'Titlenya nih', + rows: [ + { + title: 'Text Label', + placeholder: 'isinya begini', + icon: 'fa-brands fa-cc-mastercard', + }, + { + title: 'Text Label', + type: 'select', + options: ['Makan', 'Eeq', 'Tidur'], + icon: 'fa-brands fa-cc-mastercard', + }, + ], + }, + }, +]); + +const TextBox: React.FC<{ + props: KeyboardRow; + index: number; + handleChange: (value: string, number: number) => void; +}> = ({ props, index, handleChange }) => ( +
+ {props.icon && } +
+
{props.title}
+ handleChange(evt.currentTarget.value, index)} + /> +
+
+); + +const SelectBox: React.FC<{ + props: KeyboardRow; + index: number; + handleChange: (value: string, number: number) => void; +}> = ({ props, index, handleChange }) => ( +
+ {props.icon && } +
+
{props.title}
+ +
+
+); const InputKeyboard = () => { const [isOpen, setOpen] = useState(false); @@ -56,33 +112,42 @@ const InputKeyboard = () => { {isOpen && (
-
{title}
- {rows.map((row, index) => ( -
-
{row.title}
-
- {row.icon && ( - - )} - handleChange(evt.currentTarget.value, index)} +
{title}
+ {rows.map((row, index) => { + if (row.type == 'select') { + return ( + -
-
- ))} - + ); + } else { + return ( + + ); + } + })} +
+ + +
)} diff --git a/web/src/components/Instruction.tsx b/web/src/components/Instruction.tsx new file mode 100644 index 0000000..64e47f0 --- /dev/null +++ b/web/src/components/Instruction.tsx @@ -0,0 +1,118 @@ +import { useState } from 'react'; +import { useNuiEvent } from '../hooks/useNuiEvent'; +import classNames from 'classnames'; +import { debugData } from '../utils/debugData'; +import { InstructionData, InstructionItem } from '../types'; + +// debugData([ +// { +// action: 'keybind', +// data: { +// title: 'Editing Furniture', +// position: 'center-right', +// items: [ +// { +// description: 'CANCEL', +// buttons: ['BACKSPACE'], +// }, +// { +// description: 'Change Speed', +// buttons: ['CAPSLOCK', 'LSHIFT'], +// }, +// ], +// }, +// }, +// ]); + +const POSITION: { [key: string]: string } = { + ['top-left']: 'top-2 left-3', + ['top-right']: 'top-2 right-3', + ['bottom-left']: 'bottom-2 left-3', + ['bottom-right']: 'bottom-2 right-3', + ['top-center']: 'top-2 left-1/2 -translate-x-1/2', + ['bottom-center']: 'bottom-2 left-1/2 -translate-x-1/2', + ['center-left']: 'left-3 top-1/2 -translate-y-1/2', + ['center-right']: 'right-3 top-1/2 -translate-y-1/2', +}; + +const Instruction = () => { + const [show, setDisplay] = useState(false); + const [text, setText] = useState(''); + const [items, setItems] = useState([]); + const [position, setPosition] = useState('top-left'); + const audio = new Audio('sounds/helpnotification.ogg'); + const Regex = new RegExp(/\~\S+\~/); + const textArray = text?.split(' '); + let fixArray: String[] = []; + + textArray?.map((word) => { + if (Regex.test(word)) { + word = word + .replace( + /\~/, + '' + ) + .replace(/\~/, ''); + fixArray.push(word); + } else fixArray.push(word); + }); + + useNuiEvent('keybind', (data) => { + setText(data.title); + if (data.volume) audio.volume = data.volume; + if (data.play) audio.play(); + if (data.position) setPosition(data.position); + setItems(data.items); + setDisplay(true); + }); + + useNuiEvent('closeKeybind', (data) => { + setText(''); + setDisplay(false); + setPosition('top-left'); + }); + + return ( + <> + {show ? ( +
+
+ {items.map((item, index) => ( + <> +
+ {item.description} +
+
+ {item.buttons.map((button) => ( + + {button} + + ))} +
+ + ))} +
+
+
+
+
+
+   +
+
+
{text}
+
+
+
+
+ ) : null} + + ); +}; + +export default Instruction; diff --git a/web/src/components/Modal.tsx b/web/src/components/Modal.tsx index 15a8bce..df10614 100644 --- a/web/src/components/Modal.tsx +++ b/web/src/components/Modal.tsx @@ -9,8 +9,8 @@ import { locale } from '../store/locale'; // { // action: 'openModal', // data: { -// title: 'what', -// text: 'Are you sure?', +// title: 'Confirmation Title', +// text: 'Are you sure to confirm this? Lorem ipsum dolor sit amet this is the standard text since the 2000s.', // }, // }, // ]); @@ -81,31 +81,28 @@ const Modal = () => { leaveFrom="opacity-100 scale-100" leaveTo="opacity-0 scale-95" > -
- +
+ {data.title}
-

{data.text}

+

{data.text}

-
+
diff --git a/web/src/index.css b/web/src/index.css index 0294da3..002b54e 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -10,6 +10,18 @@ url('./fonts/ChaletLondonNineteenSixty.ttf') format('truetype'); } +@layer components { + .rotate-left { + transform-origin: top left; + transform: rotate(-90deg) translate(-100%); + margin-top: -50%; + } + .rotation-wrapper-inner { + padding: 50% 0; + height: 0; + } +} + body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', @@ -17,6 +29,7 @@ body { sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + overflow: hidden; } code { diff --git a/web/src/types.tsx b/web/src/types.tsx index 3590267..b480f23 100644 --- a/web/src/types.tsx +++ b/web/src/types.tsx @@ -4,6 +4,7 @@ export interface AlertData { type: keyof AlertType; play?: boolean; volume?: number; + style: 'clean' | 'transparent'; position?: string; duration?: number; icon?: string; @@ -23,8 +24,22 @@ export type AlertType = { info: AlertProp; }; +export type InstructionItem = { + description: string; + buttons: string[]; +}; + +export interface InstructionData { + title: string; + play?: boolean; + volume?: number; + position?: string; + items: InstructionItem[]; +} + export interface KeyboardRow { title: string; + options?: string[]; icon?: string; type?: string; required?: boolean; diff --git a/web/tailwind.config.js b/web/tailwind.config.js index dae4d73..d3da098 100644 --- a/web/tailwind.config.js +++ b/web/tailwind.config.js @@ -5,6 +5,20 @@ module.exports = { fontFamily: { Oswald: ['Oswald', 'sans-serif'], Chalet: ['Chalet'], + NotoSans: ['Noto Sans JP', 'sans-serif'], + }, + colors: { + success: '#4D9651', + error: '#BC2325', + warning: '#F5BF5C', + 'green-active': '#00C684', + 'green-inactive': '#68C2A4', + 'red-active': '#FF584B', + 'red-inactive': '#FF776D', + 'grey-dark': '#454442', + 'grey-light': '#A9A7A7', + 'grey-darker': '#272625', + 'white-dark': '#E6E6E6', }, }, },