Skip to content

Commit 5e868ec

Browse files
pager view in profile page
1 parent 820af72 commit 5e868ec

File tree

6 files changed

+144
-20
lines changed

6 files changed

+144
-20
lines changed

actions/users/me.ts

+25
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,31 @@ export async function myEvents(): Promise<{ results: Event[] }> {
4141
throw new Error(errorData.detail);
4242
}
4343

44+
const data = await response.json() as { results: Event[] };
45+
return data;
46+
}
47+
48+
export async function myPreviousEvents(): Promise<{ results: Event[] }> {
49+
const queryParams = new URLSearchParams({
50+
expired: "true",
51+
});
52+
53+
const url = `${BASE_URL}/users/me/events/?${queryParams}`;
54+
const token = await getToken();
55+
56+
const response = await fetch(url, {
57+
//@ts-expect-error
58+
headers: {
59+
"method": "GET",
60+
"X-Csrf-Token": token,
61+
}
62+
});
63+
64+
if (!response.ok) {
65+
const errorData = await response.json() as LeptonError;
66+
throw new Error(errorData.detail);
67+
}
68+
4469
const data = await response.json() as { results: Event[] };
4570
return data;
4671
}

app/(tabs)/profil/index.tsx

+32-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import me, { myEvents } from "@/actions/users/me";
1+
import me, { myEvents, myPreviousEvents } from "@/actions/users/me";
22
import { ThemeToggle } from "@/components/themeToggle";
33
import { Button } from "@/components/ui/button";
44
import EventCard from "@/components/ui/eventCard";
@@ -8,10 +8,16 @@ import { useAuth } from "@/context/auth";
88
import { deleteToken } from "@/lib/storage";
99
import { useQuery, UseQueryResult } from "@tanstack/react-query";
1010
import { useRouter } from "expo-router";
11-
import { Image, View } from "react-native";
11+
import { Image, ScrollView, View } from "react-native";
1212
import Toast from "react-native-toast-message";
1313
import { Event, Group } from "@/actions/types";
1414
import Icon from "@/lib/icons/Icon";
15+
import AnimatedPagerView from "@/components/ui/AnimatedPagerView";
16+
17+
//TODO: Foreløpig er react-native-pager-view broken... Det er ikke mulig å swipe mellom tabs
18+
// med mindre vi ofrer å vise noe innhold større en rundt 90vh. Forhåpenligvis fikses dette,
19+
// men i mellomtiden får vi ofre litt ux...
20+
// Vi kan også bare... lage en helt egen pager view med reanimated.
1521

1622
export default function Profil() {
1723
const { setAuthState } = useAuth();
@@ -27,6 +33,11 @@ export default function Profil() {
2733
queryFn: myEvents,
2834
});
2935

36+
const previousEvents = useQuery({
37+
queryKey: ["users", "me", "previous-events"],
38+
queryFn: myPreviousEvents,
39+
})
40+
3041
const getStudyYearAsClass = (studyYear: Group, study: Group): string => {
3142
const studyyear = Number(studyYear.name);
3243
const currentYear = new Date().getFullYear();
@@ -107,17 +118,8 @@ export default function Profil() {
107118
</Button>
108119

109120
<ThemeToggle className="flex-1 min-h-full" />
110-
111-
<Button
112-
className="flex-1 min-h-full"
113-
variant="default"
114-
>
115-
<Text>
116-
<Icon icon="Settings">
117-
118-
</Icon>
119-
</Text>
120-
</Button>
121+
</View>
122+
<View className="flex flex-row gap-4 w-full h-16">
121123
<Button
122124
className="flex-1 min-h-full"
123125
variant="destructive"
@@ -128,15 +130,28 @@ export default function Profil() {
128130
</Text>
129131
</Button>
130132
</View>
131-
<Text className="text-2xl mt-4 font-semibold">Dine arrangementer</Text>
132-
<DisplayUserEvents userEvents={userEvents} />
133+
<View className="my-2 border-t border-muted-foreground mx-8" />
134+
{!userEvents.isPending && !previousEvents.isPending &&
135+
<AnimatedPagerView titles={["Dine arrangementer", "Tidligere arrangementer"]} >
136+
<View key={0} className="max-h-[45vh]">
137+
<ScrollView bounces={false} nestedScrollEnabled>
138+
<DisplayUserEvents userEvents={userEvents} />
139+
</ScrollView>
140+
</View>
141+
<View key={1} className="max-h-[45vh]">
142+
<ScrollView bounces={false} nestedScrollEnabled>
143+
<DisplayUserEvents userEvents={previousEvents} previous />
144+
</ScrollView>
145+
</View>
146+
</AnimatedPagerView>
147+
}
133148
</View>
134149
</PageWrapper>
135150
);
136151
}
137152

138153

139-
function DisplayUserEvents({ userEvents }: { userEvents: UseQueryResult<{ results: Event[] }, Error> }) {
154+
function DisplayUserEvents({ userEvents, previous }: { userEvents: UseQueryResult<{ results: Event[] }, Error>, previous?: boolean }) {
140155
const router = useRouter();
141156

142157
if (userEvents.isPending) {
@@ -148,7 +163,7 @@ function DisplayUserEvents({ userEvents }: { userEvents: UseQueryResult<{ result
148163
}
149164

150165
if (userEvents.data.results.length === 0) {
151-
return <Text>Du er ikke påmeldt noen arrangementer.</Text>
166+
return <Text className="text-center h-fit">{previous ? "Du har ikke deltatt på noen arrangementer" : "Du er ikke påmeldt noen arrangementer."}</Text>
152167
}
153168

154169
return userEvents.data.results.map((event) => (

components/ui/AnimatedPagerView.tsx

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
2+
import { Children, useEffect, useRef, useState } from 'react';
3+
import { Pressable, View } from 'react-native';
4+
import PagerView from 'react-native-pager-view';
5+
import Animated, { useSharedValue, withSpring } from 'react-native-reanimated';
6+
import { Text } from './text';
7+
8+
9+
interface AnimatedPagerViewProps {
10+
children: React.ReactNode;
11+
titles: string[];
12+
className?: string;
13+
}
14+
15+
//TODO: lag en ny pager view som fungerer, gjerne uten react-native-pager-view
16+
// vurdere evt å lage en issue på react-native-pager-view men virker som at
17+
// de folka er jævlig treige på å fikse ting
18+
19+
export default function AnimatedPagerView(props: AnimatedPagerViewProps) {
20+
const xpos = useSharedValue(0);
21+
const outerRef = useRef<View>(null);
22+
const pagerViewRef = useRef<PagerView>(null);
23+
const [width, setWidth] = useState(0);
24+
25+
const numberOfPages = Children.count(props.children);
26+
27+
useEffect(() => {
28+
if (outerRef.current) {
29+
outerRef.current.measure((x, y, w, h) => {
30+
setWidth(w);
31+
});
32+
}
33+
}, [outerRef.current]);
34+
35+
const handleScroll = (e) => {
36+
xpos.value = (e.nativeEvent.offset + e.nativeEvent.position) * (width / numberOfPages)
37+
};
38+
39+
const scrollIndicatorWidth = 100 / numberOfPages;
40+
41+
return (
42+
<View className={props.className} ref={outerRef} >
43+
<View className="flex-row w-full justify-center">
44+
{props.titles.map((title, index) => {
45+
return (
46+
47+
<Pressable className="p-2 flex-1 active:bg-accent rounded-lg" key={index}
48+
onPress={() => requestAnimationFrame(() => pagerViewRef.current?.setPage(index))}>
49+
<Text className="text-lg w-full text-center">{title}</Text>
50+
</Pressable>
51+
)
52+
})
53+
}
54+
</View>
55+
<Animated.View className="mb-4" style={{
56+
marginLeft: xpos,
57+
width: scrollIndicatorWidth + "%",
58+
}}>
59+
<View className="h-0.5 rounded-full bg-foreground mx-8" />
60+
</Animated.View>
61+
<PagerView style={{ flex: 1 }}
62+
onPageScroll={handleScroll}
63+
orientation="horizontal"
64+
ref={pagerViewRef}
65+
overdrag={true}
66+
>
67+
{props.children}
68+
</PagerView>
69+
</View>
70+
)
71+
}

components/ui/pagewrapper.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export default function PageWrapper({ children, refreshQueryKey, className }: Pa
1717
if (!refreshQueryKey) {
1818
return (
1919
<SafeAreaWrapper>
20-
<ScrollView className={cn("min-h-full", className ?? "")}>
20+
<ScrollView className={cn("min-h-full", className ?? "")} nestedScrollEnabled>
2121
{children}
2222
</ScrollView>
2323
</SafeAreaWrapper>
@@ -56,6 +56,7 @@ export default function PageWrapper({ children, refreshQueryKey, className }: Pa
5656
<RefreshControl refreshing={isRefreshing} onRefresh={handleRefresh} />
5757
}
5858
className={cn("min-h-full", className ?? "")}
59+
nestedScrollEnabled
5960
>
6061
{children}
6162
</ScrollView>

package-lock.json

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@
5757
"react-native-webview": "13.12.5",
5858
"tailwind-merge": "^2.6.0",
5959
"tailwindcss": "^3.4.16",
60-
"tailwindcss-animate": "^1.0.7"
60+
"tailwindcss-animate": "^1.0.7",
61+
"react-native-pager-view": "7.0.0-rc.0"
6162
},
6263
"devDependencies": {
6364
"@babel/core": "^7.25.2",
@@ -70,4 +71,4 @@
7071
"typescript": "^5.3.3"
7172
},
7273
"private": true
73-
}
74+
}

0 commit comments

Comments
 (0)