add filter and cleat btn

This commit is contained in:
2025-06-01 09:33:08 +02:00
parent 3af1e72c06
commit d6fd6a225b
3 changed files with 625 additions and 13 deletions

View File

@@ -1,16 +1,31 @@
// import React from "react"
import {FlatList, Text, ActivityIndicator, RefreshControl} from "react-native";
import {useState, useEffect} from "react";
import { Ionicons } from "@expo/vector-icons";
import {useNoticesStore} from "@/store/noticesStore";
import {NoticeCard} from "@/components/NoticeCard";
import { useLocalSearchParams } from "expo-router";
import { HStack } from "@gluestack-ui/themed";
import { Button, ButtonText } from "@components/ui/Button";
import { Actionsheet } from "@components/ui/Actionsheet";
import { HStack } from "@/components/ui/hstack"
import { Box } from "@/components/ui/box"
import { Button, ButtonText, ButtonIcon } from "@/components/ui/button";
import {
Actionsheet,
ActionsheetContent,
ActionsheetItem,
ActionsheetItemText,
ActionsheetDragIndicator,
ActionsheetDragIndicatorWrapper,
ActionsheetBackdrop,
} from "@/components/ui/actionsheet"
import { useRouter } from "expo-router";
export default function Notices() {
const {notices, fetchNotices} = useNoticesStore();
const [refreshing, setRefreshing] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const [showActionsheet, setShowActionsheet] = useState(false)
const handleClose = () => setShowActionsheet(false)
const params = useLocalSearchParams();
console.log("GET params:", params);
@@ -18,6 +33,8 @@ export default function Notices() {
loadData();
}, []);
const loadData = async () => {
setIsLoading(true);
try {
@@ -30,8 +47,10 @@ export default function Notices() {
}
};
let filteredNotices = notices;
const router = useRouter();
let filteredNotices = notices;
let filterActive = false;
if (params.sort) {
if( params.sort === "latest") {
filteredNotices = [...filteredNotices].sort(
@@ -44,8 +63,13 @@ export default function Notices() {
filteredNotices = filteredNotices.filter(
(notice) => notice.category === params.category
);
filterActive = true;
}
if(params.attribute) {
filterActive = true;
}
const onRefresh = async () => {
setRefreshing(true);
try {
@@ -65,9 +89,29 @@ export default function Notices() {
return <Text>Nie udało sie pobrać listy. {error.message}</Text>;
}
return (
<>
<Box className="flex-row p-2 pt-4 pb-4 bg-white items-center justify-between">
<Button variant="outline" onPress={() => setShowActionsheet(true)}>
<ButtonText>Filtry</ButtonText>
<Ionicons name="filter-outline" size={20} color="black" />
</Button>
{filterActive && (
<Button variant="link" onPress={() => router.replace("/notices")}>
<ButtonText>Wyczyść</ButtonText>
</Button>)}
</Box>
<Actionsheet isOpen={showActionsheet} onClose={handleClose}>
<ActionsheetBackdrop />
<ActionsheetContent>
<ActionsheetDragIndicatorWrapper>
<ActionsheetDragIndicator />
</ActionsheetDragIndicatorWrapper>
<ActionsheetItem>
<ActionsheetItemText>Kategoria</ActionsheetItemText>
</ActionsheetItem>
</ActionsheetContent>
</Actionsheet>
<FlatList
key={2}
data={filteredNotices}
@@ -84,5 +128,6 @@ export default function Notices() {
/>
}
/>
</>
);
}

View File

@@ -0,0 +1,569 @@
'use client';
import React from 'react';
import { H4 } from '@expo/html-elements';
import { createActionsheet } from '@gluestack-ui/actionsheet';
import {
Pressable,
View,
Text,
ScrollView,
VirtualizedList,
FlatList,
SectionList,
PressableProps,
ViewStyle,
} from 'react-native';
import { PrimitiveIcon, UIIcon } from '@gluestack-ui/icon';
import { tva } from '@gluestack-ui/nativewind-utils/tva';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
import { cssInterop } from 'nativewind';
import {
Motion,
AnimatePresence,
createMotionAnimatedComponent,
MotionComponentProps,
} from '@legendapp/motion';
const ItemWrapper = React.forwardRef<
React.ComponentRef<typeof Pressable>,
PressableProps
>(function ItemWrapper({ ...props }, ref) {
return <Pressable {...props} ref={ref} />;
});
type IMotionViewProps = React.ComponentProps<typeof View> &
MotionComponentProps<typeof View, ViewStyle, unknown, unknown, unknown>;
const MotionView = Motion.View as React.ComponentType<IMotionViewProps>;
type IAnimatedPressableProps = React.ComponentProps<typeof Pressable> &
MotionComponentProps<typeof Pressable, ViewStyle, unknown, unknown, unknown>;
const AnimatedPressable = createMotionAnimatedComponent(
Pressable
) as React.ComponentType<IAnimatedPressableProps>;
export const UIActionsheet = createActionsheet({
Root: View,
Content: MotionView,
Item: ItemWrapper,
ItemText: Text,
DragIndicator: View,
IndicatorWrapper: View,
Backdrop: AnimatedPressable,
ScrollView: ScrollView,
VirtualizedList: VirtualizedList,
FlatList: FlatList,
SectionList: SectionList,
SectionHeaderText: H4,
Icon: UIIcon,
AnimatePresence: AnimatePresence,
});
cssInterop(UIActionsheet, { className: 'style' });
cssInterop(UIActionsheet.Content, { className: 'style' });
cssInterop(ItemWrapper, { className: 'style' });
cssInterop(UIActionsheet.ItemText, { className: 'style' });
cssInterop(UIActionsheet.DragIndicator, { className: 'style' });
cssInterop(UIActionsheet.DragIndicatorWrapper, { className: 'style' });
cssInterop(UIActionsheet.Backdrop, { className: 'style' });
cssInterop(UIActionsheet.ScrollView, {
className: 'style',
contentContainerClassName: 'contentContainerStyle',
indicatorClassName: 'indicatorStyle',
});
cssInterop(UIActionsheet.VirtualizedList, {
className: 'style',
ListFooterComponentClassName: 'ListFooterComponentStyle',
ListHeaderComponentClassName: 'ListHeaderComponentStyle',
contentContainerClassName: 'contentContainerStyle',
indicatorClassName: 'indicatorStyle',
});
cssInterop(UIActionsheet.FlatList, {
className: 'style',
ListFooterComponentClassName: 'ListFooterComponentStyle',
ListHeaderComponentClassName: 'ListHeaderComponentStyle',
columnWrapperClassName: 'columnWrapperStyle',
contentContainerClassName: 'contentContainerStyle',
indicatorClassName: 'indicatorStyle',
});
cssInterop(UIActionsheet.SectionList, { className: 'style' });
cssInterop(UIActionsheet.SectionHeaderText, { className: 'style' });
cssInterop(PrimitiveIcon, {
className: {
target: 'style',
nativeStyleToProp: {
height: true,
width: true,
fill: true,
color: 'classNameColor',
stroke: true,
},
},
});
const actionsheetStyle = tva({ base: 'w-full h-full web:pointer-events-none' });
const actionsheetContentStyle = tva({
base: 'items-center rounded-tl-3xl rounded-tr-3xl p-5 pt-2 bg-background-0 web:pointer-events-auto web:select-none shadow-hard-5 border border-b-0 border-outline-100',
});
const actionsheetItemStyle = tva({
base: 'w-full flex-row items-center p-3 rounded-sm data-[disabled=true]:opacity-40 data-[disabled=true]:web:pointer-events-auto data-[disabled=true]:web:cursor-not-allowed hover:bg-background-50 active:bg-background-100 data-[focus=true]:bg-background-100 web:data-[focus-visible=true]:bg-background-100 web:data-[focus-visible=true]:outline-indicator-primary gap-2',
});
const actionsheetItemTextStyle = tva({
base: 'text-typography-700 font-normal font-body',
variants: {
isTruncated: {
true: '',
},
bold: {
true: 'font-bold',
},
underline: {
true: 'underline',
},
strikeThrough: {
true: 'line-through',
},
size: {
'2xs': 'text-2xs',
'xs': 'text-xs',
'sm': 'text-sm',
'md': 'text-base',
'lg': 'text-lg',
'xl': 'text-xl',
'2xl': 'text-2xl',
'3xl': 'text-3xl',
'4xl': 'text-4xl',
'5xl': 'text-5xl',
'6xl': 'text-6xl',
},
},
});
const actionsheetDragIndicatorStyle = tva({
base: 'w-16 h-1 bg-background-400 rounded-full',
});
const actionsheetDragIndicatorWrapperStyle = tva({
base: 'w-full py-1 items-center',
});
const actionsheetBackdropStyle = tva({
base: 'absolute left-0 top-0 right-0 bottom-0 bg-background-dark web:cursor-default web:pointer-events-auto',
});
const actionsheetScrollViewStyle = tva({
base: 'w-full h-auto',
});
const actionsheetVirtualizedListStyle = tva({
base: 'w-full h-auto',
});
const actionsheetFlatListStyle = tva({
base: 'w-full h-auto',
});
const actionsheetSectionListStyle = tva({
base: 'w-full h-auto',
});
const actionsheetSectionHeaderTextStyle = tva({
base: 'leading-5 font-bold font-heading my-0 text-typography-500 p-3 uppercase',
variants: {
isTruncated: {
true: '',
},
bold: {
true: 'font-bold',
},
underline: {
true: 'underline',
},
strikeThrough: {
true: 'line-through',
},
size: {
'5xl': 'text-5xl',
'4xl': 'text-4xl',
'3xl': 'text-3xl',
'2xl': 'text-2xl',
'xl': 'text-xl',
'lg': 'text-lg',
'md': 'text-base',
'sm': 'text-sm',
'xs': 'text-xs',
},
sub: {
true: 'text-xs',
},
italic: {
true: 'italic',
},
highlight: {
true: 'bg-yellow500',
},
},
defaultVariants: {
size: 'xs',
},
});
const actionsheetIconStyle = tva({
base: 'text-background-500 fill-none',
variants: {
size: {
'2xs': 'h-3 w-3',
'xs': 'h-3.5 w-3.5',
'sm': 'h-4 w-4',
'md': 'w-[18px] h-[18px]',
'lg': 'h-5 w-5',
'xl': 'h-6 w-6',
},
},
});
type IActionsheetProps = VariantProps<typeof actionsheetStyle> &
React.ComponentPropsWithoutRef<typeof UIActionsheet>;
type IActionsheetContentProps = VariantProps<typeof actionsheetContentStyle> &
React.ComponentPropsWithoutRef<typeof UIActionsheet.Content> & {
className?: string;
};
type IActionsheetItemProps = VariantProps<typeof actionsheetItemStyle> &
React.ComponentPropsWithoutRef<typeof UIActionsheet.Item>;
type IActionsheetItemTextProps = VariantProps<typeof actionsheetItemTextStyle> &
React.ComponentPropsWithoutRef<typeof UIActionsheet.ItemText>;
type IActionsheetDragIndicatorProps = VariantProps<
typeof actionsheetDragIndicatorStyle
> &
React.ComponentPropsWithoutRef<typeof UIActionsheet.DragIndicator>;
type IActionsheetDragIndicatorWrapperProps = VariantProps<
typeof actionsheetDragIndicatorWrapperStyle
> &
React.ComponentPropsWithoutRef<typeof UIActionsheet.DragIndicatorWrapper>;
type IActionsheetBackdropProps = VariantProps<typeof actionsheetBackdropStyle> &
React.ComponentPropsWithoutRef<typeof UIActionsheet.Backdrop> & {
className?: string;
};
type IActionsheetScrollViewProps = VariantProps<
typeof actionsheetScrollViewStyle
> &
React.ComponentPropsWithoutRef<typeof UIActionsheet.ScrollView>;
type IActionsheetVirtualizedListProps = VariantProps<
typeof actionsheetVirtualizedListStyle
> &
React.ComponentPropsWithoutRef<typeof UIActionsheet.VirtualizedList>;
type IActionsheetFlatListProps = VariantProps<typeof actionsheetFlatListStyle> &
React.ComponentPropsWithoutRef<typeof UIActionsheet.FlatList>;
type IActionsheetSectionListProps = VariantProps<
typeof actionsheetSectionListStyle
> &
React.ComponentPropsWithoutRef<typeof UIActionsheet.SectionList>;
type IActionsheetSectionHeaderTextProps = VariantProps<
typeof actionsheetSectionHeaderTextStyle
> &
React.ComponentPropsWithoutRef<typeof UIActionsheet.SectionHeaderText>;
type IActionsheetIconProps = VariantProps<typeof actionsheetIconStyle> &
React.ComponentPropsWithoutRef<typeof UIActionsheet.Icon> & {
className?: string;
as?: React.ElementType;
height?: number;
width?: number;
};
const Actionsheet = React.forwardRef<
React.ComponentRef<typeof UIActionsheet>,
IActionsheetProps
>(function Actionsheet({ className, ...props }, ref) {
return (
<UIActionsheet
className={actionsheetStyle({
class: className,
})}
ref={ref}
{...props}
/>
);
});
const ActionsheetContent = React.forwardRef<
React.ComponentRef<typeof UIActionsheet.Content>,
IActionsheetContentProps
>(function ActionsheetContent({ className, ...props }, ref) {
return (
<UIActionsheet.Content
className={actionsheetContentStyle({
class: className,
})}
ref={ref}
{...props}
/>
);
});
const ActionsheetItem = React.forwardRef<
React.ComponentRef<typeof UIActionsheet.Item>,
IActionsheetItemProps
>(function ActionsheetItem({ className, ...props }, ref) {
return (
<UIActionsheet.Item
className={actionsheetItemStyle({
class: className,
})}
ref={ref}
{...props}
/>
);
});
const ActionsheetItemText = React.forwardRef<
React.ComponentRef<typeof UIActionsheet.ItemText>,
IActionsheetItemTextProps
>(function ActionsheetItemText(
{
isTruncated,
bold,
underline,
strikeThrough,
size = 'sm',
className,
...props
},
ref
) {
return (
<UIActionsheet.ItemText
className={actionsheetItemTextStyle({
class: className,
isTruncated,
bold,
underline,
strikeThrough,
size,
})}
ref={ref}
{...props}
/>
);
});
const ActionsheetDragIndicator = React.forwardRef<
React.ComponentRef<typeof UIActionsheet.DragIndicator>,
IActionsheetDragIndicatorProps
>(function ActionsheetDragIndicator({ className, ...props }, ref) {
return (
<UIActionsheet.DragIndicator
className={actionsheetDragIndicatorStyle({
class: className,
})}
ref={ref}
{...props}
/>
);
});
const ActionsheetDragIndicatorWrapper = React.forwardRef<
React.ComponentRef<typeof UIActionsheet.DragIndicatorWrapper>,
IActionsheetDragIndicatorWrapperProps
>(function ActionsheetDragIndicatorWrapper({ className, ...props }, ref) {
return (
<UIActionsheet.DragIndicatorWrapper
className={actionsheetDragIndicatorWrapperStyle({
class: className,
})}
ref={ref}
{...props}
/>
);
});
const ActionsheetBackdrop = React.forwardRef<
React.ComponentRef<typeof UIActionsheet.Backdrop>,
IActionsheetBackdropProps
>(function ActionsheetBackdrop({ className, ...props }, ref) {
return (
<UIActionsheet.Backdrop
initial={{
opacity: 0,
}}
animate={{
opacity: 0.5,
}}
exit={{
opacity: 0,
}}
{...props}
className={actionsheetBackdropStyle({
class: className,
})}
ref={ref}
/>
);
});
const ActionsheetScrollView = React.forwardRef<
React.ComponentRef<typeof UIActionsheet.ScrollView>,
IActionsheetScrollViewProps
>(function ActionsheetScrollView({ className, ...props }, ref) {
return (
<UIActionsheet.ScrollView
className={actionsheetScrollViewStyle({
class: className,
})}
ref={ref}
{...props}
/>
);
});
const ActionsheetVirtualizedList = React.forwardRef<
React.ComponentRef<typeof UIActionsheet.VirtualizedList>,
IActionsheetVirtualizedListProps
>(function ActionsheetVirtualizedList({ className, ...props }, ref) {
return (
<UIActionsheet.VirtualizedList
className={actionsheetVirtualizedListStyle({
class: className,
})}
ref={ref}
{...props}
/>
);
});
const ActionsheetFlatList = React.forwardRef<
React.ComponentRef<typeof UIActionsheet.FlatList>,
IActionsheetFlatListProps
>(function ActionsheetFlatList({ className, ...props }, ref) {
return (
<UIActionsheet.FlatList
className={actionsheetFlatListStyle({
class: className,
})}
ref={ref}
{...props}
/>
);
});
const ActionsheetSectionList = React.forwardRef<
React.ComponentRef<typeof UIActionsheet.SectionList>,
IActionsheetSectionListProps
>(function ActionsheetSectionList({ className, ...props }, ref) {
return (
<UIActionsheet.SectionList
className={actionsheetSectionListStyle({
class: className,
})}
ref={ref}
{...props}
/>
);
});
const ActionsheetSectionHeaderText = React.forwardRef<
React.ComponentRef<typeof UIActionsheet.SectionHeaderText>,
IActionsheetSectionHeaderTextProps
>(function ActionsheetSectionHeaderText(
{
className,
isTruncated,
bold,
underline,
strikeThrough,
size,
sub,
italic,
highlight,
...props
},
ref
) {
return (
<UIActionsheet.SectionHeaderText
className={actionsheetSectionHeaderTextStyle({
class: className,
isTruncated,
bold,
underline,
strikeThrough,
size,
sub,
italic,
highlight,
})}
ref={ref}
{...props}
/>
);
});
const ActionsheetIcon = React.forwardRef<
React.ComponentRef<typeof UIActionsheet.Icon>,
IActionsheetIconProps
>(function ActionsheetIcon({ className, size = 'sm', ...props }, ref) {
if (typeof size === 'number') {
return (
<UIActionsheet.Icon
ref={ref}
{...props}
className={actionsheetIconStyle({ class: className })}
size={size}
/>
);
} else if (
(props.height !== undefined || props.width !== undefined) &&
size === undefined
) {
return (
<UIActionsheet.Icon
ref={ref}
{...props}
className={actionsheetIconStyle({ class: className })}
/>
);
}
return (
<UIActionsheet.Icon
className={actionsheetIconStyle({
class: className,
size,
})}
ref={ref}
{...props}
/>
);
});
export {
Actionsheet,
ActionsheetContent,
ActionsheetItem,
ActionsheetItemText,
ActionsheetDragIndicator,
ActionsheetDragIndicatorWrapper,
ActionsheetBackdrop,
ActionsheetScrollView,
ActionsheetVirtualizedList,
ActionsheetFlatList,
ActionsheetSectionList,
ActionsheetSectionHeaderText,
ActionsheetIcon,
};

View File

@@ -1704,7 +1704,9 @@
}
},
"node_modules/@expo/html-elements": {
"version": "0.4.3",
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/@expo/html-elements/-/html-elements-0.4.2.tgz",
"integrity": "sha512-lNioCgdtOrCMMqzHY+PCTdyuWBTU4yMBlOzPSkS4YFIWt9bq0zexM2ZJkpybTXmowNdE3zHO93xxAmiA2yDi2w==",
"license": "MIT"
},
"node_modules/@expo/image-utils": {
@@ -1999,6 +2001,8 @@
},
"node_modules/@gluestack-ui/actionsheet": {
"version": "0.2.53",
"resolved": "https://registry.npmjs.org/@gluestack-ui/actionsheet/-/actionsheet-0.2.53.tgz",
"integrity": "sha512-93qHvq6BHezJ7wt2lce4OQ38wXCGsDtglj5nlmwo2T41vj4ubOtDVoSUhXT+hfH0EmRr0TxFNeFqIgesO46qVw==",
"dependencies": {
"@gluestack-ui/hooks": "0.1.13",
"@gluestack-ui/overlay": "^0.1.22",
@@ -2434,12 +2438,6 @@
"react-native-web": ">=0.19"
}
},
"node_modules/@gluestack-ui/themed/node_modules/@expo/html-elements": {
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/@expo/html-elements/-/html-elements-0.12.5.tgz",
"integrity": "sha512-28KWO88YKykKU7ke5sEQs5TivFRMs1Aktz13xxgqAf5rTgb+lka0VKVt3W2fG7ksbUQ407rtUqz7SEAq298NvQ==",
"license": "MIT"
},
"node_modules/@gluestack-ui/toast": {
"version": "1.0.9",
"dependencies": {