From 400f6988a5fc8d23a940ba591eb0b77ef5d01dd1 Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Thu, 29 Aug 2024 16:52:08 +0200 Subject: [PATCH 01/79] refactor: Move layout back to storage page This is done so it doesn't apply the storage header to all subpages as well --- src/app/[locale]/(default)/storage/layout.tsx | 40 ------------------- src/app/[locale]/(default)/storage/page.tsx | 23 +++++++++++ 2 files changed, 23 insertions(+), 40 deletions(-) delete mode 100644 src/app/[locale]/(default)/storage/layout.tsx diff --git a/src/app/[locale]/(default)/storage/layout.tsx b/src/app/[locale]/(default)/storage/layout.tsx deleted file mode 100644 index c941e8f..0000000 --- a/src/app/[locale]/(default)/storage/layout.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { useTranslations } from 'next-intl'; - -import { Button } from '@/components/ui/Button'; - -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from '@/components/ui/Tooltip'; -import { ShoppingCart } from 'lucide-react'; - -export default function StorageLayout({ - children, -}: { - children: React.ReactNode; -}) { - const t = useTranslations('storage'); - - return ( - <> -
-

{t('title')}

- - - - - - -

{t('tooltips.viewShoppingCart')}

-
-
-
-
- {children} - - ); -} diff --git a/src/app/[locale]/(default)/storage/page.tsx b/src/app/[locale]/(default)/storage/page.tsx index 26128df..6ab9832 100644 --- a/src/app/[locale]/(default)/storage/page.tsx +++ b/src/app/[locale]/(default)/storage/page.tsx @@ -24,6 +24,14 @@ import { SelectValue, } from '@/components/ui/Select'; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from '@/components/ui/Tooltip'; +import { ShoppingCart } from 'lucide-react'; + export async function generateMetadata({ params: { locale }, }: { @@ -84,6 +92,21 @@ export default function StoragePage({ return ( <> +
+

{t('title')}

+ + + + + + +

{t('tooltips.viewShoppingCart')}

+
+
+
+
-
diff --git a/src/components/storage/CategorySelector.tsx b/src/components/storage/CategorySelector.tsx new file mode 100644 index 0000000..05d8718 --- /dev/null +++ b/src/components/storage/CategorySelector.tsx @@ -0,0 +1,43 @@ +'use client'; +import { useTranslations } from 'next-intl'; +import { useQueryState } from 'nuqs'; +import { createSearchParamsCache, parseAsString } from 'nuqs/parsers'; +import { Combobox } from '../ui/Combobox'; + +type CategorySelectorProps = { + categories: { + value: string; + label: string; + }[]; + t: { + category: string; + sort: string; + defaultDescription: string; + defaultPlaceholder: string; + }; +}; + +function CategorySelector({ categories, t }: CategorySelectorProps) { + const [category, setCategory] = useQueryState( + t.category, + parseAsString.withDefault(''), + ); + const [sort, setSort] = useQueryState(t.sort, parseAsString.withDefault('')); + + function valueCallback(category: string | null) { + setCategory(category); + } + + return ( + + ); +} + +export { CategorySelector }; diff --git a/src/components/storage/ShoppingCartClearButton.tsx b/src/components/storage/ShoppingCartClearButton.tsx index 7674993..0ad7aae 100644 --- a/src/components/storage/ShoppingCartClearButton.tsx +++ b/src/components/storage/ShoppingCartClearButton.tsx @@ -3,7 +3,7 @@ import { Button } from '@/components/ui/Button'; import { X } from 'lucide-react'; import { useLocalStorage } from 'usehooks-ts'; -function ShoppingCartClearButton({ caption }: { caption: string }) { +async function ShoppingCartClearButton({ caption }: { caption: string }) { const [cart, setCart] = useLocalStorage('shopping-cart', []); function clearCart() { diff --git a/src/components/ui/Combobox.tsx b/src/components/ui/Combobox.tsx index 9fe99fe..c0738d7 100644 --- a/src/components/ui/Combobox.tsx +++ b/src/components/ui/Combobox.tsx @@ -29,6 +29,7 @@ type ComboboxProps = { defaultPlaceholder: string; buttonClassName?: string; contentClassName?: string; + valueCallback?: (value: string | null) => void; }; function Combobox({ @@ -37,9 +38,10 @@ function Combobox({ defaultPlaceholder, buttonClassName, contentClassName, + valueCallback, }: ComboboxProps) { const [open, setOpen] = React.useState(false); - const [value, setValue] = React.useState(''); + const [value, setValue] = React.useState(null); return ( @@ -67,8 +69,14 @@ function Combobox({ key={choice.value} value={choice.value} onSelect={(currentValue) => { - setValue(currentValue === value ? '' : currentValue); + // Set newValue to null if user selects the same value twice + const newValue = + currentValue === value ? null : currentValue; + setValue(newValue); setOpen(false); + if (valueCallback) { + valueCallback(newValue); + } }} > Date: Sun, 15 Sep 2024 16:46:59 +0200 Subject: [PATCH 17/79] feat: Add sorting to search params --- src/app/[locale]/(default)/storage/page.tsx | 39 ++++++---------- src/components/storage/CategorySelector.tsx | 1 - src/components/storage/SortSelector.tsx | 50 +++++++++++++++++++++ 3 files changed, 64 insertions(+), 26 deletions(-) create mode 100644 src/components/storage/SortSelector.tsx diff --git a/src/app/[locale]/(default)/storage/page.tsx b/src/app/[locale]/(default)/storage/page.tsx index 6fba8ca..f228ef7 100644 --- a/src/app/[locale]/(default)/storage/page.tsx +++ b/src/app/[locale]/(default)/storage/page.tsx @@ -8,13 +8,7 @@ import { ItemCard } from '@/components/storage/ItemCard'; import { Button } from '@/components/ui/Button'; import { Combobox } from '@/components/ui/Combobox'; import { SearchBar } from '@/components/ui/SearchBar'; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from '@/components/ui/Select'; + import { Tooltip, TooltipContent, @@ -25,6 +19,7 @@ import { ShoppingCart } from 'lucide-react'; import { Link } from '@/lib/navigation'; import { CategorySelector } from '@/components/storage/CategorySelector'; +import { SortSelector } from '@/components/storage/SortSelector'; export async function generateMetadata({ params: { locale }, @@ -78,11 +73,11 @@ export default function StoragePage({ ]; const filters = [ - 'select.popularity', - 'select.sortDescending', - 'select.sortAscending', - 'select.name', - ] as const; + { name: t('select.popularity'), urlName: 'popularity' }, + { name: t('select.sortDescending'), urlName: 'descending' }, + { name: t('select.sortAscending'), urlName: 'ascending' }, + { name: t('select.name'), urlName: 'name' }, + ]; return ( <> @@ -105,19 +100,13 @@ export default function StoragePage({
- - + { + const filterUrlName = filters.find((f) => f.name === value)?.urlName; + if (filterUrlName) { + setFilter(filterUrlName); + } + }} + > + + + + + {filters.map((filter) => ( + + {filter.name} + + ))} + + + ); +} +export { SortSelector }; From a9ab1a9e92da954ea58792250d205a9081a32f02 Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Sun, 15 Sep 2024 17:10:14 +0200 Subject: [PATCH 18/79] fix: Use search params for default filters --- src/app/[locale]/(default)/storage/page.tsx | 2 ++ src/components/storage/CategorySelector.tsx | 10 ++++++++-- src/components/storage/SortSelector.tsx | 10 +++++++--- src/components/ui/Combobox.tsx | 4 +++- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/app/[locale]/(default)/storage/page.tsx b/src/app/[locale]/(default)/storage/page.tsx index f228ef7..84feeac 100644 --- a/src/app/[locale]/(default)/storage/page.tsx +++ b/src/app/[locale]/(default)/storage/page.tsx @@ -106,6 +106,7 @@ export default function StoragePage({ sort: t_ui('sort'), defaultPlaceholder: t('select.defaultPlaceholder'), }} + searchParams={searchParams} />
diff --git a/src/components/storage/CategorySelector.tsx b/src/components/storage/CategorySelector.tsx index e64fb4d..a14f989 100644 --- a/src/components/storage/CategorySelector.tsx +++ b/src/components/storage/CategorySelector.tsx @@ -15,12 +15,17 @@ type CategorySelectorProps = { defaultDescription: string; defaultPlaceholder: string; }; + searchParams: Record; }; -function CategorySelector({ categories, t }: CategorySelectorProps) { +function CategorySelector({ + categories, + t, + searchParams, +}: CategorySelectorProps) { const [category, setCategory] = useQueryState( t.category, - parseAsString.withDefault(''), + parseAsString.withDefault(searchParams.category?.toString() ?? ''), ); function valueCallback(category: string | null) { @@ -35,6 +40,7 @@ function CategorySelector({ categories, t }: CategorySelectorProps) { buttonClassName='w-full lg:w-[250px]' contentClassName='w-full lg:w-[200px]' valueCallback={valueCallback} + initialValue={category} /> ); } diff --git a/src/components/storage/SortSelector.tsx b/src/components/storage/SortSelector.tsx index 50aeb54..c58108f 100644 --- a/src/components/storage/SortSelector.tsx +++ b/src/components/storage/SortSelector.tsx @@ -13,16 +13,17 @@ type SortSelectorProps = { name: string; urlName: string; }[]; - filtersUrlNames: string; t: { sort: string; defaultPlaceholder: string; }; + searchParams: Record; }; -function SortSelector({ filters, t }: SortSelectorProps) { + +function SortSelector({ filters, t, searchParams }: SortSelectorProps) { const [filter, setFilter] = useQueryState( t.sort, - parseAsString.withDefault(''), + parseAsString.withDefault(searchParams.sort?.toString() ?? ''), ); return ( @@ -33,6 +34,9 @@ function SortSelector({ filters, t }: SortSelectorProps) { setFilter(filterUrlName); } }} + defaultValue={ + filters.find((f) => f.urlName === filter)?.name ?? undefined + } > diff --git a/src/components/ui/Combobox.tsx b/src/components/ui/Combobox.tsx index c0738d7..b4bfccb 100644 --- a/src/components/ui/Combobox.tsx +++ b/src/components/ui/Combobox.tsx @@ -30,6 +30,7 @@ type ComboboxProps = { buttonClassName?: string; contentClassName?: string; valueCallback?: (value: string | null) => void; + initialValue?: string; }; function Combobox({ @@ -39,9 +40,10 @@ function Combobox({ buttonClassName, contentClassName, valueCallback, + initialValue, }: ComboboxProps) { const [open, setOpen] = React.useState(false); - const [value, setValue] = React.useState(null); + const [value, setValue] = React.useState(initialValue ?? ''); return ( From 4dac0e6b223bcf3e66e2cb129e6da252d13c155f Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:28:22 +0200 Subject: [PATCH 19/79] feat: Add WIP LoanForm --- .../(default)/storage/item/new/page.tsx | 3 + .../(default)/storage/shopping-cart/page.tsx | 2 + src/components/storage/LoanForm.tsx | 138 ++++++++++++++ src/components/ui/Calendar.tsx | 68 +++++++ src/components/ui/DatePicker.tsx | 73 +++++++ src/components/ui/Form.tsx | 179 ++++++++++++++++++ src/components/ui/Label.tsx | 26 +++ 7 files changed, 489 insertions(+) create mode 100644 src/app/[locale]/(default)/storage/item/new/page.tsx create mode 100644 src/components/storage/LoanForm.tsx create mode 100644 src/components/ui/Calendar.tsx create mode 100644 src/components/ui/DatePicker.tsx create mode 100644 src/components/ui/Form.tsx create mode 100644 src/components/ui/Label.tsx diff --git a/src/app/[locale]/(default)/storage/item/new/page.tsx b/src/app/[locale]/(default)/storage/item/new/page.tsx new file mode 100644 index 0000000..6ec7220 --- /dev/null +++ b/src/app/[locale]/(default)/storage/item/new/page.tsx @@ -0,0 +1,3 @@ +export default function NewItemPage() { + return

New item page

; +} diff --git a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx index c463c9a..c4d6b54 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx @@ -1,3 +1,4 @@ +import { LoanForm } from '@/components/storage/LoanForm'; import { ShoppingCartClearButton } from '@/components/storage/ShoppingCartClearButton'; import { ShoppingCartTable } from '@/components/storage/ShoppingCartTable'; import { Button } from '@/components/ui/Button'; @@ -36,6 +37,7 @@ export default function StorageShoppingCartPage({
+ ); } diff --git a/src/components/storage/LoanForm.tsx b/src/components/storage/LoanForm.tsx new file mode 100644 index 0000000..492ff05 --- /dev/null +++ b/src/components/storage/LoanForm.tsx @@ -0,0 +1,138 @@ +'use client'; + +import { Button } from '@/components/ui/Button'; +import { DatePicker } from '@/components/ui/DatePicker'; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from '@/components/ui/Form'; +import { Input } from '@/components/ui/Input'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; + +const formSchema = z.object({ + name: z.string().min(1), + email: z.string().email(), + phone: z.string(), + returnBy: z.date().min(new Date()), +}); + +function LoanForm() { + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + name: '', + email: '', + phone: '', + returnBy: new Date(), + }, + }); + + function onSubmit(values: z.infer) { + console.log(values); + } + + return ( +
+ +
+ ( + + Username + + + + Person lending the item(s). + + + )} + /> + ( + + Email + + + + {/* + This is your public display name. + */} + + + )} + /> + ( + + Phone number + + + + {/* + This is your public display name. + */} + + + )} + /> +
+
+ ( + + Username + + + + + This is your public display name. + + + + )} + /> +
+ + {/* ( + + Username + + + + + This is your public display name. + + + + )} + /> */} + + + ); +} + +export { LoanForm }; diff --git a/src/components/ui/Calendar.tsx b/src/components/ui/Calendar.tsx new file mode 100644 index 0000000..3f41547 --- /dev/null +++ b/src/components/ui/Calendar.tsx @@ -0,0 +1,68 @@ +'use client'; + +import { ChevronLeft, ChevronRight } from 'lucide-react'; +import type * as React from 'react'; +import { DayPicker } from 'react-day-picker'; + +import { buttonVariants } from '@/components/ui/Button'; +import { cx } from '@/lib/utils'; + +export type CalendarProps = React.ComponentProps; + +function Calendar({ + className, + classNames, + showOutsideDays = true, + locale, + ...props +}: CalendarProps) { + return ( + , + IconRight: ({ ...props }) => , + }} + weekStartsOn={1} + {...props} + /> + ); +} +Calendar.displayName = 'Calendar'; + +export { Calendar }; diff --git a/src/components/ui/DatePicker.tsx b/src/components/ui/DatePicker.tsx new file mode 100644 index 0000000..118c552 --- /dev/null +++ b/src/components/ui/DatePicker.tsx @@ -0,0 +1,73 @@ +'use client'; + +import { format } from 'date-fns'; +import { Calendar as CalendarIcon } from 'lucide-react'; +import * as React from 'react'; + +import { Button } from '@/components/ui/Button'; +import { Calendar } from '@/components/ui/Calendar'; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from '@/components/ui/Popover'; +import { cx } from '@/lib/utils'; +import type { Matcher } from 'react-day-picker'; + +type DatePickerProps = { + initialDate?: Date; + dateCallback?: (date: Date) => void; + disabled?: Matcher | Matcher[]; + buttonClassName?: string; +}; + +/** + * This is a sligtly modified version of shadcn's Date Picker built on top of Calendar. + * The component has a state, but also allows adding an additional date callback function which + * provides a way to have side effects and/or state updates on the parent component whenever a new date is selected. + */ +function DatePicker({ + initialDate, + dateCallback, + disabled, + buttonClassName, +}: DatePickerProps) { + const [date, setDate] = React.useState(initialDate ?? new Date()); + + function handleDateChange(date: Date | undefined) { + if (!date) return; + setDate(date); + if (dateCallback) { + dateCallback(date); + } + } + + return ( + + + + + + handleDateChange(date)} + initialFocus + disabled={disabled} + /> + + + ); +} + +export { DatePicker }; diff --git a/src/components/ui/Form.tsx b/src/components/ui/Form.tsx new file mode 100644 index 0000000..e4c37de --- /dev/null +++ b/src/components/ui/Form.tsx @@ -0,0 +1,179 @@ +'use client'; + +import type * as LabelPrimitive from '@radix-ui/react-label'; +import { Slot } from '@radix-ui/react-slot'; +import * as React from 'react'; +import { + Controller, + type ControllerProps, + type FieldPath, + type FieldValues, + FormProvider, + useFormContext, +} from 'react-hook-form'; + +import { Label } from '@/components/ui/Label'; +import { cx } from '@/lib/utils'; + +const Form = FormProvider; + +type FormFieldContextValue< + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath, +> = { + name: TName; +}; + +const FormFieldContext = React.createContext( + {} as FormFieldContextValue, +); + +const FormField = < + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath, +>({ + ...props +}: ControllerProps) => { + return ( + + + + ); +}; + +const useFormField = () => { + const fieldContext = React.useContext(FormFieldContext); + const itemContext = React.useContext(FormItemContext); + const { getFieldState, formState } = useFormContext(); + + const fieldState = getFieldState(fieldContext.name, formState); + + if (!fieldContext) { + throw new Error('useFormField should be used within '); + } + + const { id } = itemContext; + + return { + id, + name: fieldContext.name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState, + }; +}; + +type FormItemContextValue = { + id: string; +}; + +const FormItemContext = React.createContext( + {} as FormItemContextValue, +); + +const FormItem = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + const id = React.useId(); + + return ( + +
+ + ); +}); +FormItem.displayName = 'FormItem'; + +const FormLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + const { error, formItemId } = useFormField(); + + return ( +
- +
+

{t('borrowNow')}

+ +
); } diff --git a/src/components/storage/LoanForm.tsx b/src/components/storage/LoanForm.tsx index 492ff05..7cd77b0 100644 --- a/src/components/storage/LoanForm.tsx +++ b/src/components/storage/LoanForm.tsx @@ -19,11 +19,25 @@ import { z } from 'zod'; const formSchema = z.object({ name: z.string().min(1), email: z.string().email(), - phone: z.string(), + phone: z.string().min(1), returnBy: z.date().min(new Date()), }); -function LoanForm() { +type LoanFormParams = { + t: { + name: string; + nameDescription: string; + email: string; + emailExample: string; + phoneNumber: string; + phoneNumberDescription: string; + returnBy: string; + returnByDescription: string; + submit: string; + }; +}; + +function LoanForm({ t }: LoanFormParams) { const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { @@ -35,6 +49,7 @@ function LoanForm() { }); function onSubmit(values: z.infer) { + // TODO: Add new loan to database console.log(values); } @@ -47,11 +62,11 @@ function LoanForm() { name='name' render={({ field }) => ( - Username + {t.name} - + - Person lending the item(s). + {t.nameDescription} )} @@ -61,13 +76,10 @@ function LoanForm() { name='email' render={({ field }) => ( - Email + {t.email} - + - {/* - This is your public display name. - */} )} @@ -77,25 +89,23 @@ function LoanForm() { name='phone' render={({ field }) => ( - Phone number + {t.phoneNumber} - + - {/* - This is your public display name. - */} + {t.phoneNumberDescription} )} /> -
+
( - Username + {t.returnBy} - - This is your public display name. - + {t.returnByDescription} )} />
- - {/* ( - - Username - - - - - This is your public display name. - - - - )} - /> */} ); diff --git a/src/components/ui/Label.tsx b/src/components/ui/Label.tsx index 31bafe8..0fe725c 100644 --- a/src/components/ui/Label.tsx +++ b/src/components/ui/Label.tsx @@ -1,14 +1,14 @@ 'use client'; import * as LabelPrimitive from '@radix-ui/react-label'; -import { type VariantProps, cva } from 'class-variance-authority'; +import { type VariantProps, cva } from 'cva'; import * as React from 'react'; import { cx } from '@/lib/utils'; -const labelVariants = cva( - 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', -); +const labelVariants = cva({ + base: 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', +}); const Label = React.forwardRef< React.ElementRef, From 984def6468051d8a7043fa75a979740897cb3fe4 Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Thu, 19 Sep 2024 18:23:13 +0200 Subject: [PATCH 21/79] fix: Translate LoanForm title --- messages/en.json | 4 +- messages/no.json | 4 +- .../(default)/storage/shopping-cart/page.tsx | 2 +- src/components/storage/LoanForm.tsx | 144 +++++++++--------- .../storage/ShoppingCartClearButton.tsx | 6 +- 5 files changed, 83 insertions(+), 77 deletions(-) diff --git a/messages/en.json b/messages/en.json index e7227ff..85626d8 100644 --- a/messages/en.json +++ b/messages/en.json @@ -87,10 +87,10 @@ "tableDescription": "A list of your shopping cart items.", "backToStorage": "Back to storage", "cartEmpty": "Your shopping cart is empty.", - "clearCart": "Empty shopping cart", - "borrowNow": "Borrow now" + "clearCart": "Empty shopping cart" }, "loanForm": { + "borrowNow": "Borrow now", "name": "Name", "nameDescription": "Person lending the item(s).", "email": "Email", diff --git a/messages/no.json b/messages/no.json index d307092..ad21291 100644 --- a/messages/no.json +++ b/messages/no.json @@ -87,10 +87,10 @@ "tableDescription": "En liste over handlekurven din.", "backToStorage": "Tilbake til lageret", "cartEmpty": "Handlekurven din er tom.", - "clearCart": "Tøm handlekurven", - "borrowNow": "Lån nå" + "clearCart": "Tøm handlekurven" }, "loanForm": { + "borrowNow": "Lån nå", "name": "Navn", "nameDescription": "Personen som låner gjenstanden(e).", "email": "Epost", diff --git a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx index 19e0a06..4876bf2 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx @@ -26,6 +26,7 @@ export default function StorageShoppingCartPage({ }; const loanFormMessages = { + borrowNow: tLoanForm('borrowNow'), name: tLoanForm('name'), nameDescription: tLoanForm('nameDescription'), email: tLoanForm('email'), @@ -51,7 +52,6 @@ export default function StorageShoppingCartPage({
-

{t('borrowNow')}

diff --git a/src/components/storage/LoanForm.tsx b/src/components/storage/LoanForm.tsx index 7cd77b0..c1f34ee 100644 --- a/src/components/storage/LoanForm.tsx +++ b/src/components/storage/LoanForm.tsx @@ -25,6 +25,7 @@ const formSchema = z.object({ type LoanFormParams = { t: { + borrowNow: string; name: string; nameDescription: string; email: string; @@ -54,76 +55,79 @@ function LoanForm({ t }: LoanFormParams) { } return ( -
- -
- ( - - {t.name} - - - - {t.nameDescription} - - - )} - /> - ( - - {t.email} - - - - - - )} - /> - ( - - {t.phoneNumber} - - - - {t.phoneNumberDescription} - - - )} - /> -
-
- ( - - {t.returnBy} - - - - {t.returnByDescription} - - - )} - /> -
- -
- + <> +

{t.borrowNow}

+
+ +
+ ( + + {t.name} + + + + {t.nameDescription} + + + )} + /> + ( + + {t.email} + + + + + + )} + /> + ( + + {t.phoneNumber} + + + + {t.phoneNumberDescription} + + + )} + /> +
+
+ ( + + {t.returnBy} + + + + {t.returnByDescription} + + + )} + /> +
+ +
+ + ); } diff --git a/src/components/storage/ShoppingCartClearButton.tsx b/src/components/storage/ShoppingCartClearButton.tsx index 0ad7aae..aa78e3c 100644 --- a/src/components/storage/ShoppingCartClearButton.tsx +++ b/src/components/storage/ShoppingCartClearButton.tsx @@ -3,8 +3,10 @@ import { Button } from '@/components/ui/Button'; import { X } from 'lucide-react'; import { useLocalStorage } from 'usehooks-ts'; -async function ShoppingCartClearButton({ caption }: { caption: string }) { - const [cart, setCart] = useLocalStorage('shopping-cart', []); +function ShoppingCartClearButton({ caption }: { caption: string }) { + const [cart, setCart] = useLocalStorage('shopping-cart', [], { + initializeWithValue: false, + }); function clearCart() { setCart([]); From 5b44dc58b921c6f08b5ac21c9cac56c9df368f47 Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Thu, 19 Sep 2024 18:40:49 +0200 Subject: [PATCH 22/79] fix: Lint with biome --- bun.lockb | Bin 158157 -> 219341 bytes src/app/[locale]/(default)/storage/page.tsx | 2 +- src/components/ui/Form.tsx | 4 ++-- src/components/ui/Label.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bun.lockb b/bun.lockb index cc7295d6849e1e91a4a9fb50e1578bed9470d5d1..f99eb7dcc6485189268aa2e45c09b179d0903eea 100755 GIT binary patch literal 219341 zcmeFa2|Sfs^#6YdNv4ECGDYUGnKEQ1QN|1zGh`kLsZcbMG#HyyG?z*fl}a=x6;hfs z4=R;3$bT*8*|+E3@4dHkobUhldVOE7yI&q3dq4ZV*4k_DXFR8Sl@xRm;$n6DLnC#9 zBIn5aCqxRsrWGC)Fnd;Lc#zhtsMrX!AMPx3he#61KbRR zdTfwiKs>aZ1%tSMI1hs{05lBhBA`#8pD^fMP;6J`WiW(5L*umOhWN!Z;zImlqk%uv zpTQ7^_Klztpjn`UK+7OBv=bi}9_kPM5}JTD>cA)s+V5p#lK8I1c-$MFY5 zg-1b^5ePxz_)mc1cm+k7`wu`}0P1d_IPQAL19CN>*uMf4cBSqC#r(X3L8BH!9ZaMK z`o+WKM#e=)#l;852E|1t#KeI+Mr2STrk$}328;Pv0V)L=1B&_ZpxVtqF>Y0=T?7>S zeILxs(^F8)&s|WA(-8b(eCRJAE{;(G#xd@EP~0Es7a0`_OQ0V5_l^S;$Kjt4=O2~C zV5os}tna4U4^Z_IsN=XILgV8x?$wl^3{dPJ5gHj95gHdi8YT_<-33K|3NRU1_mA}p z2#RAc@}Z9H_dzkwx-hA|c7tMrgY+RT;4m&&U%}x~{tOwIMC@M;?U>J5esS?J;6FAf zAue=Q5@R#$htN{}+<93s49xRT&if@lyH>{9^x$ zpcwZaO0z+civ@)gq`HIRc)FFDan96b#%T^0F~@faR0Q^)2E~4*ptv4pm^0%DiVN@y_X`Y~0(Cr|$AiMDAXSN* z*-s1<&$oP3y$$k$ab2`z_PYUfj3ds98TSdOV|*&s%=!DLeE&7Cf6W)klPK81e97B0 z^TQ8{d3|rkRFc=bP{+8=gJS;&Q<(7>IWXhX0L5{Ty#3QWW4i zdmGxNVSg1U_9yeX2kN3w_oeb+2a0iNgW@_?c4p>nAt$BP{%xUc{0ak>CLR~1I7G5g?8jUe3p=kH=h4w7UfM%Yi@5VvI7flX zfcAs^XjeUm=_i=l-x$C=zIebt`dL4VX+H@1D?;5rYHl1}U#+2zc~k|J2c1gs2?==h zfiXi}0or*%@pyVo#si9RoCU>ouoF}Yv^9)r|178s)MKC>&o2_;%=6MlQ0zA#g2`pO zGwr%V9q0L<@^1}x)L{QeP>e?gR1ow%@OXUP1jTV20>yC@gW|ZuL2n0sk8gx}MGmp`rXg?D;9N+bM z%>GrN$ooS(t}8QYzXB-w;iBqcl>K8cr+8i5j&loI2#V*ixP*XMzqlaAtW;*6qC;ch zjwp^10e-Pqq%r%&hXh69^<0apj{_9~-X)bepS?E&(0}kE=6ucpMf!pb^}79W`_p)#mw8c^s2goy z#&w5kZ-qMAx7x_$j6jhKit|qh4G(1O-^}C-KqaAl5v387x>0Hdit%WJ;&`Mf<)gG? z6SMt3rI#o@LTL%5t3YvlDU^m%>Po3OD8{Q#sXV2^lm@}L(7y{P=KufdIGW3t;|vV) zPrwxw5eL7Z%!CccH60Y^bLxKP`h(*oJ}EkgVGZp#f8qz2`_-Y2=lNlvxK1{gGp{EZ zpm-e%2gT#p8FVP95v9tYL!d4Kiu3*z?4d?Z)o{49-u$Z8n6}qe<_pi{^dJ9or857` zoafE=rE+T4ayP}K=9%hiyx6f^q_L4NI?K4~iuH!GFZTuI33q2TD0m%T8FzDNf3f@f zDn`DU7?re0Y-iROhfdkX2W3~Xdy2l=&E>Ln`gl(?x^&X9^m(s0Jv<}vb8&OXlhCat z!pFqKEG##*?kX8l*)>e&>x!oaB8>_>BAXvLmp^{z-nvfMwql5{^R%IFoGTsDu5*u^ zzKDDN?SmmXr;1)q`nJMUX~E5cgd=B44vrCfx_#ao|M!B6c9vL2ZZrQmo2RvX>C$`r zRx#;yB|qyupFQ0+l}AQ4V&GZ7$w$7o-l*CXceYEjYyX9}B|9s9Uu{jFHAlkcsjE=# zh_;ZgDXBch6;{Qq@=Kf!^6ojoyJZ{C#j^7L;xonPy)@h38M!`PT%c6xhWoC1n@^jb z`p1lzXfjY_ocv&K?WGkKS4v(fI7ZE9!sP-E698@AO2xa2k)&skDoq?if$=*>LCkms)|hZ5hE? z2{%`+4oS7YvopzR8u##=_dBjw&bgx0lrC95;HD;zbtc1Bv&?0y<8*v9&@e0Y^5jG3GMj7OPx1VBEbu*9uzK9&yTi zrmJVXO*v)JAnDf;HAU{voi4lhzUldvH1}Po-kT+_|%IHfB~%-q9^wI(PA`XWCN}Mhk3s)UvpLo55+#q83A!p|*1# z+uqc5$nq8$Vc~4NPSfkE;FMc4D&DCr>94kN%GQHrhH}|;yIJaeax9-w? zOLvT|o78`)@^;slLq?g-H?~z@Pd^{aJNwxSlbo&^#>?p)S-~2r0W#)yTu!Z=l%uh6 zv}K-oeC?66V8s`;ohHJ&UA<$qmI$9*{QdO0`$2~?_ifK=Jli<&+@m%-vqh6dBa9xt zSR_Y|kNZ8VTZ5Ias~eOr3VabBby@YrV38LVLp$6*rhF>Bw0V2M1hLv7UMo_PT8-Lc z;uqTrZNM~x2tcPbbq!v4X-T7&JOqss*b8Yo7NnK%FL^>nE;x0UYzvI8 ztxOcVo3Pcq=fdd4ev8l9mBr4KEUO4GIVXH==i+Cg^6UB!;?7lGf8@4}soPGcm;eir z&Lta#!*49Lt;}uODc5##)b4K?4;L)-l`6kEF>~sL@_c*uW&1~onvYV;8+)?<(aK>{ z>+S~nTMsyEGTd2jO?hL>g@WM)_Z}uzO1!Ko(mmgm&aeDUCFFBVvL)lP^!pJ}5_x5v zS_e`cpS8{<$LIECo0ZfZN+!+M*OogwxSyg`wNKtW360pO{OckMmfGhzzS~kZ<3ftp zkMMKdQ#=!A9vyoAUVZ(~C$A0t{4VM{4A8uOi!etZtR^BzwG_!y4HWn z_h0k+*L;yY?Xfy+{$k|73tKnJC2rcVIq}D_)jJ!NXBSm{+5R=D#bYnYtDr#8q+ua) zU!*eJC(H8s-12j}Tl~0Xf$^RGS+ds`CU%dP3DVnz*ia2Mh zTJI|yp|jlL+E|yY#ebdO=gVchxMr$IB)iP&zk24Nm1I6;M5lKxKDc#h`NzA9_CI?O zxkEF3`SedRDibB!Rt}X=6|K_xXgX%Yxuw-ST(u7qW;K&_R&XrU@v_0`PyJ>XXlRG{ zx~;jjw87Qi@pxx;liI6m#h-oSYPKI3l$3fWHo#K(i&Onx&j`N|r@RNt1$PNedEhhl z)2FrNHp`Z0v?ZsOBMy?{{r!j^n=7XIJu@iuoFC(G*U14wUTptT`&3d-J0~Vy+?etx009&+i%9AY{;? zHp#U6$XBiHZJ{|4FZ(awmG>_8O-V!A{lr$aMAtzDQ-&%=6LZExB3 z-5>X8FX^zJ##g#&!Op9TN2K_#pU=J3u*r1F;WT)}m|QL}zQO45I^`DS`sw2P;x&CA ziwnq&_R`FmAk%JdQ?ESy@~6S)+a4}{kf%JoOEhL@PeM)V#0M8lDjo+b-A!LT^3fn4 zr>OizEsB;hrz)My@0qUGkKKE0%J=MB-?Eio1%*nLE7f{U_UpH8_8`A?fmfyv+BW9M zp$oA~a-GHe&YtZ4B6Y8T|K^^XPm3QIm|ilNm8;$JPx)`K@!TY&wfuEwjpN!mUX?xz zwn`reOnlE}5_JB$r(ffcH_al)a&pVMvp=?(9X8|Hz4vicp_od0N$}+jHGKCEwx9Lc zw*QLOaao<=BgcnV>t>FQl3Ad4+rIv_;gqMM`YRp>ZCm6zwIDn7(dD0Zb<2i)*SjvrD%tMf%sA>YATue^Ap_1ARYx*sIaDCLA2F>g`V~>wmC%# zsK{(j)ef)=2+W6;@0VqA6+41xL!V+K?QnRX`#RWI`q;rD62mO6YuljZ!^ z-0PneT`fO*Fn@Ka>c+>Llv6b|GJ^bLc$4h>J~VE$?YbDw`);fAk@L|5i>64#zH$nf z=eR<3!NT^}Nk+Dkn;NFw%J|@(Fq!vD;FDKv%XB+F?s>Um=9#SRor!_dg=>YTEon`zS#DYF(jE>LQetA^&PpP;PE89v$NlqWj^l#xs(a;!_FRd`{<3vy zhvg1Ux0dN*ubNCG9^_9r%|Bn@rJJnr=9S+X;!gj(J}8QKBBQijS142Pht&!Bu?M^2?^^?r^RH(Te6Rd!qCXhqni8d=ogs zrPZj~+(GATiPWWY;=kiOYR61_W&8EbU%5u%@sVN@b~Z&4M_);2RL%Z6C}{T2QCAC+ zU>)5xu3F%06EIM5nM=!~pI7&(juOgO)!Tku=0(DnAJt>OUJh~!Ty!Aly88I3$G3*f zNl5zXDQj)KV!$%nhxJ7Tm!xANjt#8YH`h#z%Y0smL8HT_?O(@Ex4zTCvtV?A$8M!p zLK$7hnyR${EKv>t{1Ex zGJmw`zzW8mD`!_4*gfk!vPiA}^4PGG-nK7mQ~11#Ca&BbN$e~uZgk^u6|5%reW%j{ z5A80rb1N4b{$yF!POaeT<=!&JIwy|hqz}nxUwU6rE>B8UaoP%VkppG%S@p{UR~~T< zy|=NwE8**6m)E%!g69>RobsF$hZ%^CQ?4JeVd+DUx~+7SWy9%vHrYbLlkUuxUYRvS>Y!`# zaqqOJw_E*p7miS9I&=Bx{)Jo9zrQP*YchVtNfFloaldu1Le+0OnAW!z_gk=LnCB6F zr5gt#mb(V~3zuEl?v&T+FClC*BOs({!f*pizZc2t6dg_-G@i5Yr`meaR8s@*eHKsN zoRF@T@4m6Pr()yxp%RgzN)so~?f>!UjV+?GHL5SChWnQEG_F2wy4y0;JJxt)vCt6n zmmBxZshc*bUSpW-pt6lJx+iYF4484DGgU5So6DLthHsR@vI>{_Oa2%jA}8LdE~aY0 zwW4jy-9@u3_13qXIm>9bQhCX3GW6Rwy=j-m1YPLwm}mJS;w=B5NgBtv)?Qi4vnOQc zpb3d3I~Rnt^D8&#nibAG$|u4-#{SBYExCu2&pchdWAG5GFVEM!o3AV$a!xK()^^OH=I>_zSI2Sx{^4Q@<;4$}DFa}l%@gEPsSZe&}8{TcPR0zKt zc$|NP6kuc5e_ekD!=3|vFie;O2fQEfIRAZ({|NAS{9x`#PSDox3hDa^czxip&IcQr zM^-d;VGtyczJs9@=1~ zkp4Gm@gv7BKWNae{Ih!Op&#Pk33w}rAJ^Y#+`(cY{9)h?f$!`6V;9AvTfF}zc7GQJ z>1P0rZNNWVhVk=iw)3|O_;JAFytA5njE(qzO!2t(&<4BfM|v=Wp$GoaH>85?`~Mh< zhtoiBOn48%N+I#zhYx$Fga5wrdhnsO3kQ5A@NOLNt-x~%@WoG~hXjzZrN= z@}~s{jU5N^Cjvi}1HKM;Jb&W32iGvG#}HY6O7NjMIe+82WtaB@ek}OM;~$SbIW)pT zA^!IRZw5U2C2cI=fAswTJh^@#$8P+F@Z|x#{^R)rH#`rsQb?>(z#9XPW5+hQon)yH zejo67{wHyNym*oP`LA{e|Cx#(Ay&^lXqfP$r5Owp%0Ekv5r#te1mN-dgKfA5S-l1l zzKX`9f1CqW3gN#1KN|e^_57(R!(iwFPyDi)1LEHccyjy@8|=jY6nGQxPu35sHi-X8 z@Wq&Mz+>FlhQ}c*h46ELpFoWteUtXz*&zL%0*}WZ#*c;F<3}C79E$$Y9{OiD|AD}h z;}`w2o4*p^F@B62eY5NT4e;i`lXcH7KYloK{H*2;$B2dGKMr^tKl;TvVAp>c@VI`- z^@G?&AOBWJzo)>D0iMi1yZKj!3kK#N?P2Wf#_tC_o_~=;8|<$CL%;D<> zIDW#BJbZme?0gH3x)6uW#;(@5nOxhu74xo%_#pXF$pXd;=c%Zec;hA zX=B9%>3bD;ynjL0q>UY3MuowcNb&goh}A-TeILnuenS6!;TNeg&p$YRUf3o`f;>o1u)cF#YPfH$S)ACDb&{VxO_uU|N3E&Rn|A>%&kIz{ z_?aBczpMJM_s0WRj2*j?_zwY(&)VdLze3>2`IDV{c(VSJ;p9!$e_#0Pz?1dY z7hW4)ev-`6|u^I#61x$avKgTw9^KVY^#4pi*iyik7{|kV};|J?Fes-UqZvk&ct7OJGXEF@yW94#082?@1@%;VQ4y^K%VDWI`KNWZz@Q-7MdH5r)zYOPpR7w7x18>Cv zuMIGyAQc_pG0f^3BK{WvZ^{8*13bBY_GSIW!NtQ1{3FY1>^N2u|8?N;{+rZsA1j6Q zmxIZ}^G9F(2LVs+pZXGiCGh0_wJ*Ff+t75`zU2K!U)GO5z;Fub^ZFSGHy@mwfBiV*j{;AgfBQ22fzz1J zKkOVkxWvi&_XeJm{O<)G&tGT{?_ttMB7hzWk??0|017F8fpFh=}*#i7~Fi~{2`C|!()Jz zLil9h$@d3&03_|dvqAbD1|E-J;va3WQV7rE&Ak2~&rTt{5Aei)U->#wi=YiRyi@k{y;{{l0A`NuZWPWt_ml74f6$K#*G&+ho20MAMO z^?jMgKdw7m|0Iroikq~P_)~nD*FWU2jos@QZjXxiF`uUq({sr*9RQ_>H?2g}h)}N0bejEe~h2-xb@Ob~ls$XK7@B+ci?>`Wp z-Srm*{Alox_Wt?~k@)&MCH}VoKZAq#e**8z0q+ARKX?TBBY*6UzY2I=;K{ug9s{ft zGX6Kf`_ufhJO2)$%;$eHf9$T`<-p_fS6})2z?0(#$IkBkpLW=v@4wiMKN@&)|I!!# zJ;1{$=#TNUGI!XA%wNFlU*|toSvr3lcyj&0c6R4~TsVUPr+`1=XO}+;JSX{+j$l5& z;=Gfb;5dF)NZ%0P@%<65zrH+wYzN*5_`dpo1iTsW7!NrHeiu9LC-EyqGS@%WNgF$S z9PoJm)K~rt@Uc|>&@a2kk3rO*&p+fm_Pa5Vv91FiKR?4d4{WUFknmT5x1r+i%lu15 zGrvF9*Yy(vydMYt8-RybfPG%S3NgQ~zkL~hA@J7VA9IiAKX&u~7 z&v9f@A&%b_(seWN@D-pw`|kqYk{UnB!S8(Ie&T;p+^>KChVATLzhZ$W_wRj~zZ<~A zD}X+aUpxL+{`=y8A@Fbr_St_s@SLol$qAhKKL|W0`5!a~{@d~#j6Vl>6X5%L{iz2Y zZejbJ|FLs9<2M2yz=8kki3|oT;XcQ2mc;!0tFPzpWx$j3PhZx53-EaU=YjGc>jv`9$5M_<+r~HFSwBT`7<8>=v&~o zB(nqIe*!<2ntvr0S?osm%Uk$X3G{W}70ON}3Gvb%nF z0k01{t~-pM-SwxmhCG|h|`sW(y-wM1L@T`uTSR}k$#-G3c$?p1d1Kt??BZu!l z+2uC@kIz52?s#BhbsQxA7Ak(6fAme-;m?09q@P$O^Yd5o+|T>3)UTa{_XM6kf9#Hb zKk(*M{?IzH`^(ec|3&(Jq~gaq=8o_0yZ?_?!rLxkt{?2sm-p8zfyd9U$$K|q_kTG2 zO9ScWxRlA0%imrljNW5|D6(EX!)=6FFP?1-VS&&|E%T?VYXSafR{9-@S_D>AGo%CG=JkB4Uf3S_T)BFD2-=yDFipTL| z8>@3b_<<{#^M~sfS$25~;B6s(Kzr9dIgYUYZ-w}827Vgw=$BO%?Gj!+>({>@#PutM zJ6R}%&jB9eM;2os?Y}cY`n3RWNyU$C?B-7+n|c3^oFr_l9>>Ig0r0aZ|G$fwzMt?t zz~k{p;%4O}vJp|_EKXMi`O;z!@4o!MH*4+fr->vsk4IDU4{y*M5c|4Yh0IsX4{tbf-=c&*jU=T|)bv5>e)E9G^M7BDp9xPCAmR&!7H-vPWH@W@KQ zhQ|Rbg^XWmEpz;YBkjMlLHhXtuTA;K7+B2%;a34q<{#TgJFEUL1CO6SqF*wG-?6x# z_!+eB*XNgLgWdRTD88@$(}2hIgYoob{u_bE>o@YO#tvQo7{C1bU-|3H{J8^<^H0uQ zB(Lb>-wNrM3A`!AleT~3$Uf4y4tRUuaqNA`pIjdEzkh`+UiN$X{-)+E;0lu%tZwv5v{zjg}z|Qd_S^VqYpA7|&#PvHHq+bs3HsBxY zc>X8jV3q#?yb17l|Agy@)oTdxZ@=N!zyJH4Px^ksuLU0C$9cnzwA1_k-QT3&JK(1P zk9~0L68HxTh44-rne>j-AyxBzzX|`23C>ZloRl{MSPIH3C15ieC%}@qeX$?Ie8d z=3mdhec>gx{K{Wncz+K0{T%W?IOJ_gnE(F)%xquAzZQ60zkTIfIpkHga^^pZL;e_t zJl8hP;x0pU>Wnje}c!q z0Bl_N2MdLqzo!Ck4f*Q_3|@a&Erj0;Jh^@h23U|q1B8DCJl?+{))#*Kj$hZ0zVMkG z@;5o;<#%!xe+2M$9OUm9@Z|c@m;7<<;*7WDkYB?ge~&|6c{gX{kK~X)$|29#^XvTI zm-)Bikk96jzs(^(Z11o0e_zJ$$01+JA^(~~UUwg7<4*uyAI?8KaQS=@!lEzvswr*v7h<=m+&|aRtn*Lfyes~d~eVnHbGWk=tKDJ zz~l2j#*X7>bqs{R3;cNC@wrWuvH|kjLU{QD%=dqI?Z@@c|67vTf$)C7JA;3Mk#e!{(Aq`7k)PIN;;yRqK#cZxAjgbfwmq4XA1N!Vab z_ZGThKX_N%+uxPB8^1f#TZiwE_ZC#_=gzG5D%L%yIx5y@P<2$Sds1~&tb0-Qzf;`r zP4)Ak`q35h;0qh7KWx}P05&Xi#rDA7);}w@2f>ENVhC(l4}}fw&4vvNU9mj^HhlM$ z4jY#L4Mn?)d#y1Q<5@!0Sy7C8Db*hp?JcM3f2X*AC2YK~t)}{+VtqYqxIZ5@EU0K7 zUZ3|WyoT=8B2X-J#eT)Gp~CCJ-hztuHo=DNn_?N(5Fl-hp`6bmZ)J5K2dP>iDrHeuK8zQtj(OMWJ2_irj8W4}fC7L!ii4Q1xR}{RAlHrJAarrRo{`nGqA^!$+0O)6`-i14%prV~_P$^JJ zFplY^_Hset zhp`rZVMyyhCxBiD#kd=&_M4#a!?;ap6Qy@Rk!t}(dylDl8z}P6Krx=zRK1 z7$4vl?(YP}{$D}S-ZxPAVf>)ldq8m=^@C2>&P!>3P|S}oD9)!i)hN@s(jop7oi2?{@q82E+fjd@i2d{7*3I%x0l zNa=D=%v%m9&R;$#uK!X{v|9#>cFL*xK~OBH$Q=VkyC*?$S2g@X`!!U(j?zn1`!!Is z*G#qFrP?2W;ygYB#b>DwP_+96R25VXjG|hBLKDLl6#F}YVw}?`oldpS0LA!xK~+FA zLDAj{P_&;1iu1S`6n+@n;1~Aag%wKC?rx~#@pA?g{av8;(-q^n4DHze3Z+-6et)MJ zM+5A~dA&vTLq$7HplGL=YDdNT9jZ=OtP<2!s?^96p`vMfX zm(+e#Y=1-5>5Bc{Qv2V7V*LZv4;8sjRQ=x+`+cGMp<;YrsXAS;-w&#tuIRTL+EIT} z`%%$O?_~c)v7H-|k6rn268@sNpPy<+#eRaIXkUnGXGO8UFx8)~czj7x?Wovq2&F@* zc2tZ*nyS+k`^!K(9zV*|{{KzI@v2dF>5A=I(2jBGfMOiFR6kT~*Qaz8)lOGDer&1s z|BH&_vxoSHfCfn|KD@`f6wvwT=L&@JoEbf-*fzb&+&Nw@!xYi z-hDuU=MKDI{qH%xHyeNZ9^k*{_`iSOfa~VJ=XmOQ@PF+&{-?-KJVE_$7O=;~VA`dd z=J6UfpDWQVxB1qtxjWOwEq?mdOEpt+#kXhkOr=+~yEnMKJ?0zs&1iMy*A0(C+iQ1- zG(KzHR=>yBQlz%(_Aq1FS2Vl07D(X<7n6RctUqbcXr7Uyqyy)_bTMu!SlHR`v%v6K zehv4;B{QT3$`&N)WO)xh{AzuZvg}Lu3)O~YMbDqwTu3*aw{->0Eq zMdgsN>8{2{@G~-!2Rx=p;mOk|Hwx?V=$gIm5wt$opXG;!;Pc);ayf^mrV%EA8=&kz0DfaKOfbbu%7EkPG^qN1e>ad4^{S+ zM_pH=*~NP}Qg|dL#){}Ri)Bh?#%FF^ZTxV@=aeIXf?m5UPCXcNKOWJcHW*n6Ls}ltIeL&l_=8e;yW!; zcsdmJzsqqSzgN$E^`&Q@?8NlO$aNiC|8n}O3C=zv$BKzaum0|yZIdIke*l;GxR&Ey zS5q>qVuxEU$ry0$M$NpTfi%1L83QRi7Zjuy6iu%aEf*#E{r2h)Z+ChXqT0Cdhd$pb-o#bQ z1J1oW(&FqYkDo!3b%viAlERa*^>&fd2)h>Fs^t0~-c6TZ_{O$L+z35+vV+T3Q|e~H zq*}gDlS~}9&1UrbCK*3LW_0Ovxx&z@d2#%%&#mqIyTL&QrukFBAb#dT3XlGJKQeE;xGsdk^ z71mQ}E`C+b{EV8PkqQR!Gfh%>rY=|&Ijv>tz;z>ky#H}zN&Od()x*B-ZEeUu)AT;D z)T;9BXr-^grS&=X-q!m*NQIZ{2y0HWIdkI0;AD5*JDq6}y?KDo5RR zSccSzcY2;YBJ<;k$_-sXxui0)5%J-R{7RD~Pe&JryR34GxIa(%oF1Rqk}zTCp5ZsG zrKd&vh`+aSxkk&c2r&xE6X9La(@q%i!>LXV%Lmk9%g>?`+zY(niA-a`TV8mNz_L zYQsE^8T@E-5HSkM<6*p^`+~ZmL<_E{xy+B5Z;83<$uy0Vsbtwv*5}xw+8$U0sQpZ#m}Hg;W?!ubZdKe(Yr^|W)UYd z)w<+Yq{q6Q9l`aWX-0m(O7}Y38PgOB7C#tnBo@(stw#6ZlUYfR!-rpeV70)-!oW+y zuGcP4@Am-kGjLLPe9Er`bLB{P_}-cM!a`Zjx_?{B4~OrmPnHc$F7xGGdDx&LNIT%0 zk^bJ{dc4*FcY&JFn4KNoxogn7X4S(3u@dE6=9!_7jMWy)5{ z`K$a8xKpv*Lp$BX_(YxfrtL#CJiNDQ*<>r<)%xI3A!V9raOYXp6#iq2B1PmfCSS6> z@xq>#2l~Go6cqcTU~=iqo@gxj?jiZUD5{pP-79{^Bbwcz#3(3FWyPUa^Zad8`K*JLf;ajX?cVQjsN8yS zRd=(h^CiWhQ>|a*$W7m%FP9S{?8<0t(w5SG*xfH8xgoelI7h5{9W%eodBg8ikis+K zd{kGzK^Fp+9DeI0K6KgTk6Z@@Kh>p5?wypg*}`S2YQo@!)AuN=O%XFJl5@#DllN$k zB$sB`fb_F&E4c!rht~AQ%d{&^jDqrflG_`)sb8MvuB&TDZh5RD*K?B3WaHcT1LJ)2g^VNPPFU$}pMTo+dDfm@yWG9&toJ)blx-g6 zQ5DHaX%;kdW6afy6H{@AiF8 zG3)Q(eXmen`caj;sUFSlFnYY{U$`GKQpbIo!Zpsgq{mo)&IfV*u!Y|yCw89M_;7Np zA^-dDnuQYtbOpP#8(Lg-vNx!F72n?>|EzR}5nn;V(H7>s@#8&-EZuHx%<2y-3j8`O z3j*F1dX`CSUsis4`j37`F4>CQ^Xj>=z|C#e4&T8~X6^|aFz}XrNr_g|j6Fxn%M5(J zp7hIlx`d0$FWMbWx9fe}Vf5Ri`?A7!4KwEJ%9y4OY0h`g*SkMMP3_j9iNjycPn+H* zkv*o}VS~7pu+GWso6dS>=S$x04X@gC|MWd`VOqR$bh`@`TH=;oh;tP34V+xtyeoN{ zOhPFCalWM=7wNR+?w1mevF5AXdNd($voLR|%!XHX16_8V|K?xNw0^<2UDn})@H;_x ze!zI;>2{qaseRMzXC(Zy!YxbUa&+rZ49?~ZR<37lbT}_`MqjyUN*S1>rifr z;>_|Vd6xB}%?~>i&s?U(t3m{ zc8qh%slv=%xw$>r+tlkXJC1)gY~L1xN2T|kb_-NEG(M!+9YMEyQ2O?49^R7icTVrI zZ?i0`OWn5F;OG1z-R`{IqL(Fq79T2?tXW?)@Q1F8=ZT|(hee;Lo8p!A)Te06paO$K zmy*P2c9rRNM~L*S=9j9d%>S5l>b&t@uL2d7xqNzh)4Oywx5%#Ud=u!qyymXv$%6xm zwMEO$ZS3)o|0yPW@k{wsQN7@Zq;vS4J8~bTLbsdb947END5&zly|62bMcmGv}QBhsm2h2N=n$v-tKrd6mT;IC)!001ZifvNc$I7pqy<+Pm!#k_5tIDv=HhoNagv#UzCYcYs>(uMEK-+hQG6!5#uE2|zVe&@}qpL51L-%vYc zU|cwICa=YV(X$FB2t_}y9r$pyaNebEhm=Pjqpl~(qyVqZ@(URPDDR=lIx#Rt=9;*`HHd*IU|G9UP z3nd2i2s;bLX?L8G>w5Ot=%rH3VB5%J>NL9=bh`!~UxrJkpA*h)8D@9>!s3})I~0_j z_cL;DANbz++uL2{w* zjx^b|VDDPbn+;dxHdz{^#yH5$c|Nma-NB`id6f>U%TqR;%>9|BZFa_MY1_f|40hI-8b_Oox6CQ7Ui=NoXdySrdv#f)=1FXz+mC$;Hz?XS#BX?&zTB`LW~ z@M!y;w_3}G9N%QWWT971o9a}#u8d)l^ObL2f1;G;@2B5$QzKj3Z&<`|-ZO7&m3yu( zR~pIu&MNb~qeHhl&GztCzWSMxr>Dp89jSBSGfy~oFne-7KVO+ui<%}`3Jm}KxDpX~CZ`iZmw%B_=!?5W?>C|~f z!fIFF=#*-u-80hfY&Y2M-Dx&bdQh{1J)|yYTdMYSyU2c|XH$v9(n)u^hyUgb-1G?Q&{UXjiFPuB0 zL2z$CZTPF!F(dM(+#0oa`S9&S7kXS++@$#8&hQN^C+vRrW&vY=BY5O=X zA}rq9^JdX<`^(xEyDipwRj*iGWwFWc^?`LZ8U;2dGGz}=UUxpBV$Fx$UlL_(PwYH% zPA#}Al*$9%r;ef9ox6BQO2OV|tCzh!Q?*;r)>`V?6W(@JF8A|3uP%(T+AujP;ES)Y z+>V)1b5eO;_V;BB=Wmt0A9%=XNKKm3tJy1@Xm-ca?J6c~Y78@StYh?WDMl4^n%#|- zRa_DnH!VC^FgeG*e#E`80x_PWzcgB(w#ZuPSL*D1<#R9s1hYP`aNR|5C+g zj%PMBKNEd3+aMqzE$v3l#EUe$?xd2a(_x|h1wx(=uEfcHE29br;<0^>cU zSASETv-?`)u0c;PS=&tWk(0IaeJj{ie>7I`%qme=huVnx=IqajV|dC0Mf{G1S*E8P zyno}zisB^#+XI(T@uFQrVic5zufZegg}c|RbtCfkmqx!>5o_VPaFlgy`tlLZo=GEa zt4wfI)_;0CLqg@zw;LtToT^Xo$0gled0F!E(d6*b&sS}G?K00hMs&N|BijdhB<4$| zoZx#r>nQ(0MIAR;=Yp~C-`a4u+8j9&d~0{T-?c2(-9)5!W(F)aFA)2%I*0sN1rJ+l+JBe<0qLz`u3B}oW_8#g!nC5+7d;R!y zsar7}w|`jN93NrcQmQv%OD3<~l$H0tNu)j3zxvJ6chIIR&w(aVg$s9EOASTvDR`-3p z`X?nLwFEg5Aho3uQ~cgR4q~W>d%i; z6}HFRYl#|B*!d;ir?vae6b;w#?$Sktd=s^Y-eTIwea(~1s`J~Kd*Zrd+^0bbEgaGw$*h) ze4ZJZX&<;$na?fE^mTD+6#c0Y~$>C+uBqN$>$(@y&7 z5Y0P0x1{^!ZVL-gu=%XpY`eqz#O85u7PY$Z^jMgrALDeGvE*<=K9`wAXRYJEHEp(} z*)^xz{h;6&De@^pB<6C0kiG0sv3Wwg6`L}C-Z+x-Qs?j!z7c0EzSV#7^4c`%w#r2x zmExVRD(p@s?i(+?b#3DD-EGasXm%~=cJ=DUSI^y2)|hwQwfyA~=Zo1h7KlW)RDO-! z#(zI>w!dk5N5zrFSI1<{K9Jq;v+MBjU1|-NhIX2Ebd0%N{MD1EmS)$IZdY}dUe%(! zn7VAP@)3`YolclmqjB#?`37ws*$a8=KkplIcAdJ{O#4mdZv_g*t6K$+G%+fzKCs~K z`d9;f?nPfz=+{jvy4`ucPLDkYT;*6eTrS~uY1)ImS;gI*j-&1lzU{a~H8rg~Or`GJYE6qlgC`4}Y-^y| zwV~Us+OeN&?CUSb=X5j7d06IPa!pZRQKFfcCpmON?8P3MT|2tnQ)A7}KWuk5 zdOAn6?1E#?^5XFk-+~?{74)mzu{9<&G;OPN|H}_GJ#VQVI{baTbl|D5XPWPNgpSn1wgYt&En#4twD z{arggS6sjf6{=TW_JqR?w0wxk8wGk>AAMgSmoV<=BH&b zLj4YFGUjz_+iw!xU|-+*cw^cjMTvtwHfGg>BS!6dzvafZDt_6DAjihN=O0uU((F3W z?P`APxwlK>iYC|jFKdq%6k3(mwpjVds@$*d-Ww2OXW^jZf2{d>zV#!%Xg8a->9TFf zk2k(PqP<$k&brf7bwW1&+aB^537t-wa(?ludF>$_*K$)vCunt!>=)M zj&UiMVyb9%o#=M`&+MF+utamel)tu?`?xV9weCj@>)e~HDS}rw99%7QddjGWHFj+EN4E~TJM!H8)pu>O_ZZe`{4KGiXm(xb@iHFE+b}kk zD!Ny9S6jxEe_t2u@OBCBlDP1IuBVURH-7taMfP3b(Su2?;RBn4BhD3n`Lx?WX}tL- zjhyhVP#q8Y=VY#QyXRj{o2^jypwxHp5!X!j%Iy(diyN=zo!fdkcU_^`bh|bOix_u=UQfBbVrk8+pA)s7 z+UPIPml-H?wODnJt-hGX-UF@Am6v!LE;zJc(6X0Y{kA=`mNa?0ai5Kq)c(B0H(O|V zaHred?7LvPl&{AH(Of~*_rW|e{Y$s#MckVv{JFFxT&hrp_rhkeg08@hhBco*uD>rW ze0ja4~#vI7UBc-TdM67r_rGM=V-P-E$;5s%tMqr9j0_viIWnf>9y~Rx;lQsDAmY1-vq)S2NeI|CdoxcKyF=bvwN;X}$OH{Y%GVU&}()tlX?u&qIsX zn{Ic^vn-o^o7Qgos=O_KvVO=KhXGghKl2M0O3QrR+tGNhOTAy)7y)SyvuN%PImJh- z19^3ZJeA%iIH!BGS3CIrv(W2)F0AM|1rY zH@3XXPV85xqjVs0%}}j3=f5An$EZwscx$ZM#3>rr6I^bOEZo&Oj{f=POnSV2WyTRc z;XLrMN>b{~)vgnD>%ZNyZyi z@m@OkHDH*?=XQX<_XpHhFkH<;YW5ic)9K+2sw^nn@C=Jmwk78P{^f(?2 zxD+KbOt4Y?!|{1h6<+UB;w8CneBPMI#m(h>K$Di=S#-N=(gvvu8is6Hube+P?BK9b zHv2D*p8UyGp&{_~p27WtU4LZQoml!f(aun6eb%i}1MB?uuiE(atrE}Fqch)KURI6& zW|-VR1k>&AmCl<`W>M&H!@sL5S4#QPo_q5L%&#)*IdMsTL$#Gf-W?u;1G=+w&2I$V z3~qn2Wr=s=G_qVM*V+W^Io<+eqILeJcl!- z{o_Imv>1?m-@$J%cxu6k|T~D)1{(TIZ=Shmwn>k=Y z=I#KCab2E2=8DDNIxP5B^XuWVfI0Ri_JWozIr>e@mYth?uV?3ufQdI-7k6o!Uf*B+ z*7)O<3!YM;l{CBI^mr$vxxG5@X7srnXGUilqv!gR_QxNTJaRv(+#6BY|HhEVJ54R# z&*2&(cHsM!=KqhWyNt@J`5p#LNp~aN-3XG>-6<&DE!`mqNOws~OM`TGr*uhomxRLm z_~Y+-XMf?_wf35G&Yn3l``kF@B7}6fWxd%Px%&NTHHDt2#}u3|{(iUfFJPLD^C@xa z4ugAD9+q&kFRxr>aRo@uRC?=tfBaFRG2&b}dX*8<4x`j6B36wCF%IM{awnImhiD|ELA>;GYkx^8j!C8=-R8u`@xlwl@=gLea*4kQDUM9qJr57xD@r#h5NPumwf)@ zWXUBZti2Y;M%wh_j6_MiOK-#pN(*0IL{uJuNe6HpLDzgW{&!o3vWkPhs&77$iBRh5 zP5H)wD4GGexiH4mN6MKSTD8i;flrJ~QzS;5^Cg`-qE-uxE}OrHSnN2plJ^1E33QbR z3&Op0k1`>iuzz&DV`88Up=Zxu6@r+Zr-mcBvD$IJ4rq42;nV%H;Rr=`W4WLdq2!I0 zAV5u=iEW3jJp2H-&Y+8Yo$DYx5kvclGsrxN9TlT@1wv@QaAeAC0JVwt4U-WYf=k-_ z)U`0b2>ysA(#Y0io`4mzc_xdV`Mv~x#3nC{k%M6hunh!6v#Wkoc zxzvdnjZ5*hfpcmsS2<{-k7N?@4&jG2xjKv#eo^tLy<2Dfu1g+k5?VavDE#@o<$1r_ z6?EfDbrKlYYd)IrC}nG#FRtM^&QC+c-hL}N`{Y*~`JUNLg4*-cf%RISNm8AIJ0=8v zfkgK*{w9U)#grMxxY_f52?YG#9x*r2RW+>{q`rkoQTt8Gp2~M}KyKvc?kt(^rdX=N zL`xW8c)QxRwfm&p^wMaU&z{aomMA8O+wR3`WnCA%eRr%V#s9|lxgW+IbX_+nn(~C0 zj|3p8{Eh5VB@1c1F_O9lT4o%lyWj9x8%`c0-D^dpuf$-BhIfQX8zXixcy-iHrwW@= zG~M258U4?F?kDg7-HUH{YqyYGg6UdFgjReII+3HDbAtjBYk7MGnjtU! zg&-Q!eVFP7v;LM_p6N5H{I>|~AUV1+B7z{_ws}TVg7Uqx7K*tKh#Y;i&%Y`1+*jcR zx{qC~bZn5XqtRc>45KwjM=N~P$W?5hz=bI}{}5kxxpmT!S(6&6PMM0?KIe07wn4(R z|Eq-=QgT5Iwp=avkJtak;o0>DUBxx119@kedU)v2I1J;B+qHC5t_kHq*Ez2{|8CQ| zNnf6Ac1#|n~ zL-c>Y8S=mWC|}S;W6DAPaKuCi#VBZN{#LG4Qq@U$XhMUlJtLR#E2P-V&847H2Wr95 z^C3UbU1G*+ib{nP3>feALiWm+eRmDZ z;5OQ_s!v;9aTvQ4hw&ML1G?2X;wNxkK7bPyChQxrHbMMa^2r<^q8^byMDEsikkJP{!D6lymm5$TVV ztlPz$DTi2SrhfT3f*&iWv#f&v3rhz^Kg)&@?$v3*iSIJ4XmGpetNey_7lHn-LqrN2Js z`@g=yK+wg!%e&TM|K?RG@}LiS15;5zU`RPUW|UA>CCz@|k-_gHD1>K-A&i0l&@oGY zUz7e~zjwu#J)1N<1P+y*Q+)S-?sJ{|1iFnA2XSpmS4x$JKC0#rID*SrMmIqlEv<_7 zu~&_x(yo_peOQ7NYa$|0Br|vJeaZSOT*{U5zh!rjJz+4F5(fXzeXf&1pi5< zENpQql;iU_{I5<1gD&~+@0S%kpHR^?Tqwm1ir&LZH1W0W?Cdm+ev>whcs z<-XUTaz_%|Zl0<|3h4hO!SA}8#YeI*DF5mI+`s2!A)xyhspsRLLW%#g>C@W*?2Y+| zwpnuh;GC|uYnx0?RsUlL9qJN&aqIfuTJMru&S69*`m(wOGbz`YIW)WpH#epBedg-nwIx3}jqkGfKlg9GVW10>A9q3h{;RwA zD&NwL#eKc1Px}i7;d>{9TEyO~KI&gWF;jPEx~lI#Sa_L38(8+2s=z5k;^z!F>G_kU z`R_dMuRqtxaL`SU*<*XeUkPD&IRdlBKmKEsZSS~2(y|wwcX)C?gRgxWmPv{Sh&JZ``;oDt_ zhgwH%w0EoedHZ`?-#_nHKiA19(7g$3kR=MTk{5um-I0991?6AdgYiDhjQw=)RCkSZ z{veF&v_Kj)(|q}X9xf4)Sx9;v+ZYShFOlLU+0r#h+w=R|bDfL^U6Y7g)||fAr0TO0 zb*pFv$HjfzTMLtf@!fKxg`Pt5uZr!5TT0gs_RyF~15{YsRc{&IaF>6-u(z`uL|IJ! zF7tK`ua zY8@MYT&9~KIALn_$C*5j>EySF+KO&TE@|c2pvenlBX50r1V#lT2Mlk(jRW04-rnNZ zFcL~uoACURw+wYFw|6+q*DSU_&^sXH0y`lg-b+(D^CIfS4RZ@%_I0?k_#G7+iIcYE zV0AlA+35ZN+<4F}L-CCrc&wZ3o9If!$HD6?4S?6R2=Noai;1F0aB3iDJsY8HmpE~( z=ElNO+xXMZd>*<14`3a-$P-WsCg>bAbt;+R&G3wumA z`~LQF8yJTq&>dp&ZhT(^+11WnW|V=;yPuHD$RNU%xA>%;&N`Hl{0+ffGSFsUH<_<5 ztL9$Jk$C%OoWW%J7L*oqgRbG$ep5NIhkg_4A*+T&L)e)?rpOsOHOmBk zG3g(AbwJ3tBxtvSLN`t#a)1#0=nK@A3v_X#?D!s zR+m@HvV!UEb<~YEQL4+dD$jiL@$LH*Bi?ngSK;&FVl|$JHZc=?%f~y8BsP^XPMQt*8Fn7Y z)yg`gmDk7gpbT<%KJE(%1UHmK8k0>tn-N;W(iF%XDVGnHd?)9Mcjm&2$peq6iUp-l zTc&8>{hJQDvUeT?Q4%7XUc3FX3=Jduun$(lbDlJ&b?Ucj7C658u>FY;?bgUrqO-Xp zIhDbNi=VjMwX}C5Ew?FN335B)seP`qboPQN-X!vddeO zq#44Oe`4%^B)c}eK}@4eOnV3|bC;vH|M?TC=EX;ica51}Yo7ampT{8+bS;ttBjFvp z(Bxo`%YGwyT%cD}G>NCla?>9>{QTg{fj|1i%;jXHfiARYB6m1oaQTVT3;)-9ua3ej z@uYTG#S`Fu$O7GVirJ6E}kSQzFiC zQ8DNCq>0heL-N^I@*!XU!0%(=NzYdV+-%StM580{3D)eyXE&^J3_qD&PZD6#*uv2F z*kLcaD~Eo?!TiQ5H5X4BUMs&9w|q$2vw+k2i%E!eKSzj+5R9}n;O2m?#4hu~Oq$rp zOTyRkRuAxYCW(l!?6HpLy~GPG)DKtj*~vWO!vR|C?cPb{x+;#d>%xTOQQDEimyuTzxhd?e73g7=t)KMH z#1*l3kRRp$YuhIfdb+P}fO*B5n&s`8kSqdzGTL8ME(rrlRECdpwBAoGPX_vGdcI+~Goh>Jf)Ep1D zA)MBgFBwj5VD(_qq#!Q*F@-(o4Zq$PKfybu8_P4#Z>` z`CH%+O|12Z{#-FnDgC!#_Y=TZ^CR0;OEKpA@fyPZ3Sy-CBA|ws%Q@jS0@>KUp(9s3 zkZ%#_dL}GYHrJRpDk17PEeMnh;9b_)?L62+C&=BHQ1P(w-Bk}%4jjRf{%XXV$n&un zoLwbKy5PMe_g=E^Q$Am>)V= z{^T5tE#y+-UPi}WBqLBN9Aoai%dQq%m5K2RtAq}&Ey7k18FpcaX8Qt~v=y8$%0U-( zI>qwa>lA|I+Yfu&K`G8SF`WVEq66w$zchN@%iiX4?^~P|z9l$lzJJZU*Tlj1;-N{O zjzuo%H$uaH~OA;Sk$bo$GCZ71S;7{B`(&$Qo1beGf^F2WLi3AeYWc0x6S% zbwJ&gq&5dsVa*4r8O#~mm{|0CIb+%N^hG!gz^wt@=^vssCFNyzIJVn;>#PVkZ*1ol z8n*lkL!UU`)_Y`MrS6K;cJvS3`fRpG3b=hfd#bdpd(`P=k^bz7WT__Q0l42m*LIQW zkJk`c>^X7iFu)U+zG?Lbin0o!Q*TG^EJDo4ok zxXP_uIb@D5H!-x^LF_<)ntQN~tATUe@p-@RdHqlax^~M@*onrJ!MMnCi_JZT=4&ou z*K#?cSmm~p36IsYv#@UizubnN7*R>;3Tx#KcFcY)AQ}mWyG;~DRZ|KH0_#IP=weI@ zTOj8x^uo+RXU+4%ga}yiBK7iplEI#CdUX`~L#243K0-1^m~4Jzk!%jjF`%L7L+1H_ zFooIvYq^E25b*wO0A0+=5H_03xuwaAD_E}#c8Xq$G-jW2)NI`2#|rl?^b@}7jghwm zOs(&WUc%tqb7m!v5lC<4e|ZeG4=}Q5wTO;VY&FJY0Vba#=@#Q4%lZbOF)OE!@ zdKm9zR|{>+YGzq}}?=6F68Jf6@va z6(y=kMc*kWymF_~ZEg(8bZ;s}cn{(Dy28T$!N&Fl>Mhlsj%KDwIpDT}?og-lPsrV9 zj%BFA@@`T;xEq`Y)6qwnEXe6;!p(LWVd6J75M5Epc34#j-dw~cjd^UP3Ku3leAnr{ zCJky_;5f8_t_(5kh>OJ`(>hOUaR$B#y1FpYFm`T|(g?D?{P1*-DzpYm(p4RHVe#BM zw`F22gULA4i!fEvG2`MQ`?TySO(5TP&aS|+zFo9 z)^ox4{Q0}O=jXT+bP2jrKhw^}jfpDZ>y7!D?7m7~?S>`~xu-96oVW2Y5GVbv#d(1~ z$&;Dm(2_p@U0?rsA_LXPyRMRK3B{jmpAX2l3v{oYZCK%&4BJH>7t9SPXH-CeB;YE0%SK3n+;SD@j;w~5&E);3j5}7` z3_9RO={u%@0hz3xc&i_8(I6e;8D$gLzupVFIKo-mPNb=J#I>QGH_57N+~ofN|&pUHi|4eDh!U zTuHC;tNGnKJl2Buw5olg@?FW%tX!uf&3$`9c{`IstVa^NtOgf<>6H_C;{Al(B+sLQBR4hFg6}#hOk~i5#&8ppyNZjkVDYhv6g7M-NZQ^UO798&GUcc zMw9F3N3*FfhjsY~t!DL8m>I^u3tXoTfG$D_mhS_{-TgAIsc4aZ zNT!zo?hxqSs`X6OWQ`I~d}?q0U{(pP`$j<5%vrt~GicNGW3NWE z&duhMezO8ZMesJ#+e|X9fRua!<@$64T%T70IDC=F#77sYR@O2iS7DAx)L! zgytNON+EYkZDU0vI!R_o92UE3DqiJS}|Wqv^=?waZ0D+{Tl`SfVn zQKM7F5k(HXy21!BRSlzXC2SQguYbt0tsWLoZgi--2Jf?R(4ElE^JuW%yDjyiF*SfL zV`eS1Zy5gaCB8Jh;!th%up80PE=qe^d{LBtk~_uN?&Qda+KMk?6+42h%4)99D+9=P z0(4)0TaF=WtL!8*7(e2$D!{BYpOUmHbs8K!jYn?RZ>z>cM zpY#0zy1s*C@b7-pc7I8suWs@~_GNS7)7rh?k&W0$ow|LC=Z=vgf%m~Ux7X;m&C7@I zQ22%$S31GCWeIqGf=#4B>Um&%r$JZ0$D2>+Vdj(R6I%MTr$5p=PS%lG5uz7u5NArd zt??63&M#Tqp4!X&G^UColE2QX{P@%6Uzh$$+u#yiwC~;>aA!bwKww7cVrNdlTr8nW zW20%SS(oSg<~pMFHTE2>^*DA@87mQL`4@JG4+xZ9Zi7JyPLT)`=$%13U%!{D(pc_2 zpSL`Z!z}2cCo)owq=eK)Mf~_y5TN7tb{qTS4arW0ud+;DYspZkrT^PLA>*5)%Eb(dJK ziPg_ufok93G29H8suka$e8HT&Pf-m{_um!i^2U%=PuQ;}Xnn)6!C;rSsat9iblpV1OnZ-)-8?5~tw8^qUiU?=nTA`tDL&vXf$jyBm>8`BFni-lWlpw?m7;Vgo{62fsx zcGF9A;77v5xfrnUzWWvNix*r+t$=QK{=zG&9%?lO_!W4!&92CL$C>>mwJmXOW7v-@t+c@?8bpB?WA>k&C2r4%QBb z2cdiM)D9WqZ1Lf$BuG&KxOTC}=Ie^X$&Gq8oVV<4rzUF)4!;&&ED}zO6vngs?lZOj z0JuLvmmrOxS`7h<;gx!EBdey2@vtNsu7Us}w#N&2o5E1v&&^_?G-0U1)legb;njxq zn{NG`DQdA05%^FNBN?s+=775fx-aBDw!y4plHr9I%r>vgRlWJLl3()j8}&<_Z{3ON zvm(ufH&P43feE8F;x*>R&O|R*T9qSiQoC|E(T`k?$fE#v9dvO$fBg6D`RSQq(4Q^? zEa6g-_Cc(~si^|R$EQ_NW%zgf2ZJl_TGt)-Q4Uoa&56QI>WwbC9|#2dOtY>DN*O)_ z?gr>;xnqpsD5z=c$|bHtTHR0n>p5Y28^A2 zF?CsFUZ^lWOdlovBxRg-ERYanita)QS`z+&|j_-TaNE1YU{myR~>1+!6_M z!`$%Uf^3B(Uv{x}9UT2MJyt4Xqz8;!Yy?+b$nfI1tcckMs04%k&jDey;ATynS0uYE%+MxQ%}I?O2j6@gqE8V&Gf(f$(=u6*Z&^ zSUo0IZc}vi5uAQbMK6Hy-2vU4vK?J)jR^N9l(hB$!WuVv$H-hfR{E+-_Y%$qwZ21T zn>WoASVPYJDnx=!lJzgQc^ws_IJCcBd60K$ejA_uqv*JefnZ2JT~#6A4&I4 z8$wo!_1yDU)peZCWl#QSZI)N7MZi?qB)!OQ@ciNcbU#z=np*#)OqDa)RVPlOc#mRi zH6)EKRkUzq%Zkl|%K58d+p(q^tpmS#^k|rzu+{bD-kL9B6l?QG8ji^REO4Gb1YKJN z*ou!Nd09Q8ollgIoCeKUzt1VRm^sqFzfN0^BWA6l^TqO^%@2MT@4r*z6bi93wu;z8 z$Qi+E($d3XTB8b#?-A%?j%1pon3xDAvd>y_uc8F2^N0w)So(~Nbn;;dQ8KWA?UwLC zz20DUWjvOPuB{^iQKoC zHV^(w^$_x{vOdGHv{}$PN7L*IJ0xN#P;_L(_-1aR*Cqq06?PB2oM$c*fO`VE-`#^8 ze&Kk`h>)a)C`-V-Ci@yPkZR+PpY_9DsN2cnu6@aOV3j@tW!B;~E74`u9T7SXMj2o2 zYr@-IOl^IGUBEpBUCjd>h)VQC7o&H6s~J2`eyJYRNtn6I9-ns;D*xCGrqNNgVgm*7=ViKT(a36#edNC#KUOECW8 zhT#?%qh5QVvf@&SHuJZfg;R!VsjoTI+?Od+|DcNBeH55)q%3;wM|@tNU4gE<_DYDx zC&naXmGFyIwQWr^{69DEg%!juK4opH5-*-*Qiz7W|AmiCBlZworAfhOuQBD;EPg*G zoa%kKL$6~CjKekPG7|2EBrw+t2UgwWhQF*qJ$yt_nMF95(bT=GOf9MaiCaEH%9eCsIH=vP* zo|oLRe+s_G-hwVmo>y_enkm~uhEbu#5NVSi zFm}IM_vAid7h=p0L0A|4At_FmIGt*6@H+#eFM*B|vHd8ANw#s=&`iVN#@CJ%`b9XN zX#RMUIKX`X-50n<4SE9|yvLCB6-E7YhjoRM41cn}BYevft)g5oamC2kQ=O>lh7vV- zOemnN^LF~9;knYf=KIswd{!00R}yf4gYK?#u_F%8?JI)P)xm=fhnoo_1eKaY4e+R>OU84kex1G;dybL-iLlxnSo zV^2NfHSd^VM+LhuwD7RcR8T*5a2{w(ZY9lS7E5hT8OUFuKz6hH9~r=HBbiO`2$oy0 zsha}sBj{p_Vvhb=TJwWuW&bvdirm2WzCHUhp`O0pCr)HP)u;rS_98FZ(^?sJO&$7; z1Y2fNQmNTL3G{}wS1E_{#Ga#o`vkgy9$D$kW4S|$lu~aSu7_)9YTuf^Tlwxa?l2g~j7;kcX&){-K|d7H4eDC>(rz-NGEo; z^@$(s6Z_i}@-JYx$}av0P5dSjG9NzD9G5rv#M|D0s$Wk%RJ+`TFZ}}koe+%aUd*9s zb1DB~5-J`{)7YINS|Spmw8T9RXKlENIxFO;x-wYHzCv!hGXF?WnjBQI*5 zLs>-#5zoF)qF4NoxDq_L0$DBR=Fv!BLadMY-2eOR{#~>F3mE#%H+?-Qj0X8X= z&g}6xLL6Z%yXJG=mVr>nc_#CDXy_)y$t7trcNlzO#~pj~ij+Y*5nN}mgDr)~jG+5> z4fro$HfxH1&j|3PxnGqA=Xq(kdK6F%(=TGMy;#m|Q1;<8^$=03gl-ZECX(ezzaN_l zE*;@Nfb-_i9B&plwLn;I{LlLLo!Z}b#D4*!99Oy4C?3z~G;aFseuJ3!@f+WyzQ^g_ zNpr{)y9Z@HM59veO}nyIaD?3Pb; z4Z0qz02cvtH6!FlnO53lDB0r0e~!cil0f--#NTB#Vn}QSMtBVt39f8WX}}Y-tjxV2 z?|P!we^I>zHD`Bxrv^`_broFz&KG~@q<;aU_{YKqqW0V=V}8FIiYw`hwc$8Pw9B67 zvgUA@A9BKNIjsR!UNOVO9Lnoh>&YK&G-g^^NG&+Xvb4@av<@f9K)!#^2L1(1e#6$r zC}~$&cla3!>p@pbJR)b(B_y2qHtW53n}QxROph|fzBD@9Wx+1xBDwK?#X9Qy{K>D5 zZnzP$exU)>fcy7d<6pr1Ib210#b;i?cE0ddxbk&bSN)_b7goTp|9VKVJsNLpx-HE} zl4^Tq8yz#Ze$jrbYCm!0VP2e0tNCPS7@zV!4RBFF7fS0T6@Gicw@{c*0%|{q^2d$N z5UaArG2I9 zff4Svo_~3dH4RjqE25SsnrPR@Uvq?-IWy$_N_z8}5q`O)O{tPm_^ldIN^QP^X zG3RxJLbBhccoVw}^I2Rm>68G9>&$FDIiw|!FFNQNDp)+;(Ak%47bolfszEvLNtWQF zO0QkV#{5;WD~OOx+b7mu4z2yLmi5u6qS~^D;m*pHx#^C|R*qMrF#R5!-~RU8{0kWS zV?C;U8>y)lqAwQRKk`;?lXy)&e~6gNSvsBiPN^A~$ekEbhAh(wFT^}MnCE<3#O8B`8H^*X z3*?Ipx=x(@6k+u>L(+PLUfFLdz92Vf-`wh!Og}1Zl%ArvI7sl5%tO6{LgV9Xt@2oZ5 zn?p!T#@JNi{&rIm4XzXZMnAq-%Lu*V@dC@FKw6OAqZn zRBQY}8K8vg=lZzpq$BPAQnmIRaR2Us{tFm&UV4O}w*0Mf&WORVOih&gia=w!Kc^f$ zhriTy&F0=W!*zwRND;ewm64oqrY8*nE&=FPHBO5&QQ}Es zDt^qb#P?5KF%_qe%W5rbo~`muYfOmnln@~!ISKCMBrKve6ruYrw4a`q*4sDGs%yHm zXtD_QfxHCW1N%zK-5*n~Z3n?c`?CJb$~@-}m>(D{2oq6%qY=oFho@h1hX-QLbgBoZ z`LiGmbK=eCu;rZOWm1>DBn-gK2l6EZ-5*OAMa6yD zyuE86JM*d3=;vHTHD!v5)4kvye-4{Hb+hrKuEaX&yWhVI8~^6`Z{8#V-Gj6?LBW!T zB=fftZY{MgXaXg98Ca=%%1Q2@k*SK!P}^vj?|%_#J^AnVY^m{QaOwJL#cL*J7B({wNq#iydPgi*n%#Y3(VXCIZjP*{w^{7c z*|&SuS@z*m`|={Vt|kLrsUF>|&Wlr{Fo&Hr7RKL^aOkm~NNnrD?P;Iq?zoZGn77)dDS5qR%}iWXZfQ5y0fwMLWxnS8>#%j`swQ1eF-hcb?-Q? zi0Q)>SGf7dAg z0%q;|No7+IJC3r-S-tpDeBf73L!MCX^bCpVp^|Ek&Pfh(Y|LiQKJv1oOPOp!3q!B` zC^LQOVy>du6vC_=IB*@dlv=u_-8xg*(tp>c|E?P?=vvECMouUke5p8qa3{S& z6Qo_QX$-2<_>gH7zaOV|3ZryAV~^ak-^*=d_2db4_wjIuMs`eCTbHB zBBxF0wajFZ+qShr6w}syg0L8xg57d?6$4wCkE#Z^44~^b$kE!ehUTHlsQtpp{Ro+c z()I9tk#YU^qj~--c*aV#Y5!C}lrJ zsVB*`>t`IFu&&>C_gADl7;?y5(a_rR(fvxT={-5uxkD=Nwx#WQ-3ba`QTo%w> zCt^Rs(Rr0)mHI*Ki&GwZOF5a!yZo$@=1}XyGWyN*`58o%S2Xz^1Nu35KOIAnuy+*i zG(OQtz5iM>t)k@f6L48Uw@-S^qkosq60`D%**yO8SniEdaf!_pV~NcAU3S#AzIlAS zoQ_#3gja!l(S|_$EW}(}46OHBvcT5>lhG^zIlyHDUE01S9*QtMJuAZ=w|x%ObK4zt zQ>k*xs;X5bh;Yd`o0^Wa3p*xma-GJ^Lg(;+saN!nk0UqB+5Z3u=j1vVyEON>NQKwMjfjw)c)kAboynFh|He7yKQBr zl^UJf-=oZB3TyjQ2yp+_pnn0AM3!E3#vwU$w=z;!8{Sa7e#_SF>`7{Hpy;X3!P~ov z8GzHj9h9??n*yaSpj4i!6*|r_@f*Kc?!C0r^{wcfvcIYBqR!9&Q z*Q;46o@1KVzF`-hK1~>fn>z)R?zU0*z29>Z22pj@)K$G8J93M{BPb%_a!oOxjBLPl z$={yce*xp4SM&wJmR`G5X&7qXuB#McVa@PNf37&*A)Pdj+@n@;xl)iBcZ=2e?DaLC zmAu32>S=`#MU!gO?^+L^eYlc;2D)giwBwpqJw0i<+qk329e4k1-R4QP<_%N|O#GDaO3K zq6E<4j%+3F?V@-+!Ya%%&d(b~LwWS``VUNvmojAr;?&sU3t-!SjAE&J=W9EI>*02N8A}tX%rzyvQAT&p8gb?7GE~=hQS>n zqwDnUd^u;W8U0#pe2HaYESe0+mmhQ=HSz{GdSofuN+H~DCn{%pl@d=?c)n{sK6b9R zqe_w$PQNE$7Tdw3Q8gCG*`UA6DH|zgO?pHNv%C=_{n}*%xB{TtaqR^^`|>?I(H&LW z3Nh{sp;%mLlnOwVoDfN z+rC(1rwB~XKCCDu##Gz{>)GF0@h@QN$rms9A%{;#MPjAW^0>v6G{P6%(0w`Hutckk zM0+6`Ey`HC?;Mv&Ia@jE9C&ZaO~*AAZ<|_UgpMwYePa8&SM;wwyaC;hRfi0nv=&Ha zF%yYm92a4^oO#^wLHbKN`eVp4)Rc#w)id>i$9u@b%;=6kX}_xPpfMSFyQ?=>B{|C1 z%CP>m{<*@Si>;16bh7Gt!s2^DaJ!R%8{5zKGgF35$FP`UGepQrdhMjZ;3hD}z0u^f z%CnY+A%g7%qE0`Jk}dlmIG6WPEr9#?Oy^&~K)Q`Ssua~yu{Gz6evpHQWZ;iAUD$HP zZM`gzo(im#4OrVL4dU~*Qs1$D6Lid0$Ew65{q9a;!nasqrbe5f1aL(`ch%ipKF~xr z?2$B5+2U6|LjNZ?L#;P%=Y=ctrXT#`zS`?c2u6!Jt19vaJW!^HT@v=5$DETeh5VS0 zls`fZ4+C5=(EW@w{dM8{k~Z>Bw*cq4GqRsgcx_K)5Z$t4-r<|j76(CPZx?cBJFIk3 z7^_ao2$PtaBxWh*PGD!t**86-Q^2||4!TE%W?qG}7!z-F18Phz{axQ|$`y{lF)O%G z5LCX}h-GHIc_n1deh8UgHs^{o;+-3a?jwt4%(h>Ath~0ZBd58Uoq_Yp+rP@x(&owF0)Z-uXl4k|#>XIkcB7n^R}3 zU|#|-4w9g|A?#3N#0k%DykDL#;o6?)*w|?$Pbh#`+aAL1_EegL!&&Op`N_%Y?c35_ zH^Kk*B`s-AQmZ|I85{A5Q1uFs@F7dbD(VyP|!&aCNf z=c>44V(Nh1#vu(mirHdHh2aH-eOrg=bj1B6nyz?_hi6aq|&s zMPM9cK(`LTpEM9M{3cLpoICON>&rtityOJOha@KzIvX4z`F&|os^>Z2bX#m&1e{0acfO+kk-?|p$)3K=^ z@($`ONG6DqI;Fef&m66{R2}axKB0Hl_K-CM?Xsh1>zI0_fW573BH+IEtLcBdkD{8184CX?QOZpR_cV zYIrg;a5z}W5sG5CVtbR@NuqtB1h=>r8?ecFH}~~bP%yLD!%-gK{=J6(0*2nqME$OL zAi>b}1XF_E$ITyc37W?`1H1Yb&gA6WxNTIlHSz9(5%U0=0FJP21h+*cP0sw@Yp?4m zKQv8w`v>4Ef$o{)3@T&m=byV6Oza*^V)VzvOJ2KSgY=SjQ5AtR)BL&wJ zFZ+e8*o!Wi%ME3|_U6T^j86!C;`+O1_OJdbgRb#SNo(U{dCM;fF1$3*v9+B2& z8U}8l*~y`9OiDy=Jmf42hTRjYB_yo;`MSI%BOsf(GkJ}DF6TECpTRVX5~>LKK^tOX zC{=X#D#Q$MRY7-rRFdmtHzN=xxGLwWzWU3@*LPu8I==EB90}OU-}^x1-%iZ^7=|)? zLGyX)bz{C8tBAY4GxNi(QEJjUaNoinHK1t z(mN&|5{O;SEX}W@^SY_r?(HW&_%no7#Ci#QJ8)V#J^np4WbFc*4x={Mq2eV_B5?W* zck@%ZvKeYb{rT44Gs1uFThR3>=eu9JhEl*5C{yES-8ZY|u=!!T_MzgK?6RA7gEy7c zq>3=A&x8u=7}>=pC}qi`gAT$ZU`dRUiM{<>Tk{RzYJ)EGO7=xl$3WkU_xR#PBfm`` zJHrFq8<~xMGfA@XZVqTBsX+IS+Rsz(7@YE3KOMe3+uqErwXua>aincOwT-zyFa1fWBEEsEycK7Z6yPJj zM>_zmJJnznWj*!ZkHY`|ad-#1q3GjO`Dp55V#kx?{6kwd`{RXV7au!%Yc2LYj70-k zaos&w$^aI^PInMXEb?AN$9Ycp)3_FXD-(%OLghQuzi}xeHX-adzek{F zRB7<=sL&gs`JiB^V4!IzzgcMDfiATx|8F2MM_w+Oam+*bR&)w>p zPDw|%RG?iCUKt!)vng~=Di?gZ1M&X%65aVv!)z6ViVK@T_|D&RwB?iQ920nqZd>>VRQ(Hf71h1jwZ8<)jV%+XP z2wa*Sc5tchHebPf=u}68_&(qog05~kO1ECG+yuR_s!x;A1~m&^sm0E5`k89W%hb-8 z2Im?yM#JkSM3mC>|Hs~YfJL!veZNDHEIEjZpn_y12MGd75ELY+C`v{oE5QH=h=@ow zpa=?*a}vaWpnyb)1_T8p3laoD1mj&b%zX5>_x3#ZzW2QMIq&_ZAAeR)t*(EqS{1sw z$Gyk8y~j>D$BObz&AD0&s+@xg;^yDKpzi>P@wLI~^0&*_*G|y&$(!0t+p5a=G1U0c zHy(5gJbP)!Du(k1Vydr2W{f`FB03bRT(0!x)TDOp#mqgaxcCmommS>7K4_0a)V0Ox zW(}3-A0XRvbX7mgkFy7&8Q7v0L|mm$Tw}Sl+Vd;JA+OhOz4aaL9h0+W+MvC@B}O*= zEpDpY$G2F2BFVw>RhctJ*AA<@E^Xf4U!{&troPf|T5p48r&w2~^q6De@3|ifRpP#{ z&sMXpO{>uw6x6HpF4JtkCBfer`((y%O9FZOszYluQZc&rSY3T{&mlx{kyH?<}J!Pck{SCUC*B0FRamhsJZfHRLWL!YD11-cCmcy zI79b3;z8LLoVa(2P0FG?xL5t=y-CrC_-uozsEs4;>^tl}>a?d>g>MHmJ>CagN)tpPwQCUO1dsb(Qe|5^Pt?R?$ zESQ!CpKSa7QsY-*4db)8_QW5ICpbAC9OU8MO=bM0?BKn+_%dx*OdO73b-(Yki)^1) zXKhRF$Q97ZaVq{{O1@RSzrmg6ti{zOeWAR7G9gWRTA?|ul$>x)^U8fpQ~N|WN^MBL zGbcD}cpE*t632rhR#&;9Coo7S&kgl*t66&V5^?1oWfr)aw7_tz!LW4 z^GTWDw&*oo@0F@(zgHbTJniA?TGex*vDgWH$4%5l?;?l?rL|FLwBy>i(yR51k;QRi z)LbvB8|NGAE$%ufW)920ZuL|f_0F)24B$BO?E8@oOOd9-+m39Z>R%<^^u9K{=nHnf zp)p51C~X5cR5$kIXgJedcG&T5de@npM-xlQo?&SYSI3ic3w;#0+tg$CKjPEiED($ zN{ka)DPI*GW_zxnyj%Drzh@(_=g;fAq)j-V_O%OuLZ(9|V-0?HHBhHZ`+WX&&o?UPVgKjtJcoZx?y$Ogfl)&R2GS{n)Ch4>P(D0Qp35ZDcq=cQmpG(ti*aIg`E%H zO?wrrJ#~cUMBxi=HQ}f#Nm`eKgAa_xwy{{;K+oF5esjm_N(ptf)J7_<-td%cylsb6 z`Z@P%#=Fttd)E26`h=BCL~+nXcc{@$yqOKTKX$8clSvB`Ww}?cj0LMR?Q3J};4zHu zajb4j(b>FB>V}8jMG5S1KjtK4)MEA6s?2b;(fWfuA;+0c_{jH|AGt=J=#}#7q10mF z*oBuPoVUx~tx^{YwXnO!%8JoFfz`b$(QX!1vbX8scrh#I!ksdgW-r_PRIZLC!IC#7 zLatwx%iLox>+oOg?CjP_Ix7`xRFYQ0eWgYn_m*Dee8nDGjIIY(H>@CWpYgUqFXla* zB3-#V&pVuaXz-lX%tVl$dLW{KCt+iq8Fzf!%*IxZJF;xo+#4#4MJba@$3(glZ;L#6 zV26Ap#@7?8n{-v>!;L0)yF9<@P3(s_@^Cu*TbWD!IO@kQn*D4)u6K?nG%-=_2#?Ta z_jQ^b*4#(JPggzt)>=w=O=f^|)XEQ|>xI?b;L%FU^C_}U#r5NAi8q@al0MX(jrX^u z{AlLPct0UUFTyG5hU>`Vq*rg!W?Hj5!bUS``hw@zq;*c<%9$HtvoN~o9Vqdj+}y@y z9eeA`={O#C#owot3KZW5=?-iaD7!uodSM_~t7PxksB)u9f|FPF>XV1&Bwp|RZ5F4n z#`(kD+>2|cH+@8VNMamLVs*D#QXEU*+Ob-u1 z(LIgTl^x8OTVvNuGsneC_V$+n&g)lsypcxBHQM~x+^(*zKfk29Y+7*9pt#$>*)n+` z)|fup^W)`>XG_>6=95KKA7SHg2CKVS`p4086nyOa*_1R-tT8wynr*xJ%()kION>b_ z2Mie*FJ}9vW@w5h71eHvtq^B;v+mCOg{R7kgPFN{>20&|*m;be?TH6v(9dqI6jqZ{ zLn<_@?>;!EoqS!rGUvfzuYvPS=09p?J?V@0EW|Shxh}MhWoSt#ccpFdYvX$sl*<<| zG^3iT%#DeIFIM+)_qJoZrCpp4RXN`M@nhzeRcnMW{XxEk>fE6SiI7gi6Wtgsx-AdF#V$q+B*@)0~*W3gVL3iHE`4B?XKJJ-MgY{OBtTX zY&w6Cja!1Ld)L+xnp(~LDr5DzRrd_azC=8i+qrM-6`zS*(o#rFh2~P&!MDPq7~Qj2 zU7ZGcEqRNk+X_uCZNF0nZ~S~*>JY-Fc%m~u?bDtnZaekO`;I*R%;n`aZ+b&MjY6`g zeH(wuQV5G%XZ3;h#t%O*y8c+*JL!okVovFO7p|4p9oT33a>Kirr3{+40`-c`0p}05 zqW>I{Gmp&w`1gZJagUOQEtwq7hUWWEwsv1!;&-*`*mic;ImZewv$P;1Q`jA7>!y_R)Hgsn1eg+p!@E65@oHn@# z|Ekz@{ELs&qdRndPU~7X;(nB1{5^-&ZPTARA|`P{(-rrMGq%h8Ub!!o$NZBu7a}h1 z5TnYkX70K#p5WM*_w7L{Q<}{{c-)rJ=gmR-#)6s`4J}@GJwwmh#PJY>)qTNg`h_pL z(pH9#>mX;U;gO?{PG#i{1vzv4HfqBu!A0uMj~mQ4NwG?xwUMZc zzAGXgl*}_rx#l+-4)016d45Y!?$())eH8Iy@*2rcX+k5fI`Rch?Y;C`bB9zGdGjSM z`Pwypsz;6${uY;Fo?8>@Ry>97Jw)9QtnN?w-vSLyZ;m*~2~s6j?v{TiSo%`#*k)5k z5sjZpl6GbujE|lTl}6S7^m}?F!A)^}@2zUx^m~Rkr-rp_?=bvE?=pzG7qPlLR8#M& z3$9713rbaI4^h{W8G=1n_y};F&+rd+gxy7rhBjdjsv&jC20JMn9{RTM)p}@$HOJ8u1}c%Q^~Dq;igS3s}5;22=`Ys zmWl2@`f6yOlIW9!vd)7(q3*Y%n!j|OiQ&1o=5-2(YR;>VOa@CmDnhJECJ(XCE$BN3 z;z9XtRk+L1E=K;Gte`A4`P`nGe(FBTLdpER4mpmuArDhaGsG{gRSKR>f4p1%c#FZO zaxN;Z7rzH7+N&4`m|__8F>wgT>Uv4ne!k53rq`PPx&3;R4(Dctf4{-~7EPfi;8SLuvTg)bNsNa_I z#Q3`J&6&Ho8qKv`{2!7PzniG>91Q*0?@+SUF0AiRwCmGA=lkge;`20;Zr+{QTT_&x z%Z_1mBeA+6@xKHOG`jYg?Oj!WI^V1z^3h~cFN5N4lRG{hqNAVL<2vPOZ*j~v-)UlO zmf7O0zu|Fi6n9NjPWJC;*O|Ta=-xvdXHi&PWoq{y=DwR`?j$Uh*3Ip3FrL^+VRUv< z(cQ_J%k#Pv`KtD8?Pt!*=Zg@%Wb`3JwXrbJU@cpk zNd~^3rZtrv^UQNsMY^j~hw_L}eo|Gv5`86jbj=u#TXBuh_EKv5#fJ)wKTN;q7&C@}-PZz8;kZ!PWie3LJ^uqq~#Nh64A?pvlY1_Hl zn6>J6V^hw&&P0kHcK>h{tNV_>|BPK{b8Xs&=}Va}_0A2|IG%f#*i}>!Ucg`WPT}3i zq+|u-mnKD?bMz+A$!=IzJH6ALv(n0NZk@{Z3Xi2tVfq;d4xQtZ_z+#!KDJl);*=xL z=`XoEu4tqg#3vt0vj1$Vsr%+BM)x{a_xw5!|5Uz7o4Xfi6J92UO}5OIs60v7_@k!( zwAS{R!|Y;@DQun#@(pxy{AvU&H=B`V8lAZ?yM+tO5SHw~nmtS{eIHGA)_^1%bwSR?v%7M1gRrHqB+&B64%MwSY6f7&+LOuJ9-{YCbW-}kIlC8$>&O5tdZMUZRSnwW|(JwP>Ak*>Tied zzcSlY(poDbYIyZ)duJ>{J9lp1-0^BHMmG_wYkVI^$@{=nuNJp{-Sy!HO1(GL3zH^a zeD}mA-F!fM_Mv3xx{^yxlz(ard|SxcDKG7c?rHFch7SbM9));NR`>;|-B^3gjHfbNX#HJ9 zVX2#$`Zh~@gSM7Bt(M%DG;lMM?WLL43uV>1atd|vfK!bA5lX>puDr-UjGKAx#*5zR zkl`qCd?1*H)t$SZ!R9(D7^pcvJRqU(uPzu{{h^GmVng$LeSM1gi*327VyRQXhxMj7 zWM;*Cc=eTUvvof@vblRK@8i|u3uhbfy34=klaAH>MIK$vk?i2L{mg9Mr+|+&*`IYT z1Q}Ke?NSt+qe{SCeYmuJfy1k*HL4*roB5{T7Tc@0Zf&2xH)t+!+jpPcm2G%kN*oRN zn}OABJz}z5c=+1&gFnML-L2=(&5CN=zx&>DQ@6X))1VMmLwE-*|^6wpFVs%B-QqCw@vpbrrsKjy%CA{m4(C-P@qUQ0N zy-kcwjX9&YSlYNkTVnWtD~rQG+T-hSUx$yrrssLq&SrKj^_3zW!Cz+ZHw&wqKb17= z7*}KI@HuqwzTOAnVipR?FTeP*O%_y~yjvr-cPKOUqzksrJrC2oM=lp_lzHKK*)HLQ zz{Zjje3RG8ALDg#G-zGV#_A^CKjzD`$-}JO9p zwx4-(<`FO3TI1szCd@wI(kty`-{hP+*d$42DLS~Jb_JdDS4tY zzRwo(b`69S7Q0$U8&CN9-&cTN+c=Sr(apo^il&swlV|QZonh$z{p&BfTG26gwtQ(9 zZ!ykO3X~@d=O{MvR26=0A7Hvp>%X^7<(f`&|A*myU*z9+w>py9)pTKWQ60pCGTY(m z&K+ZhcV*oK$5pka>a=&g_VBEAwoJB9^ES$H{t#5?bc`y9^l*u{ zRm^>GVEDLlE)`mHiR*d+R`<4N{GN?A4??a=vp+VADLZwJ?DWOe^TYXFt8X>zZ?|IR zc9R&P9Q})HiwgBncvhBv5pC~z#S1mom#pUrzPHi7(U$Pw^Z_H8oV*jY@Mr?fcrHOryIhAasxlWv(#^~O| z>avZr)2?TA%}AkJ=l;>)d^NS2JMX!Y+-af9^*3$`)z2Ifeqdv{Ek>FA!SSiGhF#j3 zwn6bK92ZpU6V^zpI5whpal|;3VRcV@EKdGlnqPPKVwtkNf24O=O|zXrxPV5W1XIB# zlVH{>re88|8FiEEG;|u9%#ztDlPzWqm+9VQ9iks!Ye|;2d_Tsab@Dz|_taGj$CHOQ zBr&x_Jlya7y4Un}m+Hdo^HBl2?9rEE`$*vc-s?#+N z8br>tyCkBvBRQn|0IPdY?AXT*7RRFw@cPryKUS(3auCs-elKYxwsW=Z!@^N#jrfw^ z(lQz}v@SBv4}&G`^*yyu$O_+C*U@_Cu=ZQ0R~X%gSl!#+j}z~hDJ}TJwj?mPbV7EtZv4rXU?s@&h9{404rOWI-$9^rgJTgDES|`rmkf4i#QI6GBP!koX-?&D3r`(YZlIg3RQ@*@YS!iZ{ z^JvZQ{fgdmQaRL7WZ@-bQUXIkxyYLfsNeMiIHb9c-6N0+uHCYQXrEo0|(nV0O1S)h)n+Vjx& z!Sy>`zQMzt>PKl?mCF?af==EF>t`2#jlp=Vwa;M?h_&znf?(#mW607TbWmf0c8o&lUs0ds$2$U1=VTM#kv9c2wSc=l5n$ zt5}Vw<$WrS9F4OlSl#a}_g~qH^;uDtZMfuY7S@sPvcqTN*(T3)*80yAw?2H1WjNT! zn>B^IQp=q=-g=cq8NT1Wv-NOZ-~9br>AQsg?|2}7{659%nt6UcBgi7x7%1=2ex)EV zK%j%Oa>rP2o(S!#RBNZ8p~e0ld0)N}SA~OB@3n0V{Z?PDP!HF=q@*S0p%cyal^q|4 z<=>;K!s>R1OdhwqwzV{d%vkugbJx?h`x1@PjJ5;5XC2v|yiJx_C6w3T*{$!s@mhvs z!fYWfoGpC9ocWivb)VE`o^$TY_lxCyUo}>@Y}I9z?=i)_9dVq;or+_5u5G=q@Qm_f zpZw%b$>hVQV%{>IjdodY`Skwgq0z*|P+yPNJ+5b>)Gz&5AC*BXrnLON52giZ)?jsK zta@XI8Y$o_wf$xSmP3i9>ft%9p`AhWpAW~@j#CeYKKfdv5GEIMjv@0Q*kCLJbs?G-!z!7|GSsj?-J$rbJdS19#b6Jmiln{ec$r$zoC0G@t{2PtDQ=` zf$3X^lB$X>&P4xy>>$U&$J!&0?zHZi+Wpvevs~}9h{;9w$9=x6EECpO`80F=Vw<+U zsI8UfyDC_)ysqPy2OJu6#Dg+)>hSjw!wC*DV@Fq>c!p8|9<_sQ-0jB_Qbd(QrG;j- zOj%Rz1Z~+L#xe{)e4tP?vLmiwPd{Ir`B7f3p@`Bkd>m--5*I zls|Iwij?0FSE=As`1}clpOWYq9{%8eck($_*C;F{dptY%#_A#?vCFMrBN?j}6eS~_ zUO0;#s*<>7x?lTH5w2|aP_0O2a-*gtM}7c#Z;N4}!Hv~6YaNDsqnGy&%fCa4-klH+ z%HP-PV`?*Vjrc?=_AQ0X^|e?Z^x>bjs@?lc@wlrO*_ZoIE96zT*odhV%EuhXG~Ww73^!bBuP^a- zPTH#XSOjD`PKO*M7f5@fTV{QFgFt7wPV4%O8JDhUKDc$M-Sw0MgKq_A?ns=& z+iqqBX|CgITlPQy{rR~?NZhYAH2rRveMvi3*KgO;M{4`HYUAz?dMmwm+?{Wm0+RXu66j^C{0 zE~mWosl$XWS6j;I(guv~3#_h$K=0wzVm)D(wUr*_TikH8V%t?6Xd$hr6EwzX-uh`W zChLHG;od{_`FT3D92KmhRetXG&QY(A;z_u@ne2=N8ob1P$xE#6K$<)Ih0&+f6x2-W z5BuA@FV!We>3DqN}d*4m1*3m0pa|c6a=6U)q{wm-+ zqLEF{{F|*#bl0htMz(k9+bRv~_J#!)s1S6~zT`DlmpWyG9+g$;?mGI&)S~D(n@;KBqvuN>18pRYB$D)CfAGVe1%HxP6? zvARZU#B~nrO0+JtY<-Y%R-^mE8U@8s3;j!qVIf_oOebtP^v_YJ@2MC{y_qZ{sHHJ{ z&3TvC^;5mnb0?(&X-_*4_LKPcJ7`W54@#{^?|1VWA8MMv?3l37^qy<*=X>9X)$b}O zBYG(wiM{P*vtYg)RVqz8ls~cRMBx)nA+`12lH!7ezP>tcXITp-#;ZxMua~^@ z<+M9myehselC_(?&3W?saA)tFW6(3d!K+SLWrHeT>IawiQOo<1w^&`);GxEd@P{Vv zy*^KJ@7qUTSDLw3i}Smqx@3S=@kU3#q~F(jT9OkLEcRaJje<8;r;|<^H4|Xbj z9nIT{-Iu(>>av7!Ib8IsYd>b%SIxF6uIv2ikf?8U@?6;h&2sgt^m)>QQbT^5R;jv5 zZ|5-=xT!jrd;i{9-o|Q+GxT&RGb%y&I4ti=da$~E2HnY8k9K5;TfwK$yJw)Eq%&jYfC@ib(i-geOTS4tHB>*`6UM}6S&XW?b@TfVL>)W*Lk*9v8trJ z{$mUInJd)a9HnxPU%yb)6)WjaD{^&H=BCQ&J%Zg@EmMVSgz>t|`;zxq-9B^M9S^^x zl3Q_<2ThoyejgdQuXHy)FeSLd%CME4+{WSAjnTn6@=Kdu9!c2wQft4>)n@Cqo0?WW zwWYWB^U#_R{6+ifeypy+y0t@26WcAX@g2S17B$`2@q%)U&Df9Z>Dz}3x>lQM#YOXc z+D{jrEiYc!Y}7GO%_|cgQ9^%q2R*%r#^u=N^#p&>`Y?di4bI_+$*aAzjV&nPL1%Ju zvE~6zpbOvohdV8gD5v8JJsO1Dl1o+bLL4!T2F-St_GRckvxkL1(RwkvOUIBfnV|A%3 ztX|Wd2*A0^-~TM|dWSDpCPTP49be09X)f^x1~r<=f>O#eDXX~sqXb`ymWm5)OXUoh zl1fPwVKJo5yEe1@-g9|hGJ@3=jBAT;`z^vA`DC#5wYZ7pKF&<@TQaFW7K7h5D(IQ* z(kyT0+Fp@9UnAQrJJ&Lnc0l9;Te^zXsltU03!Yb4oc7Zhwj?Liq-D$-@vl-<{~35d-KgN9 z*rC@iPbRIA()Xv0OaExgOK!(Nxj#s2lReiaj4s+^6A#KFN2dA_Tj}n=vD$^{Kt*%HB>ni$=WSY5$;_uEZ-{ls=KDkbe~d$J{^o-!i+69-LZx1?zP zcXr3PPvdF2rio*fo6~O%L|_hi5Di`V-bOuvwLP!e>jh(ZUWJB8J4jv4zzw${tsxS?lBJ-Fs9muSeHPwJ5; z)L+T&4=quX+3vlUkufLK=xC#w{$!n9Lwg+y_nNd5UCnB2d3QbgA~Cw?S&n#6R!oI$ z&-}gRWE>4!(0`-sHWIP|cwz_le zi#+aXyKns3MfK4b-A`EE1~#9%)iE*FNwYpb4DQ7*aQTEOnuYFP=WBAS{MWV0^_q`f z8|nHdMNiEh{W%d=H2u)-9Cvu^X)4N=T$XI(eC+$a8LaNF5ssc(|0jIwn?Dtbl=LdO z(l}1|8hh+E32BiQ?hmvvAwO;yAwth`QQD@HTHbrLjrn5jRqBr%y6SvFt%W=v@VB<* z`}{0c_p8t=zkxlU=(>u10}K}_4}O3BEE{gn=Q6x*)x4+S`p9^C%eoH>zZVO-W9wiuk=HU-3;hm9Q?sQXQ90s@u1x6QzzixmX}J`Je$SZBqX%e_VCrU z@1DKVZRpvwzvkBY2h3E3bQg}wQH4I-d9l4*KK^n!hVL(51b&m{Q;=rSX}B}eb(-Rk zocH?$n^#pwv`-(2I;4`~d247)_^IH#lB+f^`+m<*5Of2<->+ERAD_=G%*bVUZ4l0~ zxS7V=-;+8SbnUSntLI6J&Oxg1k;1~mTGPc@t|Cuyu5yNp>NuItO>Y3DxKSacN4&qM=r2yMCve!<@IAa`yf9JhhlPCfzLfwuQ<# zAn(X_jwSC<2No@=;2LK6{avXwOc*VY{onP!!h7+fwnG=5>B4~7Fm+W|3MKz zW60Cq^`yNAd_T^J!>xv~^nXzE|67`hV(Mmp+6#%>v5{i>uY!z^m9?9@qa6+>&W*#t z5DffR*Z-&5&~qU=i0Set(%+;AkRm{e04V~b2#_N1|HlZR{mWMP3q6CGYU0123;cJt z6V;Ic+Sunjly_(+4#x@glAitk-4Q40ks?5f04V~b2>ho<0Nn?@z0unP9Io&f>0Qfz zdVl>-@ehrwqo*{3k^KjZ+VMPj{D- z_Bg&M9FG1!Y@8zhY&|{gJ#BHg+?eJ0^#3M)Nbiibs|(VwadeY#{U7kfGxFKV(aRC} z{Nd_LIgrl3Mm$i$Fgp0ea^HE0^dkIqy zdwVrLX-Pg$M<09lqhfrreAX_G4sPy8;aAe&`1O1FKeP(I2Xp};BXCuJoFoM`RFe=8VPx;;Jk>C*F?ypg1pCsyyt{GYRHR46~WO=$V0zz zcb$;eLdb*Pkid}>&RZcxzsG=DLP5xTOGx3jd2r&WayZ@*^3b*EgnD}jd8;8W3-VC? zy@WjY?M9p-%H2q|h3 z8?cFxH%z#W9rCE*9JObJkjDY%lF$y+o>9ny-|xm_4;_Ho^Mi057o0ml9%|1|Lf#re z9%|1oLLN7q_XFtoO~_jd=Z*Lr_zRqaY}`5k>7n|_2zl$_yq^$1a>zsN-~k2+d6b0f zHbCAmA#WArp|QdXj6)vMpdnnx2j`=Zhpwk35`iS(4v-9_0I5J4kPc)3nLrkh4dej1Kpv0}6aa-l5l{@= z1xkQY;2uy0+y@>24}nKOIq(>$04jkez*C?Ks0M0)XFx4b2h;-%KqJruJO`SA7N8Xf z1Hyp_AQCtYoB@0RKj19j4+H>#zz!2CA7y-tB z31ABB1NH+405jkqa0oC54g*I33&0Yv0;~ZWKo3Co1_^)>U;3VZ;@fN|g> zFab;fpMZW~7-$9BfDRxSa05O={~JJR20aHK~u!WdN0b7AM_{;_AZAcRV z1~~r#?Vbm|01H41&U;_*RApjfj66$yb zyaqafH$WHA4ZH>30X;x3&AVubtEtdZF&x% z&uG8#5f}qT0JPUYdkgfLm`{T?L2xv)ljGBWwYNa?=@T#od<4dU0w5Q-1EBs(g46)m z1MCJSA#Vcs2#f<`zz8r53;}3-qH$UaR0B@|G$zs5L}L`q!D2uahy~D^gx03509vQe zn(PEf1J(dqW6@eG1)zNdgaN;=5Q9_{5CMb%dVmI?22jhvRU8$7u7~j8AgupukF*)i zHvt;~K7be40Pq0ofwjOI0PT<10ajogzzuK#8~_`@0x$xr0S15xKzl88Jt~LFBORoN zbdf%)M+o2t1OWkH3*j93Dh?ojiGHIL#by_PVxkLZ13Q5ofF_^@r~t~qHb4nb1QY;y zKn{=vWB|hB5k5gNMEa;NP^tl_1KR;D0JTL2KsI!(6<`VM0d@n(9}BTiGlNI zAPR^CB7krp47db@0vCZ0-~tc~oCp4@jqRWR?(?fqKdK`E((3?<7wYGmzzu*{KQ=#( zkdN}vb?6#&9uE`|@(Lln17re7Cj&?aQUO#?3V?KyfkfaI@K1H!CglIME>!Ow0BIo| zbX^kge@6rBGdjm={8M?PpY{iBbp1d1hBW`GRRDRp02(hjKo&qOpH0Xoen!_|&-3AP z9wv_x&WT#Y>rh*Wej=ZcMj5aJxCfL1>Ocu_7r@SSbj>5+A#fjf0H_0~d?io;lmkc? zjSqDGgz&ivQse^}ChdmvI-nhR19Sq-z;mDxcm~u0^*{}P%Aze+dJh2R_@1N{1Aio13wgp{>^wG6#Kr7G!{M9d_7HSXCj?S_5{k6ZPKgF>Kt{DVSpCG*f0L7NrKd8_80aW%q&3@`;S1D^m?7M&xA=d*;*pD{M% zAF2~wgX%%o%mYY|SRUmOKO=4A-&cUBi_%4acs(&6dmYk7_8$Pzj#A<|YCG|q4BCe_ z$;8ipO;Ma_0aONEON!9VqGX7 zl|k1NeWu4~pnR-P=vfTq5kX~;Zzv8#zlr^bu3>@eiN2%HsJ+Gan&uBOyi4rO1Z84qFFye4{oI z+l$6BYV*ur%Az`mF-4ka9-}StoT#4@O!t&oqdlY|u2L2MII57|&YT0e+B z67z_CLTnTE^PkSK8mKRo08}2ufY>fn78`SHAOBNbC@$Et$amzU9;CYfT|fue38(@{ z1I3&GBLV5)- zfOGUcLJXh|=XZffI1dLxfr~&e;13uA=z9kAeS;Zr05ArOfW5#zU_W32m=ZqQLh1n6 z0oK4lz#KRPSOFHmVc-a0383q30DIsl;0PQ8yZ~3g18@dT08YSh0Og}R7eeX|sT&{! zZ8-%gDvQc_64H~9dIM(xU%&_OBc$gb4Fm#!AmBU@0$c!498i41AiV?-_rei`{1UK5 z!8wW*x-J@06zf}%?uB$85KqWMF~14K0fvyD04d5t=cxa3fNUTO$OJNgbRZ2#1yX=y zARovB)CuL<;Jg)R0SbY;KoL+3lmR8cJ)jh52A%^=KqJrq)B|-uE$|Ge0jhy2;3@C~ zs01p2$3Qvo2zUrQ0PX`H0OZFgFait%L%<*~0Q3Xzfj*!Y=mFjVZ-H*03wQ%`0g%X56l6dfmr~@K@NXGpQkLRbSmc3@<+TC z;onHe|F7?prT+JSBe5Q?XM|yqa?2&_M9r208Zs#fMF|E-v1^kBKX^-$!Nd#Xxck(QK@l9f<2fietWS<4~7a&EIpGgzcR4fHI*0_$U7 zXnDqqHK#hnh!#owTQsD$xueK6Y`=pIz8+~=2`T)0IOJP+1=D_8cI#MF20Q@gT+(`iW0ICGK%=OZmh_I{)6?Y zQR&Dx841u^eqV(=&|7SDS@kK^6mOB0kX?RL#RirWtIp_K&vqu_>yeaDSbi@;2bLs( zKrzt^_Q-2F2|1)z4J}3WEJVE#{@8l!3puJsUPeJe@)cN++SON~FZSE)eTcUxp)%;H zZyi`D4#|j09J4wA7O7?5$e~|3!E*CK;NIslPv%!FYX}zRr9!{eqq{Z}EKTwp1ldw0HYbj)o<4XrZB118fb zA>D#_{uQ-IuyBKg%FFEX9xm1=0rDCrYurAt@`C&4e;yZDoB|0#xExEa*E#q_!Yl6u5V^_Z0F?5(bZy zk}_D(2x)LTbknd!&&H1(d9Bq z@)DA6_NTp&2j?2+ySE!#+y)CwUuhWf=sSB_D6__n``lHEH;3_RFo&h^-`FEH*75*a z#hyIWKd1=I#>)iXY|9d_ZYNVAU##^`Lp`;9>8% zNqRQ7OJmb+d_DL%=V5Pci=2!3(ACEs^XwWbgVqo!{J)!E1`irW=;hQ)GG@uiz%P6+ z| zc0zmj*p5hq-qUIZ3tIW0w>^(pdmIPfI^SnDNBvG%!dsvhWO45Z9vprc;rVh6H7i)8 zAv#cI7%XT+7TDil{2BRTBiT$5hf^Ukj3;0Xin90t-wP@y6LyB5T{^msB4Gn2D z4hXBu2Fm5$9?J@2>g=RCPEN)MIVi^H-_oEF*;jB+a8lL%4Bi9$>hI_&e(IRD7w$Z3 zcBH()0uSB;xM{##aCdR{0IzTL@?A8#yDATF!Hlw?pqMnVoMpjuwVsu#r;3mc|V zRxBJ~;e|3g%D(q@JWleY#Lq@qC?X3Mv?dx-uH$i~ueM&X7=Z=uf`RoZzuL`5N79xp zs2W$WpgW+hTiVWF&Xm0?Wx@%TvZ|E3@~k82E0%16+UvW=Vk#5H)mALEVA%v}R;I>l zCQZu?RxBUD!UvX(luUQtn-&kQSg7H)kJi!Y(9j+lofAPTEnNo|)VIEqHZu(8voSG{ zB3QnKYi#y^dDDBPj1EEVTpPKd$$9d#D;9IGtOd1CX1%eDdiS_iEZ$&Q1D5scmcmD5 zm^xQ1kzhe9Y=0HUui&m@!z-3Vu%Pw&c!t`8Am53k6-x_|dB5G|I-zVtjP)JBK2$pnXV( zSx)<|`J@rN1%Cs21QxXJP_tXI`;KcCf(7O;T6Y*=f}`2E;C4NToh}3I9AIjpwd(I` z{%ECu3H0~XB@Q|t&6`hM-3+jdE`>(gWcok$x4l5FDL_puh+tbGV46GJc3>*V@8)u?j0NiH5@{CYM z=8COP)$KcH$;s|R4(jE0NKr2+>NQPEC#*dUzM*=gr2e*tMfW+_!h+ZDpbYA5@{F0L zqsJb=N)8(e)EwLhSkQWqXtu4ByvB9|tRV!izk>zMxpPvlz1T&snypxvARF!93IhVh zSZP1StyqM>g4P4w5S*S^rrFgMizZmms{AI1vzYd!80CuPAXv~!5i^t3tbMY1^NQsJ zL2Y+;_8A>xa*S``U_l-@M0&rBxO^;drA!(@t^51eI=ZQ$3oDk#V1e!pG%untvv&-3 zVgFxuvsSRc&d0N9G0UX93G{aafA3Ke=piKb&-%_I9Chi=V zK}`|A@ci=_MN87(cY}oO!9UCr3J3`w=(}0FxjVv5-O`Yke^Yg5IDRC;a{)Xh!xgAc zJum70Doy7{W0bIkOaTiTDWb1aJvyB4qP-Zhzzi0K&OsybzAyWl*f8wxwo?bV5uay~vjG|o{TKyIO zX`YIpj)bF#;6b?Ewc^Kb8{b12w5NdRJSAA3h$XyL-nT}Npav~%2Md~Wi6P}XvVJmV zfCWt;DC27H;b0Hxd}4gY8+UQn(Exs;wEOfV_<>jR%Gb| z3tF!!&7@6RsB&t-0?(7kA_(A^$*8%#YU0~W$F;2p4_zHMRH^XkyOPr~G6$beR{qt>2YCm=mJsP|IR zAo2*5AuMAa_THY3N6+Ax__a*8$BGe0BE;bDy?{Casaf+akI{?N!ijrQ@4}i0YElwP z@LmTjaB~V&=GC?ExuU0!x8Uzga~qfMDIumEX;0gNPz=x#3-vI;)(N%8W0mvhn0gG_ z1xPOM6TLm{#U0(eT==}?zcu2j3cv!9R)Ru*U*ow!1-d8j?<1agFS!6$pmo%u^S-38 z=^T2>LHl@EDH6cK3YO!83~M_)y>!6>4<9gmWdE%8=h^rj)X)k`9V(E%|3rxj>IHn4 z;y5-h?-PHv zXPHr_%+^?OiHa4=D#7J@ih;WLJHCM9Q7aY!f+dz$*7=vh5tw*8fRY; zQji|mSxrs`kCSM*#(jq?&u6)I^dh2rk*j_sObcc`e_Z5pMSkS1_k{mg;O(*%~iba=T z$?xr%sT5SfKL;<@V-FV8bJE=}taxIRLsrTJg9Y_m*a5aD?Gts8E0#2ZWgY#_bdfZ* zz7@+eu%J;T;V?Fo#`jKR#qt3x_-E(-(ARq2-%VC5t6<`xQRV2f(Na{u?beEg4=l*H z<@;T_5e7YQdA*rx`5=s!A7;el5pS{%LX zWpK$+RXe=IuSX*bx;MkS!N0tJLl!g>;M)|q0L_K+)d|7}8U}Z)c<_i|@tt&N31yww zv|_0N3))vnFil2;d3Dhc@?`hNA z)HYu!!wwc^u$(j%TP4tXAqtg2i-;udAD=PMR}wgWD8mkAw6t_1{MadvEtf$XI7P5< zfF;oKa5Qyly8ynWcn|gvEX;c>Z_FAeDzA88L$IVQx=B(ttaV+noC3=lP+R4o=lq^t zbO5O>_fIszvWp3KW$%{a69f;SrcAJ)r>U?f51HTf3|&|$^ORr_-dUs0Qk#X3&hpr? zb@9ZHQIkINA@klq`jvgi15iY(Ch;2%b}~i?DC*020vdr!|%>);ywOb<)W6^kIja-rWp!0P{M?>hjbD6;++%#om& z6;9814!i6wNm19FQA`-o*_qzmfk{r!z%DAH;u+4!sTeRvPR#k#6EUIZorq_`9PbPt zdU~Jn)c^0js_v@p>FSW_8oNL3jMH;L1`!-bDds_G*sI+-jiy3Z1um+Qu*8q3YIfduemN=eDc9=>E(}`HwLQ@M{Z``%=%{5oh6HA z);Du)o9ompgI!07wb^TxYj^o+-q2}6IxV4X`+r-_Ev-6TvNdPcx207-W_??3d(l(O z8gp!F*FImJR!f^(T3nmu_Vc%Tvxb1*ViEmC`aZ`+^WamSNa1tmq z8+d%4x_%tWXF#KQ)fu<7_T8m*%NY_4`2?q*s?GnuEZ-DbA

bJcmbEjxHP_q?JBc+w;o|4|OgViY(jDwGk;+%^blr)#w8DD?e@T0H zpEGX8aRYu+;xsMfMfD6Qv^G1TdGNrwYb>)dD437ZMBcC~g7)(&($EU*`ZKQDWUJBF zz&c4BP;L8tzp%!DMTjVd-4}3R&L?p9h4V3&bmT6Aw@}u6Co-1kF0R;sVzTf)cc15tN|yf}jMgvjnB@9zu6! z?|%0#|JZz$c{Foi6>SJwGl`wzpp}t8s~%5DMIoF3e?HpEAxh9%Mo=~bZv#b9t5)2SIDvr7MG=S!Wan)osp^s9A32G(oGW zrOSa?20^1{6mLgE>-$3QYOy0Za;xqW9ZDRDn)UkUFV7Quiymp+QxDyF!{x^PO^$Qu zDqaJH#-CMJwzl7(Yv9+aKQPyixwkaSz^rd(>3j~}$XfK!*VljBv+ywZ>Nbt{UwPM56in9F14z}!ybl*fz~hXZq+n$ec5 zMBmz1wC&`W*Ji%EaLNumf8!yrx}?~#8Ah80)ot6M{ART9LYuYUhR@HOzTiPdW4EwT zp!A3Cyt=~Ke;<3=**AegzIm9Bnkh@Rw&ToQ%=Ke#b3qofrQ5@rc{6KOb!|KSwOIyc zv?Z&fW=s9-{e||f-}k_8rrmk%>8eLE&mhfu5NxT3iiXSv!nrP0)+Sq!9EImNSzilZdyyrK5Fh0a3BOUo8u9<$7&j9K57Y&$i# zxuwOylGQh}hHQF}u(Car_;SZ#mp_L2fpiHD@Y`@KKR^E{W0sD2tdG-9&9jaFZ7ujj z=mE`L<}BOm$+s&Vuc$ead6Y4ar@!R3{qyUNxiy;m9kZ-|$*nO?n_F5f>*u$I|B_ot zocX9(N6jmir8S=VPsI0ypLaLbt<|UK`}TVIV6pGxKPQfzAvhS*7RUHQgavT!ofn^f z!xmS(OM6pdkL6@gXsubg!8ry;V0Yf`$6C4-+==s%}1b+kJqn6te zzIjeQ6G0gW%640KZSvvplQ45|C>MeP$Ns5bb#B>r@@^+=p(qc5Leg0y@$r$%6`LmAy4zO z|9Q_V*W7l*+KRF-D8%)USGT*nq4eUqijoCoV^BK(eEH+czj@~(ML7o)vg%&4;tR81 z_+aK+iZTarQikD{Ay7zen>=~s z&dFu2o1pSJ7Zj?wgVJk#@!wmwp3D@sPR;^lT~OBl(}QDnd40!=n8Jt0=7Q1>lyPGU z7oW0l6#yR~|U@ z$gR)YMyA2ud#9uvIO&ybZ`5-Oh)C1v4d`+fdIpGWBi6RHL9HUkuzJ*{x&A7*@3 z`V@M=`3%SXL!gj!K3(>{!@gK%O;J)l*Y+$Z)F15F|Cmu%Z@oH6lPt|G+hGEpL5{BWqCh0EKjP zN-jE~_qE%;yyL!-0=bxV$0 z_On{c7h7(>;}7@BG?3^EppZ4Z_f_xo>wid>C@Gic15l_u;}h%d@z;erz`K@ZjWpkY zLi%>*s()B*-?zpMmuM)@N=J$`$Jmcwe|x{4sWQz_gLe~q8MGq}X~-={^!KiJs9+=BxrkFX1laE=e%>BWUFm9}m zn)`D3V}F0%ib*n!-6l64&Em`9m7Xw%z8`{{SdzUypUm?=gXobAS)7NF29V8Kam zcE7P@_aQ6;9J`Cx^TpvUP8#zZ>7|qy=hB_;-E!mgH-E|H;X8=T5;aRF&gg8`H}ed| zJlin060_XQqo$cRGnzS#dG=(MbsT*&&v(po3NzPRSz^}tRN{~C{OP18ulk>A^=1y@ z$l5GXv-X1$X8mQ_ua9q+vc|X_r{>JOnPm{C1-BO_*>oq_ z-6u_b_^h4pSQ%Vn4oh25W)9*|%n~)Xdh?hSr=;duFwe=&C9PEGh8xUZ7VWd={7pCd zGvtQr0>~rRTpqLTnDa5Gi8D(xqy79GEZOr zHP_q>1Em?w%$qrlIiG+wCpQnxXaRaHud*?x30TucrZJ<%k-?JHMDuJgj=jp1Imu3>O67)Azy9&0rlFrtqf;c917H?l=D?g! zoH<3De9ZPYb6YT5-OU`B_3gLE3d{D~ao64UY~q0p(N{@Zr&&5?-U3>^)G9Lv=6uY3 zuUW6nmXbIcZ{Eu>%X&EGqGX*MT3CO|kQeviU7n%C=$;buj)1u>nB``!xj21DoVmYw zO;dCA*R^OD9fA@L)l5D`JuAfoHNGt!M=<`X$R%k zNVD?%dBawkW9_IYzm;h=TmSm0gHwB_6y*j`X!n2C=of$5r|rT06~$b0W(&G`1dL@m;z%>FxOkDEAtHF11o%(Y-1Y2$dpnD=tbvo!OL zwAl~E>}~QNpOXJeJ|%HR%{cwRe_DN0gW3P>Kdt^ho@8|U&C>EDi__}O^MfTji=KIi z-&@$R?iVKuKf819+UvXv-pvXzfufk_A?DfO&p#hsvK;um#usm< zY95*XGwVbPfmd>{m-T;Uonbrqacsn9KNRyGvUzXnm+Z+L(8EUVj{W>SUmOd@{~bGp zd46E7IddOk_N6wDb7m`BoYrXGeKC*d=8~GZj$^C&CC`K|h0hb+Z|S@r+_%?fQ^Y)H z?-PaJ#s)3@M{GL(*O#mLTe2jcjac=Gjb9!!W6Z`(;VbM@U4;pmH0X2AJZk+N8vn?% zG=8S!2%ym&g?FsB(fendJ&R7O&~<;!cpoqe12+CWa&r2vn=jpaEK~S=N#L7X=y?L) z!ouA|gl2eE3a3@ZXUZAM=Zu*zja~MTRp$r}$TQ9YZ*pF3sC6X2l6qz zpM`yay+5x;~FIvQIo76q4wfrST6Rwbw^aDvII0PUPdi{S#^E*}UeK zhSOv|O@-$!Ie+aF=#{J?^z2tt!-b%bMAx5n;#;@={T|Fmu~*F=Ygd9oCr|eK_OW{& zTDJXCMY&U=9d`33AFp=mM4YS}M{=L?5U6=;_YxbNfjPJM{ZXVEK- zsGog6Az8n)`pA6$0ekNW3ULh?@MB=8pN_F-FIw-g(d6fiD>3QCgoBZ$AJR;IZD8ML zQ;8ntfIYx-SQXH}1qb}?)PEjY*%=giaEc_FDd9b0yWzw|pY)8{Ypp9~J}7C&RI$hZ z@tD+c`~PkWI%@?9(A!>#lSIv3|5bPTz}25zjq_pNMu0-+nGQJPrCT>TbT9I%l(ODc zrdjUm^!p#bcSe&+Q|_|z^zPUfU(WvMrlTJ{yLYd15SM0W=6vWaxgy^CvzI^bgw(~` z;9j=ZPZl1(U*RvwZO(d|F8|=s$GnYv=(c8P;!lz?u=l&;#w=P?1Vwr-u6T+lTn z%x0(cqLWUz8jh-a4N&?5ZQcI;vj=U`NBGRK#!rxG_Meh{==D49qIYoRS<;D;@}~nb zkM;iXh4Vm>GAJg?U5N=+&jS0AA74CR)JmYxU9YHxACQLjcH0KLb@4Wjtat(_a&0!L zE0gL%%{`kt=j&_t`-0Bg5e4;=v8`^nIXB$2_1J|6_W$^0m1h1lQ41@7GG z&WG#AEVqkJ6>|Ih@e_(OUw#(nLP@JgNB8-y;O($S7A-gP&HuvbPlto6L7}!icFf=Q zJ?e|6-=Q=@M-!(B4zBpa^iS3ruz=1p(Q_Zr>uo?GiQd%nW1;1$_3@ezX%z|KNl>WP zf5`T_y}0o%3z0^?+xL-7^UZh1bYwe1ZzerJ<8D{cG$(oiix zI_sP+cuODl*xW1nT(w;9Udte40OD?jzoa1tzwqg=Cl~r2#=LPY>wh zt%);tjR>I=oM+-M^;M%A=U%h!Gmou_G_o}Ya7~^tsM7%6s1E_| zdCa^?SqGFy_Lc$Vk!b?TgKLUOL$>>!sJX+Q9CpCRdwu&U$|Dr9;oP%C4Zic^UvAx^ zb+wB@p|KItxegTa`0T;?;MaC|Nc2_cM_U^n28HY)-}bX6{Mh=JOE?W`sHvgnY$3N} z_Drp^@fin`zRA{TO4HiVevaVn+VK-BJwF~neox4shT0-1RHvuhZaufv$o)tYsV(4) z&16spg7WVC7E|x6&DVy*;1NxRu;}uF%BGE_r6XV{`Yf z!fE(~Wy-d3Wi;+K-{aLUmYp(`$|Gz0u=50O*R;Ge`pWCSrPGqc0VEnYW}%0x9#3I& zp!=PNv^Ml4b6IpQ4Xxj;`taBb?-<9t(Ie!MQEm12n3I9ap)h zVfM3gahsgeBL$Amd2#)4+<4%ObvNAjfZs81XsHHFWdK@ckw}A(_{&!1;O}7l2mHfuo~=X#D(6_59ko&*9J+qSaq}^7o%zHmPl-c>Qe% zM)VvgG=KZ`uU>xi&-dMSqM}R%h5GHIPWs@*H`;H$R8cMfr9UWVoxS$DcOEkN0Y$k1 zl(j(F^PJUI-~QDJ>nX}Z5^eM4k34R6aQ&T3v)sL%$F?3fZn{d-_hP~Ij87JH9KXzLyu(g!<58MRFB5t_bD1f> z-{6RQn;~m4xoyZLi-|(}_=b-&TfI1X$N6tCg|*5&i>{V6>W7B<2Fq@*WU}dozME{f z^Q0BNybow-izCsE9XwNv+nEjb8g|z!-|qwpJ*-G+Kp|Nly~kD0PFwr2fg%kx;T}-d z24(ddpS^y}j5p|HkbDU0RY@8Br#p9;c;b&+G8*gK=b)^LGy_)O^YB#H%iDm`DrTyq zE*BhZ)UsRhACoVn)fDw_fm}~P_UOo(-as0v?Th+O-Ld7UTWPLL&yS)H8FhsiPpAEK z&lTUVGl1455^Z--s1JGn(?6~^XV4GNa~f_Xt6wS5G7pTpsdf3>hxD>NXVWl9QvQBX z`HQP}_zEvOI+SKfdGv$xZ(3vR-M?0pT_k1LKF{8J_4KLk@Umn58JsNXp!XMZ0hIQSUZIc~eqeJEdc{Ar~!tR8hW=l&$)2 z(bDU8?_I4Z%U>lpXkY8!EA<(;=2wcco}~PK+fO$cfA*!PE6QL=nfKMyfyZBWFy1Y9 zWW5t815lnT)^Gab3m>HpSCp}!P}@FW`}x1wV8eblDoRdLR$F_QkFL0N;!}!pilp4U zTjr?J4x8f*ODCU8Bqe*yH9x&{{sWl9I+WW$A&r0j>b@I3zQsrTDN5REuXHxR@A8y} z)_2x>hE}_{)q}@VUz_XOYsQUYhWZNrlJ>s&<|CKi-25vuk(&) z?_OI`MEt|7v)og(8b*FqUUik8-=7cdm2;Qhjiw}0*`MHvMO?Kkd_n6={gg&TdQC5;#FF-}pkpwLR<;n{oau))|7S1QV>pwLRZaf^zV= zZ71Kl*SnjjH1n=OQSooywc_u}qwG>@a3*h;liBQG+saL}N`rUpE?cF1GJ9aTl*xB) zKWNCXL3U=cRp{7y(1=0FY^F0`=vbLhP6Y_nPyYu`TxrDXv;TSv*rEP=qYK|!_15J5 zTRe*IzWAPf+Qr=`kAMFA=Oul)FK_*N_>;eVyG#oQ{G0Rrn%9>uIB(7NOumuA`n-AV zs6`td`^PfY7A0_W)C+@7I-q0kZw`Znlk%H3V(7EIx>x_PoXlh=W%B9Wk65tTqTk%H zdG8a&NIB!jmYuS<@7>=&ukh3TcCeR`o>tYb9emt%V{aa`?z{M={7zc?;MIRxv-QnI z_@?qaG4kjGcbK@%%il;T4n1@kF2~BFDkC5+S6V|n(!yK0R=bU-aTD}LeAenHcNGc~ z21((!wPy-BYrNgaf7?2;IMmCay&p0Hcm zs1O~6Qm#?1Xi9b)--VV)R?1zC$#k*^ZAwU9+DgfEraMu|Aa*iUP9!HL%gK^IG@VIi z3!PP=r9v@{^(kbKulR}CWV@C12Nny(0@TMJjK_|xRJl5|n1t!EP#ry6sES-J6td+^ zv8~*aDA;zRm7mC!I^J$8C#f-|CddLFTd_(#d16kB`NPhKHHNjRPyCgPog86>`Y`*g}g0hiivisoE$vFsdZEd)kE4! zFg)p8B9kv?`3I>XX6pPK_RgGT3m($Ro)NuaGEbkceAn zf|#-^MXNO4F615c5t>@DElO!8%63<|T(q}ogj_l^I0n))IA6?-w+9zWosD=QsWCzS zpTLy61s!a;b8<*@4HU_=FC-^HBXzcrPTF0AG0B0jQr0-}YQmsF#~(jv+>qho&xnvL zxX=I>g~yzlkQujNTM1M*R^lPavjr6mDEen&2#qX+CDx$K3)}9-LrR4SRz6HpZXBSx zzZ0B1LTEmTFjpQKF-nx^y|oJvZ$N^UQ_T^axT=EW?r)?dLjuH-DinLr@${6tpk^U5 z_QV5}=Np

ngy7Ai!iXsViAVTKNkifE8+3L^8W8St=6m^f!T>4qA62r?gc@x01+a z+EZ8@B3a4}Ypo9M_5>p7#7xmn7}EI2!D+LZe5ISR(=u}sy0pMt1=VgD z+0<=J8B*U6_z{A*m0>eQuM7Eh>Fq_8rmwi>9d8n$Si-aKf)X^q1+ z_XrxeqnaGP1X%au`o0oA4Sv;0~m>RQ;9g9uwEPRY|*kZEk$JLn?__5ga zR~YqdOF$U}h9(A`-NjG>B-KDAvx_NNFQ$)C^eNF}x~GQ_0CF_-Dy^Ty;B~cQ4+6_k z6Gt_%-V6e`RzY=(S)Wn3Z0dm;BCW!uC18BmTvWs%G&UO~hS$)6YjY$d)V|RDlg~(a z_n#_c3nirEznHAimJm{iPb`G6)+>t-EHI*GkAO;uXfC4oL`}girGWEEtaLKDB39D& zBwkU6j3(ZQBpgplh?yq3U>Z}-WT}+w$=F>Xa9S*2X`8%N}?uQQQc{{;W!0uau>Sh=~&Rsn(Oxf=p~ z9ZIVNz&Oi8&+1St5=Vvv^1q70NmvIcNgZn=?l0!?=P6qv%O2Fu=91n#NPfh+5 zqZj`wPh!bs0BPlb#eH}(U&y2fr$Twjb0naM9~e|x;GhvcsAxSm5^7&OtAx2eJh?sy zAie&{1>nJA*w84L_KMwJ=mCKEfu!W7h^#RYwURm8N|sV#vqL=^Q1nk=ktD;5p$~FM zFNZs*(@{f7E`JI4PR>g_XRGMta(0hPfBJd5LXH8nqgv)%U~;!9SuX-bRsdM&Ij5Y98*bGsUL^}apM5P{fz~Q+@T4{ zUN}4=nfSrF!wTAw$z~I!WWF=Z)~OQhe#xUAz2OPW4##)wgmT*M=n2aLBaY??Ge5lRyKrlJsR<%rD9>Q=3qOzf|&rd z>vGbb5CZ3m2}EBAgGLVp-p)oA5#0`38=^Mzszwspm5bWS^Y^vL)9rV;S89#onnwiM zR!36zH+mNM74gEhjrPowW%zYaq(rumN@58`4%u+Au{sOo47nW8(H8ti3_zq3@+VEB zL#jigrYsxuCwe}rkTM1~sEh^@ za*%cjFN{3_3+8fx8)dBpp*(!)WX`@&v?@9q5#Hk{e*AI=s6U7sTGX(i5V^)Z8cmE= zsX5OlBdt7cTL6Y?7)TqvE2z7Q8xaNtEnHoU$$Co88a$RH>&JZahK9NC`zu0E-`hrXwq;e;<}(c!HV1 zK;adwpXRl~_^HZBfn~a%h@rBCg__*{r{PNR3rm^W$qGoTlZDO7o4nd`<)ypn$q;5G z+cRAqe)bgaK^b(EEcoT6X`j)bu*x>(%~~sVf^x1(E_T-8UXTgv!+i1*-UtawrRrJ> z)aqSsztf5V&VTJab|b}0RLYqwyo)fMqlGAX!45moUg8HvLiq5+L(ZOW=sns_Q%h4+ zhr_Ad)Ran0vF${zkjGim5C*`dh=b(rZkVHFXmo|DHu78@SDYcM(pvA{KrW`B}uMMt6B zF|H0RSGp0vGuhtbaxAKht@mQ1L9*-(kHxdk`YeI<(8YlT%c|~l6S*^ks71PB-U1x) z1N@McL7#p|g37?{f4mg$^h46TLiDHf)Ty87(Ih`nZwRRPFtTTM;9-k7miuFJ4j}0+ zyy``QvtYI1Ej%xP)P){LM(8tf)ub87z&B6%!I^>+6;5j@E9?5iwDIAjQYJ<5 z8;hNs6Fe>Q7EZ>&c1TV)$#&e{)K<=<+f&&>B`tlcvM`-Vo_sm_4sDgvbi|;Xgvqp! zci?moM#b?WEM_JZN;nLJlPPrK3_c(@`_h@oTNb(3HR4kgDn!hwiAjhT|Bp(6okbo} zqGnk^K3DCC)3lw43h&G^_QVvVqggnqhf{F=@Qy;Ng43KhIAtJpR+8u| z{K?>9hrMPy*$#(Tcz{)(ucS=}VucvzShROsPvZy%aOE3JR+{B!nB!wltR2TPNufg& zB`T?x2Mtr@UI%)WBwhF_iqfVa7I6bpvWSDeRu3JJt%Cy+jW@B&LN$qbi0UyFd#*kM z()}GvPC`+IHoE-jfs294>hA;PFvg79wos+@HZ>Oz=Xbg7DGvQfNX}?Rg-SVLb#&ka zVV%|IN$ciYg{l~+17CJ1E~@;Fg;gw2m*ql<&zgiB&>y-mo?a631L?UGkR*X)?jo4| z^5BP)@8r!n5*21vZudanHqK3_l3_cKS}ZW5eW6I?dV>j$Jl?=2UJG8t!^qm=4&ctu zsO={&3i9#>aCT99cK#wtj`dOlr&gD9pZwgq@P(r`q}8qf{u;+D*-Wl$vWgD0}6lIv(q89L=Ivcg^&O^2iS(q;}w zs(m3f-B5!3$puZnC?JF%JsQDj*9*{AJv`7@kK|5~orOag-z*@!8C!>S&~|;MkjHW- zPhJgK_zehWCEVloS#k;q;9U|-bMC}{-cf^q}}vm0krtMC;9P`(hF4T`25B2`T) zK+wLxL$o8RE^H*%KdB7l%Zf@CYeM)Dz*8*M1xLF~B`0={K*3rN$LRSih9`MC%#|uQ z0XPUIK;KAT!3wY1n(+}L5}HwDlWE!tbAFNoN~9<~MM7fFH<}!(BkF>JAW0D$bmK?K zD?pT~h83WGAqRluF(!4P$I!?f(W*N>03&(=TYYUr@0=HVd%7g-3G zaG*=ya1TyYUlnw3iH}i?t;0kes#{J(5op76+>jAsYzsRw6_gOUC=~b+I+=u)*MIK{ zK*)cXT(EF21{6hhuKEov#AS`3awC@@3(y!Stj@E+GwO04aNCR>7B<;=-9a*!AV(vh533T|ph#?)=|HbwjvaM|IVHnFLuf zWCv9TSGr-sWlRr@RaTyCRV{yA{9tnYoV1y%HxG>v3*A||xTsD*EHo;1?Ms#V>(aEm zsKGPX*K9>ARHf!di84#SFI>%4NS3j9P`6m&*r#7XvDPR|@&}R(N�-Q8?YOrpK>& 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 LdY~G9q5u9L+SwW1 delta 37046 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 Utgo^qE<`6&f6KZ~IySoh50ccMfB*mh diff --git a/src/app/[locale]/(default)/storage/page.tsx b/src/app/[locale]/(default)/storage/page.tsx index 37150b4..65f8230 100644 --- a/src/app/[locale]/(default)/storage/page.tsx +++ b/src/app/[locale]/(default)/storage/page.tsx @@ -16,9 +16,9 @@ import { } from '@/components/ui/Tooltip'; import { ShoppingCart } from 'lucide-react'; -import { Link } from '@/lib/locale/navigation'; import { CategorySelector } from '@/components/storage/CategorySelector'; import { SortSelector } from '@/components/storage/SortSelector'; +import { Link } from '@/lib/locale/navigation'; export async function generateMetadata({ params: { locale }, diff --git a/src/components/ui/Form.tsx b/src/components/ui/Form.tsx index e4c37de..c945d9f 100644 --- a/src/components/ui/Form.tsx +++ b/src/components/ui/Form.tsx @@ -136,7 +136,7 @@ const FormDescription = React.forwardRef<

); @@ -158,7 +158,7 @@ const FormMessage = React.forwardRef<

{body} diff --git a/src/components/ui/Label.tsx b/src/components/ui/Label.tsx index 0fe725c..cc8890c 100644 --- a/src/components/ui/Label.tsx +++ b/src/components/ui/Label.tsx @@ -7,7 +7,7 @@ import * as React from 'react'; import { cx } from '@/lib/utils'; const labelVariants = cva({ - base: 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', + base: 'font-medium text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', }); const Label = React.forwardRef< From 849926e9848a81b668596fb779b0f45ce04215ff Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Thu, 19 Sep 2024 19:27:34 +0200 Subject: [PATCH 23/79] refactor: Newline after use client, remove unused dependencies --- src/components/home/HelloWorld.tsx | 1 + src/components/storage/CategorySelector.tsx | 4 ++-- src/components/storage/ShoppingCartClearButton.tsx | 1 + src/components/storage/SortSelector.tsx | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/home/HelloWorld.tsx b/src/components/home/HelloWorld.tsx index 4be51a8..3506c1e 100644 --- a/src/components/home/HelloWorld.tsx +++ b/src/components/home/HelloWorld.tsx @@ -1,4 +1,5 @@ 'use client'; + import { api } from '@/lib/api/client'; function HelloWorld() { diff --git a/src/components/storage/CategorySelector.tsx b/src/components/storage/CategorySelector.tsx index a14f989..0a815e6 100644 --- a/src/components/storage/CategorySelector.tsx +++ b/src/components/storage/CategorySelector.tsx @@ -1,7 +1,7 @@ 'use client'; -import { useTranslations } from 'next-intl'; + import { useQueryState } from 'nuqs'; -import { createSearchParamsCache, parseAsString } from 'nuqs/parsers'; +import { parseAsString } from 'nuqs/parsers'; import { Combobox } from '../ui/Combobox'; type CategorySelectorProps = { diff --git a/src/components/storage/ShoppingCartClearButton.tsx b/src/components/storage/ShoppingCartClearButton.tsx index aa78e3c..7897ef0 100644 --- a/src/components/storage/ShoppingCartClearButton.tsx +++ b/src/components/storage/ShoppingCartClearButton.tsx @@ -1,4 +1,5 @@ 'use client'; + import { Button } from '@/components/ui/Button'; import { X } from 'lucide-react'; import { useLocalStorage } from 'usehooks-ts'; diff --git a/src/components/storage/SortSelector.tsx b/src/components/storage/SortSelector.tsx index c58108f..4780f70 100644 --- a/src/components/storage/SortSelector.tsx +++ b/src/components/storage/SortSelector.tsx @@ -1,4 +1,5 @@ 'use client'; + import { Select, SelectContent, From 16253053ff9be831733c922906cd3c04efa9b441 Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Thu, 19 Sep 2024 19:39:16 +0200 Subject: [PATCH 24/79] refactor: Append Icon to lucide icon names, fix typos --- messages/en.json | 2 +- messages/no.json | 2 +- src/app/[locale]/(default)/storage/page.tsx | 4 ++-- src/app/[locale]/(default)/storage/shopping-cart/page.tsx | 4 ++-- src/components/storage/LoanForm.tsx | 4 ++-- src/components/storage/ShoppingCartClearButton.tsx | 4 ++-- src/components/storage/ShoppingCartTable.tsx | 4 ++-- src/components/ui/Calendar.tsx | 6 +++--- src/components/ui/DatePicker.tsx | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/messages/en.json b/messages/en.json index 85626d8..48d8d51 100644 --- a/messages/en.json +++ b/messages/en.json @@ -80,7 +80,7 @@ }, "shoppingCart": { "title": "Shopping Cart", - "productId": "Product id", + "productId": "Product ID", "productName": "Product Name", "location": "Location", "unitsAvailable": "Units available", diff --git a/messages/no.json b/messages/no.json index ad21291..d204381 100644 --- a/messages/no.json +++ b/messages/no.json @@ -80,7 +80,7 @@ }, "shoppingCart": { "title": "Handlekurv", - "productId": "Produkt id", + "productId": "Produkt-ID", "productName": "Produktnavn", "location": "Plass", "unitsAvailable": "Stk tilgjengelig", diff --git a/src/app/[locale]/(default)/storage/page.tsx b/src/app/[locale]/(default)/storage/page.tsx index 65f8230..13ffad6 100644 --- a/src/app/[locale]/(default)/storage/page.tsx +++ b/src/app/[locale]/(default)/storage/page.tsx @@ -14,7 +14,7 @@ import { TooltipProvider, TooltipTrigger, } from '@/components/ui/Tooltip'; -import { ShoppingCart } from 'lucide-react'; +import { ShoppingCartIcon } from 'lucide-react'; import { CategorySelector } from '@/components/storage/CategorySelector'; import { SortSelector } from '@/components/storage/SortSelector'; @@ -87,7 +87,7 @@ export default function StoragePage({ diff --git a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx index 2ce4338..439369d 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx @@ -3,7 +3,7 @@ import { ShoppingCartClearButton } from '@/components/storage/ShoppingCartClearB import { ShoppingCartTable } from '@/components/storage/ShoppingCartTable'; import { Button } from '@/components/ui/Button'; import { Link } from '@/lib/locale/navigation'; -import { ArrowLeft } from 'lucide-react'; +import { ArrowLeftIcon } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { unstable_setRequestLocale } from 'next-intl/server'; @@ -45,7 +45,7 @@ export default function StorageShoppingCartPage({

diff --git a/src/components/storage/LoanForm.tsx b/src/components/storage/LoanForm.tsx index c1f34ee..04076f0 100644 --- a/src/components/storage/LoanForm.tsx +++ b/src/components/storage/LoanForm.tsx @@ -23,7 +23,7 @@ const formSchema = z.object({ returnBy: z.date().min(new Date()), }); -type LoanFormParams = { +type LoanFormProps = { t: { borrowNow: string; name: string; @@ -38,7 +38,7 @@ type LoanFormParams = { }; }; -function LoanForm({ t }: LoanFormParams) { +function LoanForm({ t }: LoanFormProps) { const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { diff --git a/src/components/storage/ShoppingCartClearButton.tsx b/src/components/storage/ShoppingCartClearButton.tsx index 7897ef0..119656b 100644 --- a/src/components/storage/ShoppingCartClearButton.tsx +++ b/src/components/storage/ShoppingCartClearButton.tsx @@ -1,7 +1,7 @@ 'use client'; import { Button } from '@/components/ui/Button'; -import { X } from 'lucide-react'; +import { XIcon } from 'lucide-react'; import { useLocalStorage } from 'usehooks-ts'; function ShoppingCartClearButton({ caption }: { caption: string }) { @@ -21,7 +21,7 @@ function ShoppingCartClearButton({ caption }: { caption: string }) { variant='destructive' onClick={() => clearCart()} > - + {caption} ); diff --git a/src/components/storage/ShoppingCartTable.tsx b/src/components/storage/ShoppingCartTable.tsx index 8ee1ff1..d702f6f 100644 --- a/src/components/storage/ShoppingCartTable.tsx +++ b/src/components/storage/ShoppingCartTable.tsx @@ -11,7 +11,7 @@ import { TableHeader, TableRow, } from '@/components/ui/Table'; -import { X } from 'lucide-react'; +import { XIcon } from 'lucide-react'; import { useLocalStorage } from 'usehooks-ts'; // TODO: Must be replaced by requesting the data from a database. @@ -74,7 +74,7 @@ function ShoppingCartTable({ messages }: ShoppingCartTableProps) { className='h-8 p-1' onClick={() => removeItem(item.id)} > - + diff --git a/src/components/ui/Calendar.tsx b/src/components/ui/Calendar.tsx index 3f41547..905dbbc 100644 --- a/src/components/ui/Calendar.tsx +++ b/src/components/ui/Calendar.tsx @@ -1,6 +1,6 @@ 'use client'; -import { ChevronLeft, ChevronRight } from 'lucide-react'; +import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'; import type * as React from 'react'; import { DayPicker } from 'react-day-picker'; @@ -55,8 +55,8 @@ function Calendar({ ...classNames, }} components={{ - IconLeft: ({ ...props }) => , - IconRight: ({ ...props }) => , + IconLeft: ({ ...props }) => , + IconRight: ({ ...props }) => , }} weekStartsOn={1} {...props} diff --git a/src/components/ui/DatePicker.tsx b/src/components/ui/DatePicker.tsx index 118c552..c46a279 100644 --- a/src/components/ui/DatePicker.tsx +++ b/src/components/ui/DatePicker.tsx @@ -1,7 +1,7 @@ 'use client'; import { format } from 'date-fns'; -import { Calendar as CalendarIcon } from 'lucide-react'; +import { CalendarIcon } from 'lucide-react'; import * as React from 'react'; import { Button } from '@/components/ui/Button'; From 4d8e003e2471cde24650122be3d9ebef89001941 Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Thu, 19 Sep 2024 19:42:34 +0200 Subject: [PATCH 25/79] fix: Dynamic alt text for ItemCards --- messages/en.json | 3 ++- messages/no.json | 3 ++- src/components/storage/ItemCard.tsx | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/messages/en.json b/messages/en.json index 48d8d51..33888d7 100644 --- a/messages/en.json +++ b/messages/en.json @@ -11,7 +11,8 @@ "morePages": "More pages", "page": "page", "category": "category", - "sort": "sort" + "sort": "sort", + "photoOf": "Photo of {name}" }, "layout": { "hackerspaceHome": "Hackerspace homepage", diff --git a/messages/no.json b/messages/no.json index d204381..7e18ade 100644 --- a/messages/no.json +++ b/messages/no.json @@ -11,7 +11,8 @@ "morePages": "Flere sider", "page": "side", "category": "kategori", - "sort": "sortering" + "sort": "sortering", + "photoOf": "Bilde av {name}" }, "layout": { "hackerspaceHome": "Hackerspace hjemmeside", diff --git a/src/components/storage/ItemCard.tsx b/src/components/storage/ItemCard.tsx index 451b89e..de994d4 100644 --- a/src/components/storage/ItemCard.tsx +++ b/src/components/storage/ItemCard.tsx @@ -8,6 +8,7 @@ import { CardHeader, CardTitle, } from '@/components/ui/Card'; +import { useTranslations } from 'next-intl'; import Image from 'next/image'; type ItemCardProps = { @@ -23,6 +24,7 @@ function ItemCard({ removeFromCart, quantityInfo, }: ItemCardProps) { + const t = useTranslations('ui'); return (
From 9c64980a3543e59b4728909a0a8142f2f2c73570 Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Thu, 19 Sep 2024 20:01:40 +0200 Subject: [PATCH 26/79] refactor: Reduce repeated code, show message if shopping cart is empty --- src/components/storage/ShoppingCartClearButton.tsx | 3 +-- src/components/storage/ShoppingCartTable.tsx | 6 ++---- .../storage/ShoppingCartTableSkeleton.tsx | 13 +++++++------ 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/components/storage/ShoppingCartClearButton.tsx b/src/components/storage/ShoppingCartClearButton.tsx index 119656b..baa1141 100644 --- a/src/components/storage/ShoppingCartClearButton.tsx +++ b/src/components/storage/ShoppingCartClearButton.tsx @@ -13,12 +13,11 @@ function ShoppingCartClearButton({ caption }: { caption: string }) { setCart([]); } - if (cart.length <= 0) return; - return ( diff --git a/src/components/storage/ItemCard.tsx b/src/components/storage/ItemCard.tsx index 0698835..f2d4ecb 100644 --- a/src/components/storage/ItemCard.tsx +++ b/src/components/storage/ItemCard.tsx @@ -38,9 +38,12 @@ function ItemCard({ height={192} alt={t('photoOf', { name: item.name })} className='rounded-md duration-200 group-hover:scale-105' + priority={true} /> - {item.name} + + {item.name} + {item.location} From 234eadf3a72d05722353a630f55d043095a966e8 Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Thu, 26 Sep 2024 00:25:14 +0200 Subject: [PATCH 51/79] feat: Select how many items you would like to loan, fix skeletons --- messages/en.json | 3 +- messages/no.json | 3 +- .../(default)/storage/(main)/loading.tsx | 10 ++-- .../(default)/storage/shopping-cart/page.tsx | 3 +- src/components/storage/LoanForm.tsx | 6 +++ src/components/storage/ShoppingCartTable.tsx | 52 +++++++++++++++---- 6 files changed, 56 insertions(+), 21 deletions(-) diff --git a/messages/en.json b/messages/en.json index 57fcbf9..1826791 100644 --- a/messages/en.json +++ b/messages/en.json @@ -99,7 +99,8 @@ "tableDescription": "A list of your shopping cart items.", "backToStorage": "Back to storage", "cartEmpty": "Your shopping cart is empty.", - "clearCart": "Empty shopping cart" + "clearCart": "Empty shopping cart", + "amountOfItemARIA": "Select number of this item" }, "loanForm": { "borrowNow": "Borrow now", diff --git a/messages/no.json b/messages/no.json index e1644e1..a48bfc8 100644 --- a/messages/no.json +++ b/messages/no.json @@ -99,7 +99,8 @@ "tableDescription": "En liste over handlekurven din.", "backToStorage": "Tilbake til lageret", "cartEmpty": "Handlekurven din er tom.", - "clearCart": "Tøm handlekurven" + "clearCart": "Tøm handlekurven", + "amountOfItemARIA": "Velg antallet av denne gjenstanden" }, "loanForm": { "borrowNow": "Lån nå", diff --git a/src/app/[locale]/(default)/storage/(main)/loading.tsx b/src/app/[locale]/(default)/storage/(main)/loading.tsx index f88b271..e2de77b 100644 --- a/src/app/[locale]/(default)/storage/(main)/loading.tsx +++ b/src/app/[locale]/(default)/storage/(main)/loading.tsx @@ -1,15 +1,10 @@ +import { PaginationCarouselSkeleton } from '@/components/composites/PaginationCarouselSkeleton'; import { SkeletonCard } from '@/components/storage/SkeletonCard'; -import { Skeleton } from '@/components/ui/Skeleton'; export default function StorageSkeleton() { return ( <> -
- - - -
-
+
@@ -19,6 +14,7 @@ export default function StorageSkeleton() {
+ ); } diff --git a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx index 439369d..60d1565 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx @@ -23,6 +23,7 @@ export default function StorageShoppingCartPage({ location: t('location'), unitsAvailable: t('unitsAvailable'), cartEmpty: t('cartEmpty'), + amountOfItemARIA: t('amountOfItemARIA'), }; const loanFormMessages = { @@ -41,7 +42,7 @@ export default function StorageShoppingCartPage({ return ( <>

{t('title')}

- +
diff --git a/src/components/storage/ShoppingCartClearButton.tsx b/src/components/storage/ShoppingCartClearButton.tsx index 2f055e2..6a0aebb 100644 --- a/src/components/storage/ShoppingCartClearButton.tsx +++ b/src/components/storage/ShoppingCartClearButton.tsx @@ -11,12 +11,14 @@ function ShoppingCartClearButton({ }: { caption: string; className?: string }) { const [cart, setCart, isLoading] = useLocalStorage('shopping-cart'); + if (!cart) return; + return ( - + {t.borrowNow} diff --git a/src/components/storage/LoanForm.tsx b/src/components/storage/LoanForm.tsx index 11208bb..fd89335 100644 --- a/src/components/storage/LoanForm.tsx +++ b/src/components/storage/LoanForm.tsx @@ -1,7 +1,7 @@ 'use client'; import { Button } from '@/components/ui/Button'; -import { DatePicker } from '@/components/ui/DatePicker'; +import { Calendar } from '@/components/ui/Calendar'; import { Form, FormControl, @@ -13,12 +13,11 @@ import { } from '@/components/ui/Form'; import { Input } from '@/components/ui/Input'; import { zodResolver } from '@hookform/resolvers/zod'; +import { addDays, addWeeks, endOfWeek } from 'date-fns'; import { useForm } from 'react-hook-form'; import { z } from 'zod'; const formSchema = z.object({ - name: z.string().min(1), - email: z.string().email(), phone: z.string().min(1), returnBy: z.date().min(new Date()), }); @@ -27,9 +26,7 @@ type LoanFormProps = { t: { borrowNow: string; name: string; - nameDescription: string; email: string; - emailExample: string; phoneNumber: string; phoneNumberDescription: string; returnBy: string; @@ -42,8 +39,6 @@ function LoanForm({ t }: LoanFormProps) { const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { - name: '', - email: '', phone: '', returnBy: new Date(), }, @@ -57,70 +52,44 @@ function LoanForm({ t }: LoanFormProps) { return ( <> - -
- ( - - {t.name} - - - - {t.nameDescription} - - - )} - /> - ( - - {t.email} - - - - - - )} - /> - ( - - {t.phoneNumber} - - - - {t.phoneNumberDescription} - - - )} - /> -
-
- ( - - {t.returnBy} - - - - {t.returnByDescription} - - - )} - /> -
+ + ( + + {t.phoneNumber} + + + + {t.phoneNumberDescription} + + + )} + /> + ( + + {t.returnBy} + + + + {t.returnByDescription} + + + )} + /> From 19ff5de8fc4d495787dd0b0ea5f7b1d119439bc7 Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Fri, 27 Sep 2024 19:31:10 +0200 Subject: [PATCH 68/79] fix: change to use object for localstorage --- .../(default)/storage/shopping-cart/page.tsx | 2 - src/components/storage/AddToCartButton.tsx | 49 ++++++++++--------- src/components/storage/BorrowDialog.tsx | 5 +- src/components/storage/LoanForm.tsx | 1 + .../storage/ShoppingCartClearButton.tsx | 6 ++- src/components/storage/ShoppingCartTable.tsx | 36 +++++++------- .../storage/ShoppingCartTableSkeleton.tsx | 3 +- 7 files changed, 53 insertions(+), 49 deletions(-) diff --git a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx index 0bb7243..e658120 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx @@ -26,9 +26,7 @@ export default function StorageShoppingCartPage({ const borrowNowMessages = { borrowNow: t('borrowNow'), name: tLoanForm('name'), - nameDescription: tLoanForm('nameDescription'), email: tLoanForm('email'), - emailExample: tLoanForm('emailExample'), phoneNumber: tLoanForm('phoneNumber'), phoneNumberDescription: tLoanForm('phoneNumberDescription'), returnBy: tLoanForm('returnBy'), diff --git a/src/components/storage/AddToCartButton.tsx b/src/components/storage/AddToCartButton.tsx index aac0215..0f1b33d 100644 --- a/src/components/storage/AddToCartButton.tsx +++ b/src/components/storage/AddToCartButton.tsx @@ -4,7 +4,6 @@ import { Button } from '@/components/ui/Button'; import { Loader } from '@/components/ui/Loader'; import { useLocalStorage } from '@/lib/hooks/useLocalStorage'; import { cx } from 'cva'; -import { useEffect, useState } from 'react'; // TODO: Type must be replaced by the type provided from database ORM. export type StorageItem = { @@ -16,6 +15,11 @@ export type StorageItem = { location: string; }; +export type CartItem = { + id: number; + amount: number; +}; + type AddToCartButtonProps = { className?: string; item: StorageItem; @@ -26,43 +30,42 @@ type AddToCartButtonProps = { }; function AddToCartButton({ className, item, t }: AddToCartButtonProps) { - const [cart, setCart, loading] = useLocalStorage( + const [cart, setCart, loading] = useLocalStorage( 'shopping-cart', [], ); - const [isInCart, setIsInCart] = useState(false); - - useEffect(() => { - setIsInCart(cart.some((i) => i === item.id)); - }, [cart, item.id]); if (loading) { return ; } - const updateState = (addToCart: boolean) => { - if (addToCart) { - setCart((prevCart) => { - const newCart = [...prevCart, item.id]; - console.log(newCart); - return newCart; - }); + function updateCart() { + if (!cart) return; + + const isInCart = cart.some((cartItem) => cartItem.id === item.id); + + if (isInCart) { + const newCart = cart.filter((cartItem) => cartItem.id !== item.id); + setCart(newCart); } else { - setCart((prevCart) => { - const newCart = prevCart.filter((i) => i !== item.id); - console.log(newCart); - return newCart; - }); + const newCart = [...cart, { id: item.id, amount: 1 }]; + setCart(newCart); } - }; + } return ( ); } diff --git a/src/components/storage/BorrowDialog.tsx b/src/components/storage/BorrowDialog.tsx index 4c99642..f00ebfc 100644 --- a/src/components/storage/BorrowDialog.tsx +++ b/src/components/storage/BorrowDialog.tsx @@ -1,5 +1,6 @@ 'use client'; +import type { CartItem } from '@/components/storage/AddToCartButton'; import { LoanForm } from '@/components/storage/LoanForm'; import { Button } from '@/components/ui/Button'; import { @@ -15,9 +16,7 @@ type BorrowNowDialogProps = { t: { borrowNow: string; name: string; - nameDescription: string; email: string; - emailExample: string; phoneNumber: string; phoneNumberDescription: string; returnBy: string; @@ -28,7 +27,7 @@ type BorrowNowDialogProps = { }; function BorrowDialog({ t, className }: BorrowNowDialogProps) { - const [cart, _, isLoading] = useLocalStorage('shopping-cart'); + const [cart, _, isLoading] = useLocalStorage('shopping-cart'); if (!cart) return; diff --git a/src/components/storage/LoanForm.tsx b/src/components/storage/LoanForm.tsx index fd89335..cbdad93 100644 --- a/src/components/storage/LoanForm.tsx +++ b/src/components/storage/LoanForm.tsx @@ -79,6 +79,7 @@ function LoanForm({ t }: LoanFormProps) { mode='single' selected={field.value} onSelect={field.onChange} + showOutsideDays={false} disabled={{ before: new Date(), after: addDays(endOfWeek(addWeeks(new Date(), 2)), 2), diff --git a/src/components/storage/ShoppingCartClearButton.tsx b/src/components/storage/ShoppingCartClearButton.tsx index 6a0aebb..310355e 100644 --- a/src/components/storage/ShoppingCartClearButton.tsx +++ b/src/components/storage/ShoppingCartClearButton.tsx @@ -1,5 +1,6 @@ 'use client'; +import type { CartItem } from '@/components/storage/AddToCartButton'; import { Button } from '@/components/ui/Button'; import { useLocalStorage } from '@/lib/hooks/useLocalStorage'; import { cx } from '@/lib/utils'; @@ -9,7 +10,8 @@ function ShoppingCartClearButton({ caption, className, }: { caption: string; className?: string }) { - const [cart, setCart, isLoading] = useLocalStorage('shopping-cart'); + const [cart, setCart, isLoading] = + useLocalStorage('shopping-cart'); if (!cart) return; @@ -17,7 +19,7 @@ function ShoppingCartClearButton({ diff --git a/src/components/storage/ShoppingCartClearButton.tsx b/src/components/storage/ShoppingCartClearButton.tsx index 310355e..edf3092 100644 --- a/src/components/storage/ShoppingCartClearButton.tsx +++ b/src/components/storage/ShoppingCartClearButton.tsx @@ -13,11 +13,9 @@ function ShoppingCartClearButton({ const [cart, setCart, isLoading] = useLocalStorage('shopping-cart'); - if (!cart) return; - return ( ); } diff --git a/src/components/storage/ShoppingCartTable.tsx b/src/components/storage/ShoppingCartTable.tsx index 1c12bc7..703105c 100644 --- a/src/components/storage/ShoppingCartTable.tsx +++ b/src/components/storage/ShoppingCartTable.tsx @@ -40,7 +40,7 @@ function ShoppingCartTable({ t }: ShoppingCartTableProps) { return ; } - if (!cart) { + if (!cart || cart.length === 0) { return

{t.cartEmpty}

; } From 7760b654b442d0a99a7cbccfc893e725d0dbfd1e Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Fri, 27 Sep 2024 20:23:57 +0200 Subject: [PATCH 71/79] feat: add amount indicator to shopping cart --- messages/en.json | 1 - messages/no.json | 1 - .../(default)/storage/(main)/layout.tsx | 37 ++----------- src/components/composites/SortSelector.tsx | 6 +- src/components/storage/BorrowDialog.tsx | 2 +- src/components/storage/ShoppingCartLink.tsx | 55 +++++++++++++++++++ 6 files changed, 65 insertions(+), 37 deletions(-) create mode 100644 src/components/storage/ShoppingCartLink.tsx diff --git a/messages/en.json b/messages/en.json index 246723c..429b278 100644 --- a/messages/en.json +++ b/messages/en.json @@ -72,7 +72,6 @@ "select": { "ariaLabel": "Select how to filter the storage items", "filters": "Filters", - "defaultPlaceholder": "Sort results", "popularity": "Popularity", "sortDescending": "Inventory (descending)", "sortAscending": "Inventory (ascending)", diff --git a/messages/no.json b/messages/no.json index 02564ba..7ee62fd 100644 --- a/messages/no.json +++ b/messages/no.json @@ -72,7 +72,6 @@ "select": { "ariaLabel": "Velg hvordan du vil filtrere lager varene", "filters": "Filtre", - "defaultPlaceholder": "Sorter resultater", "popularity": "Popularitet", "sortDescending": "Lagerbeholdning (synkende)", "sortAscending": "Lagerbeholdning (stigende)", diff --git a/src/app/[locale]/(default)/storage/(main)/layout.tsx b/src/app/[locale]/(default)/storage/(main)/layout.tsx index eb5c6da..7862f07 100644 --- a/src/app/[locale]/(default)/storage/(main)/layout.tsx +++ b/src/app/[locale]/(default)/storage/(main)/layout.tsx @@ -1,17 +1,8 @@ -import { Link } from '@/lib/locale/navigation'; -import { ShoppingCartIcon } from 'lucide-react'; -import { useTranslations } from 'next-intl'; - import { CategorySelector } from '@/components/composites/CategorySelector'; import { SearchBar } from '@/components/composites/SearchBar'; import { SortSelector } from '@/components/composites/SortSelector'; -import { Button } from '@/components/ui/Button'; -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from '@/components/ui/Tooltip'; +import { ShoppingCartLink } from '@/components/storage/ShoppingCartLink'; +import { useTranslations } from 'next-intl'; import { unstable_setRequestLocale } from 'next-intl/server'; type StorageLayoutProps = { @@ -58,25 +49,9 @@ export default function StorageLayout({ <>

{t('title')}

- - - -
- -
-
- -

{t('tooltips.viewShoppingCart')}

-
-
-
+
diff --git a/src/components/composites/SortSelector.tsx b/src/components/composites/SortSelector.tsx index 6d3010c..2adc1db 100644 --- a/src/components/composites/SortSelector.tsx +++ b/src/components/composites/SortSelector.tsx @@ -16,7 +16,7 @@ type SortSelectorProps = { }[]; t: { sort: string; - defaultPlaceholder: string; + defaultValue: string; defaultSorting: string; ariaLabel: string; }; @@ -39,11 +39,11 @@ function SortSelector({ filters, t }: SortSelectorProps) { } }} defaultValue={ - filters.find((f) => f.urlName === filter)?.name ?? undefined + filters.find((f) => f.urlName === filter)?.name ?? t.defaultValue } > - + {filters.map((filter) => ( diff --git a/src/components/storage/BorrowDialog.tsx b/src/components/storage/BorrowDialog.tsx index e79efe8..920bec8 100644 --- a/src/components/storage/BorrowDialog.tsx +++ b/src/components/storage/BorrowDialog.tsx @@ -35,7 +35,7 @@ function BorrowDialog({ t, className }: BorrowNowDialogProps) { + {!isLoading && cart && cart.length > 0 && ( + + {cart.length} + + )} +
+ + +

{t.viewShoppingCart}

+
+ + + ); +} + +export { ShoppingCartLink }; From 97c51960066938016b33061230a28fc821b0a9fa Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Fri, 27 Sep 2024 21:08:49 +0200 Subject: [PATCH 72/79] fix: responsive design --- messages/en.json | 3 ++ messages/no.json | 3 ++ .../storage/shopping-cart/layout.tsx | 5 +- .../(default)/storage/shopping-cart/page.tsx | 16 +++--- src/components/composites/ConfirmDialog.tsx | 54 +++++++++++++++++++ src/components/storage/LoanForm.tsx | 2 +- .../storage/ShoppingCartClearButton.tsx | 29 ---------- .../storage/ShoppingCartClearDialog.tsx | 45 ++++++++++++++++ 8 files changed, 119 insertions(+), 38 deletions(-) create mode 100644 src/components/composites/ConfirmDialog.tsx delete mode 100644 src/components/storage/ShoppingCartClearButton.tsx create mode 100644 src/components/storage/ShoppingCartClearDialog.tsx diff --git a/messages/en.json b/messages/en.json index 429b278..5c0c922 100644 --- a/messages/en.json +++ b/messages/en.json @@ -108,6 +108,9 @@ "backToStorage": "Back to storage", "cartEmpty": "Your shopping cart is empty.", "clearCart": "Empty shopping cart", + "cancel": "Cancel", + "clear": "Clear", + "clearCartDescription": "Are you sure you want to clear your shopping cart? All items will be removed.", "borrowNow": "Borrow now", "amountOfItemARIA": "Select number of this item" }, diff --git a/messages/no.json b/messages/no.json index 7ee62fd..d3a1faf 100644 --- a/messages/no.json +++ b/messages/no.json @@ -108,6 +108,9 @@ "backToStorage": "Tilbake til lageret", "cartEmpty": "Handlekurven din er tom.", "clearCart": "Tøm handlekurven", + "cancel": "Avbryt", + "clear": "Tøm", + "clearCartDescription": "Er du sikker på at du vil tømme handlekurven? Alle varer vil bli slettet.", "borrowNow": "Lån nå", "amountOfItemARIA": "Velg antallet av denne gjenstanden" }, diff --git a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx index cbce318..fcfe2a0 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx @@ -18,14 +18,15 @@ export default function StorageLayout({ return ( <>
-

{t('title')}

+

{t('title')}

diff --git a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx index 5f3c4ef..06e9184 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx @@ -1,5 +1,5 @@ import { BorrowDialog } from '@/components/storage/BorrowDialog'; -import { ShoppingCartClearButton } from '@/components/storage/ShoppingCartClearButton'; +import { ShoppingCartClearDialog } from '@/components/storage/ShoppingCartClearDialog'; import { ShoppingCartTable } from '@/components/storage/ShoppingCartTable'; import { useTranslations } from 'next-intl'; import { unstable_setRequestLocale } from 'next-intl/server'; @@ -37,11 +37,15 @@ export default function StorageShoppingCartPage({ return ( <> -
- - + +
diff --git a/src/components/composites/ConfirmDialog.tsx b/src/components/composites/ConfirmDialog.tsx new file mode 100644 index 0000000..d1b0658 --- /dev/null +++ b/src/components/composites/ConfirmDialog.tsx @@ -0,0 +1,54 @@ +'use client'; + +import { Button, type buttonVariants } from '@/components/ui/Button'; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from '@/components/ui/Dialog'; +import type { VariantProps } from '@/lib/utils'; + +type ConfirmDialogProps = { + t: { + title: string; + description: string; + cancel: string; + confirm: string; + }; + confirmAction: () => void; + disabled?: boolean; +} & React.HTMLAttributes & + VariantProps; + +function ConfirmDialog({ confirmAction, t, ...props }: ConfirmDialogProps) { + return ( + + + + + + +
+ + ); +} + +export { ConfirmDialog }; diff --git a/src/components/storage/LoanForm.tsx b/src/components/storage/LoanForm.tsx index cbdad93..81b26ac 100644 --- a/src/components/storage/LoanForm.tsx +++ b/src/components/storage/LoanForm.tsx @@ -52,7 +52,7 @@ function LoanForm({ t }: LoanFormProps) { return ( <> - + ('shopping-cart'); - - return ( - - ); -} - -export { ShoppingCartClearButton }; diff --git a/src/components/storage/ShoppingCartClearDialog.tsx b/src/components/storage/ShoppingCartClearDialog.tsx new file mode 100644 index 0000000..cd6721b --- /dev/null +++ b/src/components/storage/ShoppingCartClearDialog.tsx @@ -0,0 +1,45 @@ +'use client'; + +import { ConfirmDialog } from '@/components/composites/ConfirmDialog'; +import type { CartItem } from '@/components/storage/AddToCartButton'; +import { useLocalStorage } from '@/lib/hooks/useLocalStorage'; +import { cx } from '@/lib/utils'; +import { XIcon } from 'lucide-react'; + +type ShoppingCartClearDialogProps = { + className?: string; + t: { + clearCart: string; + clearCartDescription: string; + clear: string; + cancel: string; + }; +}; + +function ShoppingCartClearDialog({ + className, + t, +}: ShoppingCartClearDialogProps) { + const [cart, setCart, isLoading] = + useLocalStorage('shopping-cart'); + + return ( + setCart(null)} + t={{ + title: t.clearCart, + description: t.clearCartDescription, + confirm: t.clear, + cancel: t.cancel, + }} + > + + ); +} + +export { ShoppingCartClearDialog }; From e61223b83a359c2abf7888d5800a218044762119 Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Fri, 27 Sep 2024 22:01:15 +0200 Subject: [PATCH 73/79] fix: Add SelectorsSkeleton back, as nuqs uses search params and they need to be wrapped in Suspense --- messages/no.json | 2 +- .../(default)/storage/(main)/layout.tsx | 40 ++++++++++--------- src/components/storage/SelectorsSkeleton.tsx | 13 ++++++ 3 files changed, 36 insertions(+), 19 deletions(-) create mode 100644 src/components/storage/SelectorsSkeleton.tsx diff --git a/messages/no.json b/messages/no.json index d3a1faf..62a6fd0 100644 --- a/messages/no.json +++ b/messages/no.json @@ -70,7 +70,7 @@ "removeFromCart": "Fjern fra handlekurven" }, "select": { - "ariaLabel": "Velg hvordan du vil filtrere lager varene", + "ariaLabel": "Velg hvordan du vil filtrere varene i lageret", "filters": "Filtre", "popularity": "Popularitet", "sortDescending": "Lagerbeholdning (synkende)", diff --git a/src/app/[locale]/(default)/storage/(main)/layout.tsx b/src/app/[locale]/(default)/storage/(main)/layout.tsx index 7862f07..25b96b3 100644 --- a/src/app/[locale]/(default)/storage/(main)/layout.tsx +++ b/src/app/[locale]/(default)/storage/(main)/layout.tsx @@ -1,9 +1,11 @@ import { CategorySelector } from '@/components/composites/CategorySelector'; import { SearchBar } from '@/components/composites/SearchBar'; import { SortSelector } from '@/components/composites/SortSelector'; +import { SelectorsSkeleton } from '@/components/storage/SelectorsSkeleton'; import { ShoppingCartLink } from '@/components/storage/ShoppingCartLink'; import { useTranslations } from 'next-intl'; import { unstable_setRequestLocale } from 'next-intl/server'; +import { Suspense } from 'react'; type StorageLayoutProps = { children: React.ReactNode; @@ -58,24 +60,26 @@ export default function StorageLayout({ className='lg:max-w-2xl' placeholder={t('searchPlaceholder')} /> - - + }> + + +
{children} diff --git a/src/components/storage/SelectorsSkeleton.tsx b/src/components/storage/SelectorsSkeleton.tsx new file mode 100644 index 0000000..8bf78b1 --- /dev/null +++ b/src/components/storage/SelectorsSkeleton.tsx @@ -0,0 +1,13 @@ +import { Skeleton } from '@/components/ui/Skeleton'; +import { useId } from 'react'; + +function SelectorsSkeleton() { + return ( +
+ + +
+ ); +} + +export { SelectorsSkeleton }; From dfa81e565e415e24a4d3b2b39e726f042076040d Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Fri, 27 Sep 2024 22:11:48 +0200 Subject: [PATCH 74/79] feat: Auto-close ConfirmDialog on confirm --- src/components/composites/ConfirmDialog.tsx | 13 +++++++++++-- src/components/storage/BorrowDialog.tsx | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/components/composites/ConfirmDialog.tsx b/src/components/composites/ConfirmDialog.tsx index d1b0658..4a2c1b3 100644 --- a/src/components/composites/ConfirmDialog.tsx +++ b/src/components/composites/ConfirmDialog.tsx @@ -12,6 +12,7 @@ import { DialogTrigger, } from '@/components/ui/Dialog'; import type { VariantProps } from '@/lib/utils'; +import { useState } from 'react'; type ConfirmDialogProps = { t: { @@ -26,8 +27,10 @@ type ConfirmDialogProps = { VariantProps; function ConfirmDialog({ confirmAction, t, ...props }: ConfirmDialogProps) { + const [open, setOpen] = useState(false); + return ( - + - diff --git a/src/components/storage/BorrowDialog.tsx b/src/components/storage/BorrowDialog.tsx index 920bec8..bfffe11 100644 --- a/src/components/storage/BorrowDialog.tsx +++ b/src/components/storage/BorrowDialog.tsx @@ -13,7 +13,7 @@ import { import { useLocalStorage } from '@/lib/hooks/useLocalStorage'; import { cx } from '@/lib/utils'; -type BorrowNowDialogProps = { +type BorrowDialogProps = { t: { borrowNow: string; name: string; @@ -27,7 +27,7 @@ type BorrowNowDialogProps = { className?: string; }; -function BorrowDialog({ t, className }: BorrowNowDialogProps) { +function BorrowDialog({ t, className }: BorrowDialogProps) { const [cart, _, isLoading] = useLocalStorage('shopping-cart'); return ( From f81ed8ee599d51e3c4ef45ae7a8de968835e3351 Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Fri, 27 Sep 2024 22:18:11 +0200 Subject: [PATCH 75/79] fix: Make the Borrow Now button centered and responsive --- src/app/[locale]/(default)/storage/shopping-cart/page.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx index 06e9184..28f00f0 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx @@ -37,8 +37,8 @@ export default function StorageShoppingCartPage({ return ( <> -
- +
+
From d642455188dda16a823f4509cf8c5790e8affcca Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Fri, 27 Sep 2024 22:47:41 +0200 Subject: [PATCH 76/79] fix: Make header and skeleton look better on small screens --- .../[locale]/(default)/storage/shopping-cart/layout.tsx | 4 ++-- .../[locale]/(default)/storage/shopping-cart/loading.tsx | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx index fcfe2a0..d7cab7f 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx @@ -18,7 +18,7 @@ export default function StorageLayout({ return ( <>
-

{t('title')}

+

{t('title')}

diff --git a/src/app/[locale]/(default)/storage/shopping-cart/loading.tsx b/src/app/[locale]/(default)/storage/shopping-cart/loading.tsx index 3359810..3dca707 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/loading.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/loading.tsx @@ -1,5 +1,5 @@ import { ShoppingCartTableSkeleton } from '@/components/storage/ShoppingCartTableSkeleton'; -import { Loader } from '@/components/ui/Loader'; +import { Skeleton } from '@/components/ui/Skeleton'; import { useTranslations } from 'next-intl'; export default function ShoppingCartSkeleton() { @@ -14,8 +14,9 @@ export default function ShoppingCartSkeleton() { return ( <> -
- +
+ +
); From 516db444b267d54e1c8a4a147d3becdfcf581c23 Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Sat, 28 Sep 2024 12:46:39 +0200 Subject: [PATCH 77/79] fix: Reduce size of shopping cart title on small screens --- src/app/[locale]/(default)/storage/shopping-cart/layout.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx index d7cab7f..8235cb2 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx @@ -18,7 +18,9 @@ export default function StorageLayout({ return ( <>
-

{t('title')}

+

+ {t('title')} +