diff --git a/web/package-lock.json b/web/package-lock.json index 99462e85..646b5c15 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -16,6 +16,7 @@ "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-popover": "^1.1.1", "@radix-ui/react-radio-group": "^1.2.0", + "@radix-ui/react-slider": "^1.2.0", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-switch": "^1.1.0", "@radix-ui/react-toast": "^1.2.1", @@ -3002,6 +3003,11 @@ "node": ">=14" } }, + "node_modules/@radix-ui/number": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", + "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==" + }, "node_modules/@radix-ui/primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", @@ -3585,6 +3591,38 @@ } } }, + "node_modules/@radix-ui/react-slider": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.2.0.tgz", + "integrity": "sha512-dAHCDA4/ySXROEPaRtaMV5WHL8+JB/DbtyTbJjYkY0RXmKMO2Ln8DFZhywG5/mVQ4WqHDBc8smc14yPXPqZHYA==", + "dependencies": { + "@radix-ui/number": "1.1.0", + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-use-size": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", diff --git a/web/package.json b/web/package.json index 70dbcb47..404796a8 100644 --- a/web/package.json +++ b/web/package.json @@ -26,6 +26,7 @@ "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-popover": "^1.1.1", "@radix-ui/react-radio-group": "^1.2.0", + "@radix-ui/react-slider": "^1.2.0", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-switch": "^1.1.0", "@radix-ui/react-toast": "^1.2.1", diff --git a/web/src/components/ui/slider.tsx b/web/src/components/ui/slider.tsx new file mode 100644 index 00000000..0b9948b0 --- /dev/null +++ b/web/src/components/ui/slider.tsx @@ -0,0 +1,26 @@ +import * as React from "react" +import * as SliderPrimitive from "@radix-ui/react-slider" + +import { cn } from "../../lib/utils" + +const Slider = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + + +)) +Slider.displayName = SliderPrimitive.Root.displayName + +export { Slider } diff --git a/web/src/generators/components/ValueAndChance.tsx b/web/src/generators/components/ValueAndChance.tsx deleted file mode 100644 index 1a8a6910..00000000 --- a/web/src/generators/components/ValueAndChance.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import { useState } from 'react'; -import { Button } from '../../components/ui/button'; -import { Input } from '../../components/ui/input'; -import { Label } from '../../components/ui/label'; -import { - Accordion, - AccordionContent, - AccordionItem, - AccordionTrigger -} from '../../components/ui/accordion'; -import { - Command, - CommandEmpty, - CommandGroup, - CommandInput, - CommandItem, - CommandList -} from '../../components/ui/command'; -import { Popover, PopoverContent, PopoverTrigger } from '../../components/ui/popover'; -import { Check, ChevronsUpDown } from 'lucide-react'; -import { cn } from '../../lib/utils'; -import { v4 as uuidv4 } from 'uuid'; -import { GetOutfits, GetPeds, GetVehicles, GetWeapons } from '../../store/helpers'; - -export const ValueAndChance = (mode: 'ped' | 'vehicle' | 'weapon' | 'outfit') => { - let type = ''; - switch (mode) { - case 'outfit': { - type = 'Outfit'; - break; - } - case 'vehicle': { - type = 'Vehicle'; - break; - } - case 'weapon': { - type = 'Weapon'; - break; - } - case 'ped': { - type = 'Ped'; - break; - } - } - - return ( - <> -
- - - Click here to expand the config. (Type: {type}) - {Card(mode)} - - -
- - ); -}; - -const Card = (mode: 'ped' | 'vehicle' | 'weapon' | 'outfit') => { - const [isOpen, setOpen] = useState(false); - const [value, setValue] = useState(''); - - const presets: string[] = []; - - switch (mode) { - case 'outfit': { - const local = GetOutfits(); - if (local) { - local.map((preset) => { - presets.push(preset.name); - }); - } - break; - } - case 'ped': { - const local = GetPeds(); - if (local) { - local.map((preset) => { - presets.push(preset.name); - }); - } - break; - } - case 'vehicle': { - const local = GetVehicles(); - if (local) { - local.map((preset) => { - presets.push(preset.name); - }); - } - break; - } - case 'weapon': { - const local = GetWeapons(); - if (local) { - local.map((preset) => { - presets.push(preset.name); - }); - } - break; - } - } - - const id = uuidv4(); - - return ( - <> -
- -
- - - - - - - - - - No preset found. - - {presets.map((preset) => ( - { - setValue(currentValue === value ? '' : currentValue); - setOpen(false); - }}> - - {preset} - - ))} - - - - - -
-
- - ); -}; diff --git a/web/src/generators/components/ValueWithChance.tsx b/web/src/generators/components/ValueWithChance.tsx new file mode 100644 index 00000000..19be6dd5 --- /dev/null +++ b/web/src/generators/components/ValueWithChance.tsx @@ -0,0 +1,321 @@ +import { useState } from 'react'; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger +} from '../../components/ui/accordion'; +import { Check, ChevronsUpDown } from 'lucide-react'; +import { cn } from '../../lib/utils'; +import { Button } from '../../components/ui/button'; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList +} from '../../components/ui/command'; +import { Popover, PopoverContent, PopoverTrigger } from '../../components/ui/popover'; +import { Slider } from '../../components/ui/slider'; +import { v4 as uuidv4 } from 'uuid'; +import { Label } from '../../components/ui/label'; +import { GetOutfits, GetPeds, GetVehicles, GetWeapons } from '../../store/helpers'; +import { toast } from '../../components/ui/use-toast'; + +type Vwc = { + id: string; + chance: number; + value: string; + open: boolean; +}; + +type Props = { + mode: 'vehicle' | 'ped' | 'weapon' | 'outfit'; + title: string; + handleValueChange(value: string): void; +}; + +const defaultChance = 100; +const chanceMin = 1; +const chanceMax = 1000; + +export const ValueWithChance = (props: Props) => { + const [vwcItems, setVwcItems] = useState([]); + + const presets: string[] = []; + let type = 'Unknown'; + switch (props.mode) { + case 'vehicle': { + type = 'Vehicle'; + const local = GetVehicles(); + if (local) { + local.map((preset) => { + presets.push(preset.name); + }); + } + break; + } + case 'ped': { + type = 'Ped'; + const local = GetPeds(); + if (local) { + local.map((preset) => { + presets.push(preset.name); + }); + } + break; + } + case 'weapon': { + type = 'Weapon'; + const local = GetWeapons(); + if (local) { + local.map((preset) => { + presets.push(preset.name); + }); + } + break; + } + case 'outfit': { + type = 'Outfit'; + const local = GetOutfits(); + if (local) { + local.map((preset) => { + presets.push(preset.name); + }); + } + break; + } + } + + const returnJson = (values: Vwc[]) => { + const jsonBase: [number, string][] = []; + values.map((vwc) => jsonBase.push([vwc.chance, vwc.value])); + props.handleValueChange(JSON.stringify(jsonBase)); + }; + + const onAddClicked = () => { + const newValue: Vwc = { + chance: defaultChance, + value: '', + id: uuidv4(), + open: false + }; + + setVwcItems((previous) => { + const value = [...previous, newValue]; + console.log(value); + returnJson(value); + return value; + }); + }; + + const handleEditChance = (id: string, chance: number) => { + const deepCopy = vwcItems.map((vwc) => ({ ...vwc })); + const newVwcItems = deepCopy.map((vwc) => { + if (vwc.id === id) { + vwc.chance = chance; + } + return vwc; + }); + setVwcItems(() => { + returnJson(newVwcItems); + return newVwcItems; + }); + }; + + const onNewValueSelected = (id: string, value: string) => { + const deepCopy = vwcItems.map((vwc) => ({ ...vwc })); + const newVwcItems = deepCopy.map((vwc) => { + if (vwc.id === id) { + vwc.value = value; + vwc.open = false; + } + return vwc; + }); + setVwcItems(() => { + returnJson(newVwcItems); + return newVwcItems; + }); + }; + + const handleEditOpen = (id: string, isOpen: boolean) => { + const deepCopy = vwcItems.map((vwc) => ({ ...vwc })); + const newVwcItems = deepCopy.map((vwc) => { + if (vwc.id === id) { + vwc.open = isOpen; + } + return vwc; + }); + setVwcItems(() => { + returnJson(newVwcItems); + return newVwcItems; + }); + }; + + const onOperatorButtonsClicked = (id: string, value: number, multiplier: number) => { + const deepCopy = vwcItems.map((vwc) => ({ ...vwc })); + const newVwcItems = deepCopy.map((vwc) => { + if (vwc.id === id) { + const temp = vwc.chance + value * multiplier; + if (temp < chanceMin) { + toast({ + variant: 'destructive', + title: "Couldn't minus the value!", + description: + 'The value is too small to minus. The chance value must be bigger than zero!' + }); + } else if (temp > chanceMax) { + toast({ + variant: 'destructive', + title: "Couldn't plus the value!", + description: + 'The value is too big to plus. The chance value must be smaller less than 1001!' + }); + } else { + vwc.chance = temp; + } + } + return vwc; + }); + setVwcItems(() => { + returnJson(newVwcItems); + return newVwcItems; + }); + }; + + const handleDelete = (id: string) => { + const newVwcItems = vwcItems.filter((vwc) => vwc.id !== id); + setVwcItems(() => { + returnJson(newVwcItems); + return newVwcItems; + }); + }; + + return ( + <> +
+
+ + +
+ + + Click to expand the configurations. (Type: {type}) + + {vwcItems.map((item) => ( +
+
+ +
+ + + + + + +
+
+
+ handleEditChance(item.id, value[0])} + /> + handleEditOpen(item.id, value)}> + + + + + + + + No preset found. + + {presets.map((preset) => ( + { + onNewValueSelected( + item.id, + currentValue === item.value ? '' : currentValue + ); + }}> + + {preset} + + ))} + + + + + + +
+
+ ))} +
+
+
+
+ + ); +}; diff --git a/web/src/generators/components/Vector3.tsx b/web/src/generators/components/Vector3.tsx index ae4695f9..902e073d 100644 --- a/web/src/generators/components/Vector3.tsx +++ b/web/src/generators/components/Vector3.tsx @@ -1,14 +1,137 @@ +import { useState } from 'react'; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger +} from '../../components/ui/accordion'; +import { Button } from '../../components/ui/button'; +import { v4 as uuidv4 } from 'uuid'; +import { Label } from '../../components/ui/label'; +import { Input } from '../../components/ui/input'; + export interface Vector3Config { x: number; y: number; z: number; } -export const Vector3 = () => { +type V3 = { + id: string; + open: boolean; + v3: Vector3Config; +}; + +type Props = { + title: string; +}; + +export const Vector3 = (props: Props) => { + const [v3Items, setV3Items] = useState([]); + + function onAddClicked() { + const newValue: V3 = { + id: uuidv4(), + open: false, + v3: { x: 0, y: 0, z: 0 } + }; + + setV3Items((previous) => [...previous, newValue]); + } + + let newVwcItems: V3[]; + const handleEditV3 = (id: string, axes: 'x' | 'y' | 'z', value: number) => { + const deepCopy = v3Items.map((v3) => ({ ...v3 })); + newVwcItems = deepCopy.map((v3) => { + if (v3.id === id) { + switch (axes) { + case 'x': + v3.v3.x = value; + break; + case 'y': + v3.v3.y = value; + break; + case 'z': + v3.v3.z = value; + break; + } + } + return v3; + }); + }; + + const handleSaveV3 = () => { + setV3Items(newVwcItems); + }; + + const handleDelete = (id: string) => { + const newVwcItems = v3Items.filter((vwc) => vwc.id !== id); + setV3Items(newVwcItems); + }; + return ( <> -
- +
+
+ + +
+ + + + Click to expand the configurations. (Type: {'Vector3'}) + + + {v3Items.map((item) => ( +
+ + { + e.preventDefault(); + handleEditV3(item.id, 'x', e.target.valueAsNumber); + }} + /> + + { + e.preventDefault(); + handleEditV3(item.id, 'y', e.target.valueAsNumber); + }} + /> + + { + e.preventDefault(); + handleEditV3(item.id, 'z', e.target.valueAsNumber); + }} + /> + + +
+ ))} +
+
+
); diff --git a/web/src/generators/pages/Callouts/PacificBankHeist.tsx b/web/src/generators/pages/Callouts/PacificBankHeist.tsx index 4fdffc1e..fd4df93b 100644 --- a/web/src/generators/pages/Callouts/PacificBankHeist.tsx +++ b/web/src/generators/pages/Callouts/PacificBankHeist.tsx @@ -1,77 +1,275 @@ -import { zodResolver } from '@hookform/resolvers/zod'; -import { useForm } from 'react-hook-form'; -import { z } from 'zod'; import { v4 as uuidv4 } from 'uuid'; - import { Button } from '../../../components/ui/button'; import { Input } from '../../../components/ui/input'; import { toast } from '../../../components/ui/use-toast'; import { useTranslation } from 'react-i18next'; -import { ID_PEDS } from '../../../store/keys'; import { createElement, ReactElement, useEffect, useState } from 'react'; import { Switch } from '../../../components/ui/switch'; import { VehicleConfig } from '../Objects/Vehicle'; import { PedConfig } from '../Objects/Ped'; import { WeaponConfig } from '../Objects/Weapon'; -import { Vector3Config } from '../../components/Vector3'; +import { Vector3, Vector3Config } from '../../components/Vector3'; import { Vector3HConfig } from '../../components/Vector3H'; -import { ValueAndChance } from '../../components/ValueAndChance'; +import { ped, vehicle, weapon } from '../base'; +import { ValueWithChance } from '../../components/ValueWithChance'; export interface PacificBankHeistConfig { - hostage_count: number; - wife_name: string; - police_cruisers: VehicleConfig[]; - police_transporters: VehicleConfig[]; - police_riots: VehicleConfig[]; - ambulances: VehicleConfig[]; - firetrucks: VehicleConfig[]; + hostage_count?: number; + wife_name?: string; + + police_cruisers: [number, VehicleConfig][]; + police_transporters: [number, VehicleConfig][]; + police_riots: [number, VehicleConfig][]; + ambulances: [number, VehicleConfig][]; + firetrucks: [number, VehicleConfig][]; - police_officers_models: PedConfig[]; - police_swat_models: PedConfig[]; - paramedic_models: PedConfig[]; - firefighter_models: PedConfig[]; - commander_models: PedConfig[]; - wife_models: PedConfig[]; - robber_models: PedConfig[]; - hostage_models: PedConfig[]; + police_officers_models: [number, PedConfig][]; + police_swat_models: [number, PedConfig][]; + paramedic_models: [number, PedConfig][]; + firefighter_models: [number, PedConfig][]; + commander_models: [number, PedConfig][]; + wife_models: [number, PedConfig][]; + robber_models: [number, PedConfig][]; + hostage_models: [number, PedConfig][]; - officer_weapons: WeaponConfig[]; - swat_weapons: WeaponConfig[]; - robbers_weapons: WeaponConfig[]; - robbers_sub_weapons: WeaponConfig[]; - weapons_in_riot: WeaponConfig[]; + officer_weapons: [number, WeaponConfig][]; + swat_weapons: [number, WeaponConfig][]; + robbers_weapons: [number, WeaponConfig][]; + robbers_sub_weapons: [number, WeaponConfig][]; + weapons_in_riot: [number, WeaponConfig][]; - police_cruiser_positions: Vector3HConfig[]; - police_transporter_positions: Vector3HConfig[]; - riot_positions: Vector3HConfig[]; - ambulance_positions: Vector3HConfig[]; - firetruck_positions: Vector3HConfig[]; - barrier_positions: Vector3HConfig[]; - aiming_officer_positions: Vector3HConfig[]; - standing_officer_positions: Vector3HConfig[]; - normal_robbers_positions: Vector3HConfig[]; - robbers_negotiation_positions: Vector3HConfig[]; - robbers_sneak_positions: Vector3HConfig[]; - robbers_in_vault_positions: Vector3HConfig[]; - robbers_surrendering_positions: Vector3HConfig[]; - firefighter_positions: Vector3HConfig[]; - paramedic_positions: Vector3HConfig[]; - left_sitting_swat_positions: Vector3HConfig[]; - right_sitting_swat_positions: Vector3HConfig[]; - right_looking_swat_positions: Vector3HConfig[]; - hostage_positions: Vector3Config[]; - hostage_safe_position: Vector3HConfig; - commander_position: Vector3HConfig; - wife_position: Vector3HConfig; - wife_vehicle_destination: Vector3Config; + police_cruiser_positions?: Vector3HConfig[]; + police_transporter_positions?: Vector3HConfig[]; + riot_positions?: Vector3HConfig[]; + ambulance_positions?: Vector3HConfig[]; + firetruck_positions?: Vector3HConfig[]; + barrier_positions?: Vector3HConfig[]; + aiming_officer_positions?: Vector3HConfig[]; + standing_officer_positions?: Vector3HConfig[]; + normal_robbers_positions?: Vector3HConfig[]; + robbers_negotiation_positions?: Vector3HConfig[]; + robbers_sneak_positions?: Vector3HConfig[]; + robbers_in_vault_positions?: Vector3HConfig[]; + robbers_surrendering_positions?: Vector3HConfig[]; + firefighter_positions?: Vector3HConfig[]; + paramedic_positions?: Vector3HConfig[]; + left_sitting_swat_positions?: Vector3HConfig[]; + right_sitting_swat_positions?: Vector3HConfig[]; + right_looking_swat_positions?: Vector3HConfig[]; + hostage_positions?: Vector3Config[]; + hostage_safe_position?: Vector3HConfig; + commander_position?: Vector3HConfig; + wife_position?: Vector3HConfig; + wife_vehicle_destination?: Vector3Config; } export const PacificBankHeistGen = () => { + const [key0, setKey0] = useState<[number, VehicleConfig][]>([]); + const [key1, setKey1] = useState<[number, VehicleConfig][]>([]); + const [key2, setKey2] = useState<[number, VehicleConfig][]>([]); + const [key3, setKey3] = useState<[number, VehicleConfig][]>([]); + const [key4, setKey4] = useState<[number, VehicleConfig][]>([]); + const [key5, setKey5] = useState<[number, PedConfig][]>([]); + const [key6, setKey6] = useState<[number, PedConfig][]>([]); + const [key7, setKey7] = useState<[number, PedConfig][]>([]); + const [key8, setKey8] = useState<[number, PedConfig][]>([]); + const [key9, setKey9] = useState<[number, PedConfig][]>([]); + const [key10, setKey10] = useState<[number, PedConfig][]>([]); + const [key11, setKey11] = useState<[number, PedConfig][]>([]); + const [key12, setKey12] = useState<[number, PedConfig][]>([]); + const [key13, setKey13] = useState<[number, WeaponConfig][]>([]); + const [key14, setKey14] = useState<[number, WeaponConfig][]>([]); + const [key15, setKey15] = useState<[number, WeaponConfig][]>([]); + const [key16, setKey16] = useState<[number, WeaponConfig][]>([]); + const [key17, setKey17] = useState<[number, WeaponConfig][]>([]); + const { t } = useTranslation(); useEffect(() => { // updateList(); }, []); - return
{ValueAndChance('vehicle')}
; + const generate = () => { + const data: PacificBankHeistConfig = { + police_cruisers: key0, + police_transporters: key1, + police_riots: key2, + ambulances: key3, + firetrucks: key4, + + police_officers_models: key5, + police_swat_models: key6, + paramedic_models: key7, + firefighter_models: key8, + commander_models: key9, + wife_models: key10, + robber_models: key11, + hostage_models: key12, + + officer_weapons: key13, + swat_weapons: key14, + robbers_weapons: key15, + robbers_sub_weapons: key16, + weapons_in_riot: key17 + }; + console.log(JSON.stringify(data, null, 2)); + toast({ + variant: 'default', + title: t('generators.common.saved') + }); + }; + + return ( +
+

Pacific Bank Heist Generator

+ { + setKey0(vehicle(json)); + }} + /> + { + setKey1(vehicle(json)); + }} + /> + { + setKey2(vehicle(json)); + }} + /> + { + setKey3(vehicle(json)); + }} + /> + { + setKey4(vehicle(json)); + }} + /> + { + setKey5(ped(json)); + }} + /> + { + setKey6(ped(json)); + }} + /> + { + setKey7(ped(json)); + }} + /> + { + setKey8(ped(json)); + }} + /> + { + setKey9(ped(json)); + }} + /> + { + setKey10(ped(json)); + }} + /> + { + setKey11(ped(json)); + }} + /> + { + setKey12(ped(json)); + }} + /> + { + setKey13(weapon(json)); + }} + /> + { + setKey14(weapon(json)); + }} + /> + { + setKey15(weapon(json)); + }} + /> + { + setKey16(weapon(json)); + }} + /> + { + setKey17(weapon(json)); + }} + /> + + +
+ ); }; diff --git a/web/src/generators/pages/base.ts b/web/src/generators/pages/base.ts new file mode 100644 index 00000000..95cd7ccc --- /dev/null +++ b/web/src/generators/pages/base.ts @@ -0,0 +1,57 @@ +import { GetOutfits, GetPeds, GetVehicles, GetWeapons } from "../../store/helpers"; +import { PedConfig } from "./Objects/Ped"; +import { VehicleConfig } from "./Objects/Vehicle"; +import { WeaponConfig } from "./Objects/Weapon"; +import { Outfit } from "./Outfits/Outfits"; + +export const vehicle = (json: string): [number, VehicleConfig][] => { + const values: [number, string][] = JSON.parse(json) as [number, string][]; + const vehicles = GetVehicles(); + const temp: [number, VehicleConfig][] = []; + values.map((value) => { + const config: VehicleConfig | undefined = vehicles?.find((x) => x.name == value[1]); + if (config) { + temp.push([value[0], config]); + } + }); + return temp; +}; + +export const ped = (json: string): [number, PedConfig][] => { + const values: [number, string][] = JSON.parse(json) as [number, string][]; + const peds = GetPeds(); + const temp: [number, PedConfig][] = []; + values.map((value) => { + const config: PedConfig | undefined = peds?.find((x) => x.name == value[1]); + if (config) { + temp.push([value[0], config]); + } + }); + return temp; +}; + +export const weapon = (json: string): [number, WeaponConfig][] => { + const values: [number, string][] = JSON.parse(json) as [number, string][]; + const weapons = GetWeapons(); + const temp: [number, WeaponConfig][] = []; + values.map((value) => { + const config: WeaponConfig | undefined = weapons?.find((x) => x.name == value[1]); + if (config) { + temp.push([value[0], config]); + } + }); + return temp; +}; + +export const outfit = (json: string): [number, Outfit][] => { + const values: [number, string][] = JSON.parse(json) as [number, string][]; + const outfit = GetOutfits(); + const temp: [number, Outfit][] = []; + values.map((value) => { + const config: Outfit | undefined = outfit?.find((x) => x.name == value[1]); + if (config) { + temp.push([value[0], config]); + } + }); + return temp; +}; \ No newline at end of file diff --git a/web/src/sleep.ts b/web/src/sleep.ts new file mode 100644 index 00000000..623801b9 --- /dev/null +++ b/web/src/sleep.ts @@ -0,0 +1,2 @@ +const sleep = (ms: number) => new Promise((res) => setTimeout(res, ms)); +export default sleep; diff --git a/web/src/store/helpers.ts b/web/src/store/helpers.ts index c6cdf0c3..1072b72a 100644 --- a/web/src/store/helpers.ts +++ b/web/src/store/helpers.ts @@ -2,7 +2,7 @@ import { PedConfig } from '../generators/pages/Objects/Ped'; import { VehicleConfig } from '../generators/pages/Objects/Vehicle'; import { WeaponConfig } from '../generators/pages/Objects/Weapon'; import { Outfit } from '../generators/pages/Outfits/Outfits'; -import { ID_VEHICLES, ID_PEDS, ID_WEAPONS, ID_OUTFITS } from './keys'; +import { ID_VEHICLES, ID_PEDS, ID_WEAPONS, ID_OUTFITS, ID_PACIFIC_BANK_HEIST } from './keys'; export function GetVehicles(): VehicleConfig[] | null { const temp: string | null = localStorage.getItem(ID_VEHICLES); @@ -111,3 +111,21 @@ export function SetOutfits(value: Outfit[]) { localStorage.setItem(ID_OUTFITS, JSON.stringify(value)); } } + +export function GetCalloutSettings(id: string): T[] | null { + const temp: string | null = localStorage.getItem(id); + if (temp) { + return JSON.parse(temp) as T[]; + } + + return null; +} + +export function SetCalloutSettings(id: string, value: string) { + const local = GetCalloutSettings(id); + if (local) { + localStorage.setItem(id, JSON.stringify([...local, ...value])); + } else { + localStorage.setItem(id, JSON.stringify(value)); + } +} diff --git a/web/src/store/keys.ts b/web/src/store/keys.ts index 97c00d38..9a36ad06 100644 --- a/web/src/store/keys.ts +++ b/web/src/store/keys.ts @@ -4,3 +4,5 @@ export const ID_VEHICLES = 'JPC_VEHICLES'; export const ID_PEDS = 'JPC_PEDS'; export const ID_WEAPONS = 'JPC_WEAPONS'; export const ID_OUTFITS = 'JPC_OUTFITS'; + +export const ID_PACIFIC_BANK_HEIST = 'JPC_CALLOUT_PBH'; diff --git a/web/src/styles/globals.css b/web/src/styles/globals.css index 76f28f49..ee7aa519 100644 --- a/web/src/styles/globals.css +++ b/web/src/styles/globals.css @@ -5,6 +5,7 @@ @layer base { :root { --background: rgb(255, 255, 255); + --background-sub: rgb(172, 172, 172); --foreground: rgb(7, 15, 37); --card: rgb(255, 255, 255); --card-foreground: rgb(2, 8, 23); @@ -33,6 +34,7 @@ .dark { --background: rgb(38, 40, 46); + --background-sub: rgb(131, 131, 131); --foreground: rgb(247, 249, 251); --card: rgb(2, 8, 23); --card-foreground: rgb(247, 249, 251); @@ -159,8 +161,8 @@ a:hover { } .mainContent code { - background-color: var(--card); - border: 1px solid var(--card); + background-color: var(--background-sub); + border: 1px solid var(--background-sub); border-radius: 10px; padding: 3px; } @@ -174,7 +176,7 @@ a:hover { border: 2px solid var(--border); border-radius: 10px; padding: 7px; - background-color: var(--card); + background-color: var(--background-sub); } footer { @@ -275,7 +277,7 @@ footer p { } .generator-main > .list p:hover { - background: var(--card); + background: var(--background-sub); } .generator-main > .list p:active { @@ -308,19 +310,54 @@ footer p { display: inline-flex; } -.value-and-chance > div > div { - margin: 10px; +.callout-generator-main { + margin: 0 20px 0 20px; } -.vac-item { +.vwc { margin: 5px 5px 5px 5px; } -.vac-flex { +.vwc-header { + display: flex; + align-items: center; +} + +.vwc-header label { + font-size: 25px; + margin: 5px 5px 5px 5px; +} + +.vwc-header button { + display: block; + margin: 5px 5px 0 auto; +} + +.vwc-root { + margin: 10px 5px 10px 5px; + padding: 5px 5px 5px 5px; + border-radius: 10px; + background: var(--background-sub); +} + +.vwc-flex { display: flex; + align-items: center; } -.vac-item input, -.vac-item button { +.vwc-flex-buttons { + display: block; + margin: 0 0 0 auto; +} + +.vwc-flex .op-btn, +.vwc-flex label , +.vwc-flex input{ margin: 5px 5px 5px 5px; + font-size: 15px; + justify-content: center; +} + +.vwc-flex-child { + margin: 0 5px 0 5px; }